]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #49906 - kennytm:stable-unreachable, r=sfackler
authorkennytm <kennytm@gmail.com>
Tue, 24 Apr 2018 03:57:04 +0000 (11:57 +0800)
committerGitHub <noreply@github.com>
Tue, 24 Apr 2018 03:57:04 +0000 (11:57 +0800)
Stabilize `std::hint::unreachable_unchecked`.

Closes #43751.

652 files changed:
CONTRIBUTING.md
config.toml.example
src/Cargo.lock
src/bootstrap/builder.rs
src/bootstrap/cc_detect.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/install.rs
src/bootstrap/native.rs
src/bootstrap/sanity.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/bootstrap/util.rs
src/ci/docker/wasm32-unknown/Dockerfile
src/doc/rustdoc/src/documentation-tests.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/language-features/doc-alias.md [new file with mode: 0644]
src/doc/unstable-book/src/library-features/slice-rsplit.md [deleted file]
src/liballoc/alloc.rs
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/btree/map.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/liballoc/linked_list.rs
src/liballoc/raw_vec.rs
src/liballoc/rc.rs
src/liballoc/slice.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/liballoc/tests/str.rs
src/liballoc/vec.rs
src/liballoc/vec_deque.rs
src/liballoc_jemalloc/Cargo.toml
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libarena/Cargo.toml
src/libarena/lib.rs
src/libcore/alloc.rs
src/libcore/array.rs
src/libcore/cell.rs
src/libcore/char/convert.rs
src/libcore/char/mod.rs
src/libcore/clone.rs
src/libcore/cmp.rs
src/libcore/convert.rs
src/libcore/fmt/mod.rs
src/libcore/internal_macros.rs
src/libcore/iter/iterator.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/mod.rs
src/libcore/ops/arith.rs
src/libcore/ops/bit.rs
src/libcore/ops/index.rs
src/libcore/ops/range.rs
src/libcore/ops/try.rs
src/libcore/panic.rs
src/libcore/prelude/v1.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs
src/libcore/sync/atomic.rs
src/libcore/tests/cell.rs
src/libcore/tests/lib.rs
src/libcore/time.rs
src/libpanic_abort/lib.rs
src/libpanic_unwind/lib.rs
src/libproc_macro/quote.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_cstore.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/mod.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/middle/cstore.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/mod.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/job.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/sty.rs
src/librustc_allocator/expand.rs
src/librustc_allocator/lib.rs
src/librustc_apfloat/lib.rs
src/librustc_back/target/android_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_data_structures/array_vec.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/persist/save.rs
src/librustc_llvm/build.rs
src/librustc_metadata/astencode.rs [deleted file]
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/isolated_encoder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check/borrow_set.rs [new file with mode: 0644]
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/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/values.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/nll/universal_regions.rs
src/librustc_mir/borrow_check/place_ext.rs [new file with mode: 0644]
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_traits/lowering.rs
src/librustc_trans/allocator.rs
src/librustc_trans/attributes.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/base.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/lib.rs
src/librustc_trans/llvm_util.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/mir/operand.rs
src/librustc_trans_utils/trans_crate.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/item_type.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/settings.css [new file with mode: 0644]
src/librustdoc/html/static/settings.js [new file with mode: 0644]
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/html/static/wheel.svg [new file with mode: 0644]
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/libstd/alloc.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/table.rs
src/libstd/error.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/ffi/os_str.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/os/android/fs.rs
src/libstd/os/bitrig/fs.rs
src/libstd/os/dragonfly/fs.rs
src/libstd/os/emscripten/fs.rs
src/libstd/os/freebsd/fs.rs
src/libstd/os/fuchsia/fs.rs
src/libstd/os/haiku/fs.rs
src/libstd/os/ios/fs.rs
src/libstd/os/linux/fs.rs
src/libstd/os/macos/fs.rs
src/libstd/os/netbsd/fs.rs
src/libstd/os/openbsd/fs.rs
src/libstd/os/solaris/fs.rs
src/libstd/panicking.rs
src/libstd/path.rs
src/libstd/primitive_docs.rs
src/libstd/process.rs
src/libstd/sys/cloudabi/stdio.rs
src/libstd/sys/redox/ext/ffi.rs
src/libstd/sys/redox/ext/fs.rs
src/libstd/sys/redox/ext/process.rs
src/libstd/sys/redox/ext/thread.rs
src/libstd/sys/redox/stdio.rs
src/libstd/sys/unix/ext/ffi.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/ext/process.rs
src/libstd/sys/unix/ext/thread.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/stdio.rs
src/libstd/sys/wasm/rwlock.rs
src/libstd/sys/wasm/stdio.rs
src/libstd/sys/windows/ext/ffi.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/ext/process.rs
src/libstd/sys/windows/mutex.rs
src/libstd/sys/windows/stdio.rs
src/libstd/sys_common/backtrace.rs
src/libstd/sys_common/mod.rs
src/libstd/sys_common/thread_local.rs
src/libstd/sys_common/util.rs
src/libstd/sys_common/wtf8.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/libsyntax/edition.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/tokenstream.rs
src/libsyntax_pos/hygiene.rs
src/libsyntax_pos/symbol.rs
src/libtest/lib.rs
src/libunwind/macros.rs
src/rustc/rustc.rs
src/stdsimd
src/test/codegen/nounwind.rs
src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs
src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs
src/test/compile-fail-fulldeps/proc-macro/attribute-with-error.rs
src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs [new file with mode: 0644]
src/test/compile-fail/E0501.rs
src/test/compile-fail/allocator/not-an-allocator.rs
src/test/compile-fail/borrowck/borrowck-asm.rs
src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs
src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs
src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs
src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs
src/test/compile-fail/borrowck/borrowck-union-borrow.rs
src/test/compile-fail/borrowck/two-phase-across-loop.rs [new file with mode: 0644]
src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs
src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs
src/test/compile-fail/borrowck/two-phase-cannot-nest-mut-self-calls.rs
src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs
src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference-2.rs
src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
src/test/compile-fail/borrowck/two-phase-sneaky.rs
src/test/compile-fail/call-fn-never-arg-wrong-type.rs
src/test/compile-fail/coerce-overloaded-autoderef.rs
src/test/compile-fail/coerce-to-bang-cast.rs
src/test/compile-fail/coerce-to-bang.rs
src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs
src/test/compile-fail/const-size_of-cycle.rs
src/test/compile-fail/cycle-projection-based-on-where-clause.rs
src/test/compile-fail/cycle-trait-default-type-trait.rs
src/test/compile-fail/cycle-trait-supertrait-direct.rs
src/test/compile-fail/defaulted-never-note.rs
src/test/compile-fail/edition-raw-pointer-method-2015.rs
src/test/compile-fail/edition-raw-pointer-method-2018.rs
src/test/compile-fail/extern-macro.rs
src/test/compile-fail/hrtb-identity-fn-borrows.rs
src/test/compile-fail/infinite-vec-type-recursion.rs
src/test/compile-fail/inhabitedness-infinite-loop.rs
src/test/compile-fail/issue-20772.rs
src/test/compile-fail/issue-20825.rs
src/test/compile-fail/issue-21177.rs
src/test/compile-fail/issue-22673.rs
src/test/compile-fail/issue-26548.rs
src/test/compile-fail/issue-34373.rs
src/test/compile-fail/issue-36082.rs
src/test/compile-fail/issue-43105.rs
src/test/compile-fail/issue-44415.rs
src/test/compile-fail/issue-44578.rs [deleted file]
src/test/compile-fail/issue32829.rs
src/test/compile-fail/loop-break-value.rs
src/test/compile-fail/macro-with-seps-err-msg.rs
src/test/compile-fail/macros-nonfatal-errors.rs
src/test/compile-fail/match-privately-empty.rs
src/test/compile-fail/mir_check_cast_closure.rs
src/test/compile-fail/mir_check_cast_reify.rs
src/test/compile-fail/mir_check_cast_unsafe_fn.rs
src/test/compile-fail/mir_check_cast_unsize.rs
src/test/compile-fail/mut-pattern-internal-mutability.rs
src/test/compile-fail/never-assign-dead-code.rs
src/test/compile-fail/never-assign-wrong-type.rs
src/test/compile-fail/nll/loan_ends_mid_block_pair.rs
src/test/compile-fail/nll/loan_ends_mid_block_vec.rs
src/test/compile-fail/nll/reference-carried-through-struct-field.rs
src/test/compile-fail/nll/region-ends-after-if-condition.rs
src/test/compile-fail/nll/return_from_loop.rs
src/test/compile-fail/nll/where_clauses_in_functions.rs
src/test/compile-fail/nll/where_clauses_in_structs.rs
src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
src/test/compile-fail/privacy/associated-item-privacy-trait.rs
src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
src/test/compile-fail/private-inferred-type-3.rs
src/test/compile-fail/private-inferred-type.rs
src/test/compile-fail/regions-pattern-typing-issue-19997.rs
src/test/compile-fail/regions-static-bound.rs
src/test/compile-fail/resolve-self-in-impl.rs
src/test/compile-fail/single-primitive-inherent-impl.rs
src/test/compile-fail/uninhabited-irrefutable.rs
src/test/compile-fail/uninhabited-patterns.rs
src/test/compile-fail/unreachable-loop-patterns.rs
src/test/compile-fail/unreachable-try-pattern.rs
src/test/mir-opt/nll/liveness-call-subtlety.rs
src/test/mir-opt/nll/liveness-drop-intra-block.rs
src/test/mir-opt/nll/liveness-interblock.rs
src/test/mir-opt/nll/named-lifetimes-basic.rs
src/test/mir-opt/nll/reborrow-basic.rs
src/test/mir-opt/nll/region-liveness-basic.rs
src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
src/test/mir-opt/nll/region-subtyping-basic.rs
src/test/parse-fail/obsolete-proc.rs [deleted file]
src/test/run-fail/adjust_never.rs
src/test/run-fail/call-fn-never-arg.rs
src/test/run-fail/cast-never.rs
src/test/run-fail/never-associated-type.rs
src/test/run-fail/never-type-arg.rs
src/test/run-make/wasm-panic-small/Makefile [new file with mode: 0644]
src/test/run-make/wasm-panic-small/foo.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/hello_macro.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/macro-quote-cond.rs
src/test/run-pass-fulldeps/macro-quote-test.rs
src/test/run-pass-fulldeps/proc-macro/attr-args.rs
src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs
src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/bang-macro.rs
src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/derive-b.rs
src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs
src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
src/test/run-pass-fulldeps/proc-macro/issue-50061.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/negative-token.rs
src/test/run-pass-fulldeps/proc_macro.rs
src/test/run-pass/allocator-alloc-one.rs
src/test/run-pass/borrowck/two-phase-baseline.rs
src/test/run-pass/diverging-fallback-control-flow.rs
src/test/run-pass/empty-types-in-patterns.rs
src/test/run-pass/hygiene/issue-47311.rs
src/test/run-pass/hygiene/issue-47312.rs
src/test/run-pass/hygiene/legacy_interaction.rs
src/test/run-pass/hygiene/lexical.rs
src/test/run-pass/hygiene/wrap_unhygienic_example.rs
src/test/run-pass/hygiene/xcrate.rs
src/test/run-pass/impl-for-never.rs
src/test/run-pass/impl-trait/example-calendar.rs
src/test/run-pass/issue-16819.rs
src/test/run-pass/issue-44402.rs
src/test/run-pass/issue-49973.rs [new file with mode: 0644]
src/test/run-pass/loop-break-value.rs
src/test/run-pass/mir_calls_to_shims.rs
src/test/run-pass/never-result.rs
src/test/run-pass/paths-in-macro-invocations.rs
src/test/run-pass/realloc-16687.rs
src/test/run-pass/regions-mock-trans.rs
src/test/run-pass/simd-target-feature-mixup.rs
src/test/run-pass/type-sizes.rs
src/test/rustdoc-js/alias-1.js [new file with mode: 0644]
src/test/rustdoc-js/alias-2.js [new file with mode: 0644]
src/test/rustdoc-js/alias-3.js [new file with mode: 0644]
src/test/rustdoc-js/alias.js [new file with mode: 0644]
src/test/rustdoc-js/multi-query.js [new file with mode: 0644]
src/test/rustdoc-js/never.js [new file with mode: 0644]
src/test/rustdoc-ui/intra-links-warning.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-links-warning.stderr [new file with mode: 0644]
src/test/rustdoc/all.rs
src/test/rustdoc/issue-23511.rs
src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
src/test/ui-fulldeps/proc-macro/three-equals.rs
src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs
src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr
src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr [deleted file]
src/test/ui/borrowck/borrowck-closures-two-mut.rs
src/test/ui/borrowck/borrowck-closures-two-mut.stderr
src/test/ui/borrowck/issue-45983.nll.stderr
src/test/ui/borrowck/issue-7573.nll.stderr
src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr
src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr
src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr
src/test/ui/borrowck/two-phase-method-receivers.rs
src/test/ui/borrowck/two-phase-multiple-activations.rs
src/test/ui/chalkify/lower_impl.rs
src/test/ui/chalkify/lower_impl.stderr
src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr
src/test/ui/const-eval/conditional_array_execution.rs
src/test/ui/const-eval/conditional_array_execution.stderr
src/test/ui/const-eval/const_signed_pat.rs [new file with mode: 0644]
src/test/ui/const-eval/issue-43197.rs
src/test/ui/const-eval/issue-43197.stderr
src/test/ui/const-eval/issue-44578.rs [new file with mode: 0644]
src/test/ui/const-eval/issue-44578.stderr [new file with mode: 0644]
src/test/ui/const-eval/promoted_errors.rs [new file with mode: 0644]
src/test/ui/const-eval/promoted_errors.stderr [new file with mode: 0644]
src/test/ui/const-fn-error.stderr
src/test/ui/cycle-trait-supertrait-indirect.rs
src/test/ui/cycle-trait-supertrait-indirect.stderr
src/test/ui/did_you_mean/issue-34126.nll.stderr
src/test/ui/did_you_mean/issue-35937.nll.stderr
src/test/ui/did_you_mean/issue-38147-1.nll.stderr
src/test/ui/did_you_mean/issue-38147-4.nll.stderr
src/test/ui/did_you_mean/issue-39544.nll.stderr
src/test/ui/e0119/conflict-with-std.rs
src/test/ui/e0119/conflict-with-std.stderr
src/test/ui/error-codes/E0389.nll.stderr
src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr
src/test/ui/feature-gate-cfg-target-feature.rs [deleted file]
src/test/ui/feature-gate-cfg-target-feature.stderr [deleted file]
src/test/ui/feature-gate-doc_alias.rs [new file with mode: 0644]
src/test/ui/feature-gate-doc_alias.stderr [new file with mode: 0644]
src/test/ui/feature-gate-exhaustive-patterns.rs
src/test/ui/feature-gate-generic_associated_types.rs
src/test/ui/feature-gate-generic_associated_types.stderr
src/test/ui/feature-gate-never_type.rs [new file with mode: 0644]
src/test/ui/feature-gate-never_type.stderr [new file with mode: 0644]
src/test/ui/feature-gate-target_feature.rs [deleted file]
src/test/ui/feature-gate-target_feature.stderr [deleted file]
src/test/ui/hygiene/fields-move.nll.stderr [new file with mode: 0644]
src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr [new file with mode: 0644]
src/test/ui/hygiene/fields-numeric-borrowck.rs
src/test/ui/hygiene/fields.rs
src/test/ui/hygiene/globs.rs
src/test/ui/hygiene/impl_items.rs
src/test/ui/hygiene/intercrate.rs
src/test/ui/hygiene/no_implicit_prelude.rs
src/test/ui/hygiene/privacy.rs
src/test/ui/hygiene/trait_items.rs
src/test/ui/impl-trait/auto-trait-leak.rs
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
src/test/ui/imports/macro-paths.rs
src/test/ui/imports/shadow_builtin_macros.rs
src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
src/test/ui/in-band-lifetimes/mismatched.nll.stderr
src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr
src/test/ui/issue-12511.rs
src/test/ui/issue-12511.stderr
src/test/ui/issue-13058.nll.stderr
src/test/ui/issue-23302-1.stderr
src/test/ui/issue-23302-2.stderr
src/test/ui/issue-23302-3.rs
src/test/ui/issue-23302-3.stderr
src/test/ui/issue-36163.stderr
src/test/ui/issue-36400.nll.stderr
src/test/ui/issue-45697-1.nll.stderr [deleted file]
src/test/ui/issue-45697-1.rs
src/test/ui/issue-45697-1.stderr
src/test/ui/issue-45697.rs
src/test/ui/issue-45697.stderr
src/test/ui/issue-46471-1.nll.stderr [deleted file]
src/test/ui/issue-46471-1.stderr
src/test/ui/issue-48636.rs [new file with mode: 0644]
src/test/ui/issue-48636.stderr [new file with mode: 0644]
src/test/ui/issue-49851/compiler-builtins-error.rs [new file with mode: 0644]
src/test/ui/issue-49851/compiler-builtins-error.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr
src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr
src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr
src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr
src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr
src/test/ui/macros/macro-backtrace-invalid-internals.rs
src/test/ui/macros/macro-backtrace-invalid-internals.stderr
src/test/ui/mir_check_nonconst.rs [new file with mode: 0644]
src/test/ui/mir_check_nonconst.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument-callee.rs
src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
src/test/ui/nll/closure-requirements/escape-argument.rs
src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs
src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
src/test/ui/nll/constant.rs
src/test/ui/nll/drop-may-dangle.rs
src/test/ui/nll/drop-no-may-dangle.rs
src/test/ui/nll/get_default.rs
src/test/ui/nll/issue-47388.stderr
src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
src/test/ui/nll/maybe-initialized-drop.rs
src/test/ui/nll/projection-return.rs
src/test/ui/nll/ty-outlives/impl-trait-captures.rs
src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
src/test/ui/nll/ty-outlives/projection-implied-bounds.rs
src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
src/test/ui/nll/ty-outlives/ty-param-fn.rs
src/test/ui/nll/ty-outlives/ty-param-fn.stderr
src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
src/test/ui/print_type_sizes/uninhabited.rs
src/test/ui/reachable/expr_add.rs
src/test/ui/reachable/expr_assign.rs
src/test/ui/reachable/expr_call.rs
src/test/ui/reachable/expr_cast.rs
src/test/ui/reachable/expr_method.rs
src/test/ui/reachable/expr_type.rs
src/test/ui/reachable/expr_unary.rs
src/test/ui/resolve/issue-23305.rs
src/test/ui/resolve/issue-23305.stderr
src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr
src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
src/test/ui/span/borrowck-object-mutability.nll.stderr
src/test/ui/span/destructor-restrictions.nll.stderr
src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
src/test/ui/span/dropck_vec_cycle_checked.rs
src/test/ui/span/dropck_vec_cycle_checked.stderr
src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
src/test/ui/span/wf-method-late-bound-regions.nll.stderr
src/test/ui/span/wf-method-late-bound-regions.rs
src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
src/test/ui/target-feature-gate.rs [new file with mode: 0644]
src/test/ui/target-feature-gate.stderr [new file with mode: 0644]
src/test/ui/target-feature-wrong.rs
src/test/ui/target-feature-wrong.stderr
src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
src/test/ui/update-references.sh
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/rustbook/Cargo.toml
src/tools/rustdoc-js/tester.js
src/tools/rustfmt
src/tools/tidy/src/ui_tests.rs

index 7a62405f059677affac001298e8f5fd2f9dbe515..c5dd3cd720548c8ea1ca9a3b7b3035ac099d7df8 100644 (file)
@@ -121,6 +121,7 @@ configuration used in the build process. Some options to note:
 #### `[rust]`:
 - `debuginfo = true` - Build a compiler with debuginfo. Makes building rustc slower, but then you can use a debugger to debug `rustc`.
 - `debuginfo-lines = true` - An alternative to `debuginfo = true` that doesn't let you use a debugger, but doesn't make building rustc slower and still gives you line numbers in backtraces.
+- `debuginfo-tools = true` - Build the extended tools with debuginfo.
 - `debug-assertions = true` - Makes the log output of `debug!` work.
 - `optimize = false` - Disable optimizations to speed up compilation of stage1 rust, but makes the stage1 compiler x100 slower.
 
@@ -135,6 +136,8 @@ file. If you still have a `config.mk` file in your directory - from
 ### Building
 [building]: #building
 
+A default configuration shall use around 3.5 GB of disk space, whereas building a debug configuration may require more than 30 GB.
+
 Dependencies
 - [build dependencies](README.md#building-from-source)
 - `gdb` 6.2.0 minimum, 7.1 or later recommended for test builds
index 68bc7dfe720fe11f20313c299b4dc4bc44318b5d..effe00843810da1dcd993bfc48ec00f6df6e288c 100644 (file)
 # standard library.
 #debuginfo-only-std = false
 
+# Enable debuginfo for the extended tools: cargo, rls, rustfmt
+# Adding debuginfo makes them several times larger.
+#debuginfo-tools = false
+
 # Whether or not jemalloc is built and enabled
 #use-jemalloc = true
 
index daa8d0dc84cea5dda67d7daaa89befd03dc82e01..d60a8689f3da13dc7a7f418697f61704834ee459 100644 (file)
@@ -19,9 +19,8 @@ dependencies = [
 name = "alloc_jemalloc"
 version = "0.0.0"
 dependencies = [
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
@@ -66,6 +65,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "arena"
 version = "0.0.0"
+dependencies = [
+ "rustc_data_structures 0.0.0",
+]
 
 [[package]]
 name = "arrayvec"
@@ -87,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "backtrace"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -102,7 +104,7 @@ name = "backtrace-sys"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -130,8 +132,8 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -139,11 +141,11 @@ dependencies = [
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -159,9 +161,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -175,7 +177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cargo"
-version = "0.27.0"
+version = "0.28.0"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -184,10 +186,10 @@ dependencies = [
  "crates-io 0.16.0",
  "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -207,15 +209,15 @@ dependencies = [
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -225,9 +227,9 @@ name = "cargo_metadata"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -237,9 +239,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -248,7 +250,7 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -283,18 +285,18 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.0.193"
+version = "0.0.195"
 dependencies = [
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
- "clippy_lints 0.0.193",
+ "clippy_lints 0.0.195",
  "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -304,6 +306,26 @@ version = "0.2.0"
 [[package]]
 name = "clippy_lints"
 version = "0.0.193"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "clippy_lints"
+version = "0.0.195"
 dependencies = [
  "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -311,21 +333,21 @@ dependencies = [
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cmake"
-version = "0.1.29"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -348,7 +370,7 @@ dependencies = [
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -357,16 +379,16 @@ name = "compiletest"
 version = "0.0.0"
 dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -381,10 +403,10 @@ dependencies = [
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -420,11 +442,11 @@ dependencies = [
 name = "crates-io"
 version = "0.16.0"
 dependencies = [
- "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -471,36 +493,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "curl"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.2 (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.40 (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.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "curl-sys"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -556,16 +578,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "elasticlunr-rs"
-version = "1.0.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -591,7 +613,7 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.5.6"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -606,7 +628,7 @@ name = "error-chain"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -621,7 +643,7 @@ name = "failure"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -649,6 +671,16 @@ dependencies = [
  "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "filetime"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "find_all_refs_no_cfg_test"
 version = "0.1.0"
@@ -745,7 +777,7 @@ dependencies = [
  "libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (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.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -754,7 +786,7 @@ name = "git2-curl"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -792,8 +824,8 @@ dependencies = [
  "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -884,7 +916,7 @@ dependencies = [
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -930,9 +962,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -950,9 +982,9 @@ version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -990,13 +1022,13 @@ name = "libgit2-sys"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1005,10 +1037,10 @@ name = "libssh2-sys"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1017,10 +1049,10 @@ name = "libz-sys"
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1056,7 +1088,7 @@ name = "lzma-sys"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1079,9 +1111,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1094,14 +1126,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.1.5"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "elasticlunr-rs 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1111,12 +1143,12 @@ dependencies = [
  "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1138,7 +1170,7 @@ name = "miniz-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1147,7 +1179,7 @@ name = "miow"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1212,14 +1244,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl"
-version = "0.10.5"
+version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1229,13 +1261,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.27"
+version = "0.9.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1383,7 +1415,7 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "0.3.1"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1403,7 +1435,7 @@ dependencies = [
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -1445,7 +1477,7 @@ name = "quote"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1454,7 +1486,7 @@ version = "2.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1540,14 +1572,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.5.3"
+version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1563,7 +1595,7 @@ version = "0.1.0"
 
 [[package]]
 name = "remove_dir_all"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1573,10 +1605,10 @@ dependencies = [
 name = "rls"
 version = "0.126.0"
 dependencies = [
- "cargo 0.27.0",
+ "cargo 0.28.0",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "clippy_lints 0.0.193",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy_lints 0.0.193 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1593,9 +1625,9 @@ dependencies = [
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustfmt-nightly 0.4.2",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1624,8 +1656,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1639,8 +1671,8 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1657,7 +1689,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1665,7 +1697,7 @@ name = "rustc"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1688,7 +1720,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "98.0.0"
+version = "103.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1697,7 +1729,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "98.0.0"
+version = "103.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1705,20 +1737,20 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "98.0.0"
+version = "103.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1726,32 +1758,32 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "98.0.0"
+version = "103.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "98.0.0"
+version = "103.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "98.0.0"
+version = "103.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1800,7 +1832,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -1864,7 +1896,7 @@ version = "0.0.0"
 dependencies = [
  "ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "arena 0.0.0",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -1934,7 +1966,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
 ]
@@ -1946,7 +1978,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -1996,7 +2028,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -2087,8 +2119,8 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2136,7 +2168,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -2183,19 +2215,19 @@ dependencies = [
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2210,7 +2242,7 @@ dependencies = [
 
 [[package]]
 name = "schannel"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2233,7 +2265,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2243,26 +2275,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_derive_internals"
-version = "0.23.0"
+version = "0.23.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2271,18 +2303,18 @@ name = "serde_ignored"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.13"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2311,7 +2343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "socket2"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2364,7 +2396,7 @@ dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2390,6 +2422,20 @@ name = "strsim"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "strum"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "strum_macros"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "syn"
 version = "0.11.11"
@@ -2415,7 +2461,7 @@ name = "syn"
 version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2511,13 +2557,13 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.14"
+version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xattr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2526,18 +2572,18 @@ version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tempfile"
-version = "3.0.0"
+version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2620,9 +2666,9 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2645,10 +2691,10 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2660,7 +2706,7 @@ dependencies = [
  "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2754,7 +2800,7 @@ name = "url_serde"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2779,7 +2825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "vcpkg"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2844,7 +2890,7 @@ version = "0.1.0"
 
 [[package]]
 name = "xattr"
-version = "0.1.11"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2870,7 +2916,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
 "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
-"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
+"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e"
 "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
@@ -2879,11 +2925,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
 "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
 "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3"
-"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc"
+"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5f60682a4c264e7f8d77b82e7788938a76befdf949d4a98026d19099c9d873"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
-"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
+"checksum clippy_lints 0.0.193 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6358b7e2e0c99c24ea88edc43c5fe1638f186255adb92d2302ae71027560f"
+"checksum cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5cf678ceebedde428000cb3a34465cf3606d1a48da17014948a916deac39da7c"
 "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
 "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
 "checksum compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "608d9d3ccc45b63bf337d2ff5e65def5a5a52c187122232509f6b72707f61b1b"
@@ -2894,23 +2941,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
-"checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e"
-"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
+"checksum curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf20bbe084f285f215eef2165feed70d6b75ba29cad24469badb853a4a287d0"
+"checksum curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f7738d877ec81040305d5bb91976ac594f564f5e455dc02a29a23c1d00fe6f"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
-"checksum elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19ab5f8db0ffb76b5d87454566ceb502c3650e29057c053f93e884d3b884e344"
+"checksum elasticlunr-rs 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4511b63d69dd5d31e8e29aed2c132c413f87acea8035d0584801feaab9dd1f0f"
 "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
 "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
-"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
+"checksum env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "be27f8ea102a7182093a80d98f0b78623b580eda8791cbe8e2345fe6e57567a6"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
 "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
 "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
+"checksum filetime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08530a39af0bd442c40aabb9e854f442a83bd2403feb1ed58fbe982dec2385f3"
 "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
@@ -2957,7 +3005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "326d0861da5681a13c19a00952a56c254dd04f00eb944e506fdb36e93ae6f1ca"
+"checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
@@ -2969,9 +3017,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364"
 "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
 "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
-"checksum openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1636c9f1d78af9cbcc50e523bfff4a30274108aad5e86761afd4d31e4e184fa7"
+"checksum openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)" = "63246f69962e8d5ef865f82a65241d6483c8a2905a1801e2f7feb5d187d51320"
 "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9"
+"checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
@@ -2988,7 +3036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
 "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
-"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786"
+"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
 "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
@@ -3004,43 +3052,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb"
-"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756"
-"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24"
+"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb"
+"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
 "checksum rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4b9a3a3f2345854e39768e6425d1c893855da217183d1c0b3ff6f1664b6b6d"
 "checksum rls-blacklist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "156cee9c1750b2e97d404dd0506c4780b7a2d615164f49874013807fb3cbfe5e"
 "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510"
 "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-rustc_cratesio_shim 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b576584b70d2b0c5f8a82c98a3eb39ef95eaf9187b90ad8858a149a55e94e85"
-"checksum rustc-ap-rustc_data_structures 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be7c3367229e1497a65c754188842cc02f5e50e93cced2168f621c170cd08ee5"
-"checksum rustc-ap-rustc_errors 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6440cf26fe79acf54d9d0991835a2eabec4b7039da153889a16f50bda5a7ef"
-"checksum rustc-ap-serialize 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3854db2139a75e4d1898289c08dcd8487bec318975877c6268551afccab8844b"
-"checksum rustc-ap-syntax 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1852c80f5195a3da20023205bd1202254bf0282b9ffbaaa029a6beed31db3d"
-"checksum rustc-ap-syntax_pos 98.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc60c04eccec0304b3684584b696669b2cfdfbeacee615bb5a9f431aafa64ab9"
+"checksum rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "463834ac5ea777cb56c073586675fac37292f8425aafb3757efca7e6a76545aa"
+"checksum rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d256eeab1b8639c2a1fd341e54f3613f8150bc262e4ec9361a29bbcb162906d"
+"checksum rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6dd73033bb512845a6df347174c65ad430c92ecd35527e24d8bb186f5664ee"
+"checksum rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356d338dbe538c7d6428296872d5d68da8f091e34eb89bca3b3f245ed0785e5e"
+"checksum rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f02edede4ba70963a7dac2308876f03f76f9edd48a035e5abc8fa37c57a77c8"
+"checksum rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8e50d4c38121fa8ded3ffbf94926ec74c95f24316c3b80de84fbfb42c005cf"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
-"checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4"
+"checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade"
 "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645"
-"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f"
-"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce"
+"checksum serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "29465552c9b767d0cb44be3ddf4c3214be15d34975a7750f6cf4f409835f0248"
+"checksum serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "fb88f3c93214390ed9ef3ad15ce303c36684a915a97a30883ac6ca261bf67dc7"
+"checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794"
 "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74"
+"checksum serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7bf1cbb1387028a13739cb018ee0d9b3db534f22ca3c84a5904f7eadfde14e75"
 "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
-"checksum socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "71ebbe82fcdd697244ba7fe6e05e63b5c45910c3927e28469a04947494ff48d8"
+"checksum socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ff606e0486e88f5fc6cfeb3966e434fb409abbc7a3ab495238f70a1ca97f789d"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
+"checksum strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "099e21b5dd6dd07b5adcf8c4b723a7c0b7efd7a9359bf963d58c0caae8532545"
+"checksum strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd9bd569e88028750e3ae5c25616b8278ac16a8e61aba4339195c72396d49e1"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
@@ -3049,9 +3099,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b"
 "checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac"
 "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
-"checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195"
+"checksum tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6af6b94659f9a571bf769a5b71f54079393585ee0bfdd71b691be22d7d6b1d18"
 "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
-"checksum tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "439d9a7c00f98b1b5ee730039bf5b1f9203d508690e3c76b509e7ad59f8f7c99"
+"checksum tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8cddbd26c5686ece823b507f304c8f188daef548b4cb753512d929ce478a093c"
 "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
@@ -3061,7 +3111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
 "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
-"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
+"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9"
 "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8"
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@@ -3078,7 +3128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3"
 "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
+"checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
@@ -3088,6 +3138,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
-"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc"
+"checksum xattr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb373b92de38a4301d66bec009929b4fb83120ea1c4a401be89dbe0b9777443"
 "checksum xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df591c3504d014dd791d998123ed00a476c7e26dc6b2e873cb55c6ac9e59fa"
 "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
index 7ff64af919671f977497bff7abf05dfac28e694c..b9c82127342fddf94f4125c60934a1eb944c0e05 100644 (file)
@@ -154,18 +154,17 @@ fn maybe_run(&self, builder: &Builder, pathset: &PathSet) {
             eprintln!("{:?} not skipped for {:?} -- not in {:?}", pathset,
                 self.name, builder.config.exclude);
         }
-        let build = builder.build;
-        let hosts = &build.hosts;
+        let hosts = &builder.hosts;
 
         // Determine the targets participating in this rule.
         let targets = if self.only_hosts {
-            if !build.config.run_host_only {
+            if !builder.config.run_host_only {
                 return; // don't run anything
             } else {
-                &build.hosts
+                &builder.hosts
             }
         } else {
-            &build.targets
+            &builder.targets
         };
 
         for host in hosts {
@@ -311,7 +310,8 @@ macro_rules! describe {
                 tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient,
                 tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
                 native::Llvm, tool::Rustfmt, tool::Miri, native::Lld),
-            Kind::Check => describe!(check::Std, check::Test, check::Rustc),
+            Kind::Check => describe!(check::Std, check::Test, check::Rustc, check::CodegenBackend,
+                check::Rustdoc),
             Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
                 test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
                 test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo,
@@ -326,7 +326,7 @@ macro_rules! describe {
                 test::TheBook, test::UnstableBook,
                 test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
                 // Run run-make last, since these won't pass without make on Windows
-                test::RunMake),
+                test::RunMake, test::RustdocUi),
             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc,
@@ -476,7 +476,7 @@ fn run(self, builder: &Builder) -> Interned<PathBuf> {
 
     pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
         self.sysroot_libdir(compiler, compiler.host)
-            .with_file_name(self.build.config.rust_codegen_backends_dir.clone())
+            .with_file_name(self.config.rust_codegen_backends_dir.clone())
     }
 
     /// Returns the compiler's libdir where it stores the dynamic libraries that
@@ -486,7 +486,7 @@ pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
     /// Windows.
     pub fn rustc_libdir(&self, compiler: Compiler) -> PathBuf {
         if compiler.is_snapshot(self) {
-            self.build.rustc_snapshot_libdir()
+            self.rustc_snapshot_libdir()
         } else {
             self.sysroot(compiler).join(libdir(&compiler.host))
         }
@@ -523,12 +523,12 @@ pub fn rustdoc_cmd(&self, host: Interned<String>) -> Command {
         let compiler = self.compiler(self.top_stage, host);
         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
            .env("RUSTC_SYSROOT", self.sysroot(compiler))
-           .env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
-           .env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
+           .env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build))
+           .env("CFG_RELEASE_CHANNEL", &self.config.channel)
            .env("RUSTDOC_REAL", self.rustdoc(host))
-           .env("RUSTDOC_CRATE_VERSION", self.build.rust_version())
+           .env("RUSTDOC_CRATE_VERSION", self.rust_version())
            .env("RUSTC_BOOTSTRAP", "1");
-        if let Some(linker) = self.build.linker(host) {
+        if let Some(linker) = self.linker(host) {
             cmd.env("RUSTC_TARGET_LINKER", linker);
         }
         cmd
@@ -553,6 +553,12 @@ pub fn cargo(&self,
              .arg("--target")
              .arg(target);
 
+        // Set a flag for `check` so that certain build scripts can do less work
+        // (e.g. not building/requiring LLVM).
+        if cmd == "check" {
+            cargo.env("RUST_CHECK", "1");
+        }
+
         // If we were invoked from `make` then that's already got a jobserver
         // set up for us so no need to tell Cargo about jobs all over again.
         if env::var_os("MAKEFLAGS").is_none() && env::var_os("MFLAGS").is_none() {
@@ -609,23 +615,27 @@ pub fn cargo(&self,
              .env("TEST_MIRI", self.config.test_miri.to_string())
              .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir());
 
-        if let Some(host_linker) = self.build.linker(compiler.host) {
+        if let Some(host_linker) = self.linker(compiler.host) {
             cargo.env("RUSTC_HOST_LINKER", host_linker);
         }
-        if let Some(target_linker) = self.build.linker(target) {
+        if let Some(target_linker) = self.linker(target) {
             cargo.env("RUSTC_TARGET_LINKER", target_linker);
         }
         if let Some(ref error_format) = self.config.rustc_error_format {
             cargo.env("RUSTC_ERROR_FORMAT", error_format);
         }
         if cmd != "build" && cmd != "check" {
-            cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.build.build)));
+            cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build)));
         }
 
-        if mode != Mode::Tool {
-            // Tools don't get debuginfo right now, e.g. cargo and rls don't
-            // get compiled with debuginfo.
-            // Adding debuginfo increases their sizes by a factor of 3-4.
+        if mode == Mode::Tool {
+            // Tools like cargo and rls don't get debuginfo by default right now, but this can be
+            // enabled in the config.  Adding debuginfo makes them several times larger.
+            if self.config.rust_debuginfo_tools {
+                cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string());
+                cargo.env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string());
+            }
+        } else {
             cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string());
             cargo.env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string());
             cargo.env("RUSTC_FORCE_UNSTABLE", "1");
@@ -673,7 +683,7 @@ pub fn cargo(&self,
         //
         // If LLVM support is disabled we need to use the snapshot compiler to compile
         // build scripts, as the new compiler doesn't support executables.
-        if mode == Mode::Libstd || !self.build.config.llvm_enabled {
+        if mode == Mode::Libstd || !self.config.llvm_enabled {
             cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc)
                  .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
         } else {
@@ -752,12 +762,14 @@ pub fn cargo(&self,
             }
         }
 
-        if mode == Mode::Libstd && self.config.extended && compiler.is_final_stage(self) {
+        if cmd == "build" && mode == Mode::Libstd
+            && self.config.extended && compiler.is_final_stage(self)
+        {
             cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string());
         }
 
         // For `cargo doc` invocations, make rustdoc print the Rust version into the docs
-        cargo.env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
+        cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
 
         // Environment variables *required* throughout the build
         //
@@ -765,7 +777,7 @@ pub fn cargo(&self,
         cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
 
         // Set this for all builds to make sure doc builds also get it.
-        cargo.env("CFG_RELEASE_CHANNEL", &self.build.config.channel);
+        cargo.env("CFG_RELEASE_CHANNEL", &self.config.channel);
 
         // This one's a bit tricky. As of the time of this writing the compiler
         // links to the `winapi` crate on crates.io. This crate provides raw
@@ -831,7 +843,7 @@ pub fn cargo(&self,
         cargo
     }
 
-    /// Ensure that a given step is built, returning it's output. This will
+    /// Ensure that a given step is built, returning its output. This will
     /// cache the step, so it is safe (and good!) to call this as often as
     /// needed to ensure that all dependencies are built.
     pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
@@ -850,7 +862,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
                 panic!(out);
             }
             if let Some(out) = self.cache.get(&step) {
-                self.build.verbose(&format!("{}c {:?}", "  ".repeat(stack.len()), step));
+                self.verbose(&format!("{}c {:?}", "  ".repeat(stack.len()), step));
 
                 {
                     let mut graph = self.graph.borrow_mut();
@@ -865,7 +877,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
 
                 return out;
             }
-            self.build.verbose(&format!("{}> {:?}", "  ".repeat(stack.len()), step));
+            self.verbose(&format!("{}> {:?}", "  ".repeat(stack.len()), step));
             stack.push(Box::new(step.clone()));
         }
 
@@ -895,7 +907,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
 
         self.parent.set(prev_parent);
 
-        if self.build.config.print_step_timings && dur > Duration::from_millis(100) {
+        if self.config.print_step_timings && dur > Duration::from_millis(100) {
             println!("[TIMING] {:?} -- {}.{:03}",
                      step,
                      dur.as_secs(),
@@ -907,7 +919,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
             let cur_step = stack.pop().expect("step stack empty");
             assert_eq!(cur_step.downcast_ref(), Some(&step));
         }
-        self.build.verbose(&format!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step));
+        self.verbose(&format!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step));
         self.cache.put(step, out.clone());
         out
     }
index 8f393a4c573716e38eecc660f4a412a1a0ed1a1c..698903f128d4dd346f60fd8848a79fa05741c997 100644 (file)
@@ -79,8 +79,16 @@ pub fn find(build: &mut Build) {
         let mut cfg = cc::Build::new();
         cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false)
            .target(&target).host(&build.build);
-        if target.contains("msvc") {
-            cfg.static_crt(true);
+        match build.crt_static(target) {
+            Some(a) => { cfg.static_crt(a); }
+            None => {
+                if target.contains("msvc") {
+                    cfg.static_crt(true);
+                }
+                if target.contains("musl") {
+                    cfg.static_flag(true);
+                }
+            }
         }
 
         let config = build.config.target_config.get(&target);
@@ -97,8 +105,9 @@ pub fn find(build: &mut Build) {
             cc2ar(compiler.path(), &target)
         };
 
-        build.verbose(&format!("CC_{} = {:?}", &target, compiler.path()));
         build.cc.insert(target, compiler);
+        build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target)));
+        build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target)));
         if let Some(ar) = ar {
             build.verbose(&format!("AR_{} = {:?}", &target, ar));
             build.ar.insert(target, ar);
index a39fad67ebea4ac967bffe828dd8d39c7375b624..64354ae29aa243c6b49b916ae5a6954174970a9c 100644 (file)
 
 //! Implementation of compiling the compiler and standard library, in "check" mode.
 
-use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, add_to_sysroot};
+use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot};
 use builder::{RunConfig, Builder, ShouldRun, Step};
-use {Build, Compiler, Mode};
-use cache::Interned;
+use tool::{self, prepare_tool_cargo};
+use {Compiler, Mode};
+use cache::{INTERNER, Interned};
 use std::path::PathBuf;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -36,24 +37,24 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
-        let compiler = builder.compiler(0, build.build);
+        let compiler = builder.compiler(0, builder.config.build);
+
+        let out_dir = builder.stage_out(compiler, Mode::Libstd);
+        builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
 
-        let out_dir = build.stage_out(compiler, Mode::Libstd);
-        build.clear_if_dirty(&out_dir, &builder.rustc(compiler));
         let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "check");
         std_cargo(builder, &compiler, target, &mut cargo);
 
-        let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
+        let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
         println!("Checking std artifacts ({} -> {})", &compiler.host, target);
-        run_cargo(build,
+        run_cargo(builder,
                   &mut cargo,
-                  &libstd_stamp(build, compiler, target),
+                  &libstd_stamp(builder, compiler, target),
                   true);
 
         let libdir = builder.sysroot_libdir(compiler, target);
-        add_to_sysroot(&build, &libdir, &libstd_stamp(build, compiler, target));
+        add_to_sysroot(&builder, &libdir, &libstd_stamp(builder, compiler, target));
     }
 }
 
@@ -83,26 +84,71 @@ fn make_run(run: RunConfig) {
     /// the `compiler` targeting the `target` architecture. The artifacts
     /// created will also be linked into the sysroot directory.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
-        let compiler = builder.compiler(0, build.build);
+        let compiler = builder.compiler(0, builder.config.build);
         let target = self.target;
 
         let stage_out = builder.stage_out(compiler, Mode::Librustc);
-        build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target));
-        build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));
+        builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target));
+        builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target));
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
-        rustc_cargo(build, &mut cargo);
+        rustc_cargo(builder, &mut cargo);
 
-        let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
+        let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
         println!("Checking compiler artifacts ({} -> {})", &compiler.host, target);
-        run_cargo(build,
+        run_cargo(builder,
                   &mut cargo,
-                  &librustc_stamp(build, compiler, target),
+                  &librustc_stamp(builder, compiler, target),
                   true);
 
         let libdir = builder.sysroot_libdir(compiler, target);
-        add_to_sysroot(&build, &libdir, &librustc_stamp(build, compiler, target));
+        add_to_sysroot(&builder, &libdir, &librustc_stamp(builder, compiler, target));
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct CodegenBackend {
+    pub target: Interned<String>,
+    pub backend: Interned<String>,
+}
+
+impl Step for CodegenBackend {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.all_krates("rustc_trans")
+    }
+
+    fn make_run(run: RunConfig) {
+        let backend = run.builder.config.rust_codegen_backends.get(0);
+        let backend = backend.cloned().unwrap_or_else(|| {
+            INTERNER.intern_str("llvm")
+        });
+        run.builder.ensure(CodegenBackend {
+            target: run.target,
+            backend,
+        });
+    }
+
+    fn run(self, builder: &Builder) {
+        let compiler = builder.compiler(0, builder.config.build);
+        let target = self.target;
+        let backend = self.backend;
+
+        let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
+        let features = builder.rustc_features().to_string();
+        cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_trans/Cargo.toml"));
+        rustc_cargo_env(builder, &mut cargo);
+
+        // We won't build LLVM if it's not available, as it shouldn't affect `check`.
+
+        let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
+        run_cargo(builder,
+                  cargo.arg("--features").arg(features),
+                  &codegen_backend_stamp(builder, compiler, target, backend),
+                  true);
     }
 }
 
@@ -126,41 +172,105 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
+        let compiler = builder.compiler(0, builder.config.build);
         let target = self.target;
-        let compiler = builder.compiler(0, build.build);
 
-        let out_dir = build.stage_out(compiler, Mode::Libtest);
-        build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
+        let out_dir = builder.stage_out(compiler, Mode::Libtest);
+        builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
+
         let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check");
-        test_cargo(build, &compiler, target, &mut cargo);
+        test_cargo(builder, &compiler, target, &mut cargo);
 
-        let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
+        let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
         println!("Checking test artifacts ({} -> {})", &compiler.host, target);
-        run_cargo(build,
+        run_cargo(builder,
                   &mut cargo,
-                  &libtest_stamp(build, compiler, target),
+                  &libtest_stamp(builder, compiler, target),
                   true);
 
         let libdir = builder.sysroot_libdir(compiler, target);
-        add_to_sysroot(&build, &libdir, &libtest_stamp(build, compiler, target));
+        add_to_sysroot(builder, &libdir, &libtest_stamp(builder, compiler, target));
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Rustdoc {
+    pub target: Interned<String>,
+}
+
+impl Step for Rustdoc {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/tools/rustdoc")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(Rustdoc {
+            target: run.target,
+        });
+    }
+
+    fn run(self, builder: &Builder) {
+        let compiler = builder.compiler(0, builder.config.build);
+        let target = self.target;
+
+        let mut cargo = prepare_tool_cargo(builder,
+                                           compiler,
+                                           target,
+                                           "check",
+                                           "src/tools/rustdoc");
+
+        let _folder = builder.fold_output(|| format!("stage{}-rustdoc", compiler.stage));
+        println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target);
+        run_cargo(builder,
+                  &mut cargo,
+                  &rustdoc_stamp(builder, compiler, target),
+                  true);
+
+        let libdir = builder.sysroot_libdir(compiler, target);
+        add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target));
+
+        builder.ensure(tool::CleanTools {
+            compiler,
+            target,
+            mode: Mode::Tool,
+        });
     }
 }
 
 /// Cargo's output path for the standard library in a given stage, compiled
 /// by a particular compiler for the specified target.
-pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Libstd, target).join(".libstd-check.stamp")
+pub fn libstd_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Libstd, target).join(".libstd-check.stamp")
 }
 
 /// Cargo's output path for libtest in a given stage, compiled by a particular
 /// compiler for the specified target.
-pub fn libtest_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Libtest, target).join(".libtest-check.stamp")
+pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Libtest, target).join(".libtest-check.stamp")
 }
 
 /// Cargo's output path for librustc in a given stage, compiled by a particular
 /// compiler for the specified target.
-pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
+pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
+}
+
+/// Cargo's output path for librustc_trans in a given stage, compiled by a particular
+/// compiler for the specified target and backend.
+fn codegen_backend_stamp(builder: &Builder,
+                         compiler: Compiler,
+                         target: Interned<String>,
+                         backend: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Librustc, target)
+         .join(format!(".librustc_trans-{}-check.stamp", backend))
+}
+
+/// Cargo's output path for rustdoc in a given stage, compiled by a particular
+/// compiler for the specified target.
+pub fn rustdoc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Tool, target).join(".rustdoc-check.stamp")
 }
index b411b19bd53d21047bd4f93956195070b1e9779c..1248c2b50be5e8700b4fa672ced5981db5db41b8 100644 (file)
@@ -31,7 +31,7 @@
 use serde_json;
 
 use util::{exe, libdir, is_dylib, CiEnv};
-use {Build, Compiler, Mode};
+use {Compiler, Mode};
 use native;
 use tool;
 
@@ -65,14 +65,13 @@ fn make_run(run: RunConfig) {
     /// using the `compiler` targeting the `target` architecture. The artifacts
     /// created will also be linked into the sysroot directory.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
         let compiler = self.compiler;
 
         builder.ensure(StartupObjects { compiler, target });
 
-        if build.force_use_stage1(compiler, target) {
-            let from = builder.compiler(1, build.build);
+        if builder.force_use_stage1(compiler, target) {
+            let from = builder.compiler(1, builder.config.build);
             builder.ensure(Std {
                 compiler: from,
                 target,
@@ -83,7 +82,7 @@ fn run(self, builder: &Builder) {
             // still contain the musl startup objects.
             if target.contains("musl") {
                 let libdir = builder.sysroot_libdir(compiler, target);
-                copy_musl_third_party_objects(build, target, &libdir);
+                copy_musl_third_party_objects(builder, target, &libdir);
             }
 
             builder.ensure(StdLink {
@@ -96,24 +95,24 @@ fn run(self, builder: &Builder) {
 
         if target.contains("musl") {
             let libdir = builder.sysroot_libdir(compiler, target);
-            copy_musl_third_party_objects(build, target, &libdir);
+            copy_musl_third_party_objects(builder, target, &libdir);
         }
 
-        let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
-        build.clear_if_dirty(&out_dir, &builder.rustc(compiler));
+        let out_dir = builder.cargo_out(compiler, Mode::Libstd, target);
+        builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
         let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build");
         std_cargo(builder, &compiler, target, &mut cargo);
 
-        let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
-        build.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage,
+        let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
+        builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage,
                 &compiler.host, target));
-        run_cargo(build,
+        run_cargo(builder,
                   &mut cargo,
-                  &libstd_stamp(build, compiler, target),
+                  &libstd_stamp(builder, compiler, target),
                   false);
 
         builder.ensure(StdLink {
-            compiler: builder.compiler(compiler.stage, build.build),
+            compiler: builder.compiler(compiler.stage, builder.config.build),
             target_compiler: compiler,
             target,
         });
@@ -126,17 +125,17 @@ fn run(self, builder: &Builder) {
 /// with a glibc-targeting toolchain, given we have the appropriate startup
 /// files. As those shipped with glibc won't work, copy the ones provided by
 /// musl so we have them on linux-gnu hosts.
-fn copy_musl_third_party_objects(build: &Build,
+fn copy_musl_third_party_objects(builder: &Builder,
                                  target: Interned<String>,
                                  into: &Path) {
     for &obj in &["crt1.o", "crti.o", "crtn.o"] {
-        build.copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
+        builder.copy(&builder.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
     }
 }
 
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
-pub fn std_cargo(build: &Builder,
+pub fn std_cargo(builder: &Builder,
                  compiler: &Compiler,
                  target: Interned<String>,
                  cargo: &mut Command) {
@@ -144,27 +143,27 @@ pub fn std_cargo(build: &Builder,
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
 
-    if build.no_std(target) == Some(true) {
+    if builder.no_std(target) == Some(true) {
         // for no-std targets we only compile a few no_std crates
         cargo.arg("--features").arg("c mem")
             .args(&["-p", "alloc"])
             .args(&["-p", "compiler_builtins"])
             .args(&["-p", "std_unicode"])
             .arg("--manifest-path")
-            .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml"));
+            .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml"));
     } else {
-        let mut features = build.std_features();
+        let mut features = builder.std_features();
 
         // When doing a local rebuild we tell cargo that we're stage1 rather than
         // stage0. This works fine if the local rust and being-built rust have the
         // same view of what the default allocator is, but fails otherwise. Since
         // we don't have a way to express an allocator preference yet, work
         // around the issue in the case of a local rebuild with jemalloc disabled.
-        if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
+        if compiler.stage == 0 && builder.local_rebuild && !builder.config.use_jemalloc {
             features.push_str(" force_alloc_system");
         }
 
-        if compiler.stage != 0 && build.config.sanitizers {
+        if compiler.stage != 0 && builder.config.sanitizers {
             // This variable is used by the sanitizer runtime crates, e.g.
             // rustc_lsan, to build the sanitizer runtime from C code
             // When this variable is missing, those crates won't compile the C code,
@@ -172,8 +171,8 @@ pub fn std_cargo(build: &Builder,
             // missing
             // We also only build the runtimes when --enable-sanitizers (or its
             // config.toml equivalent) is used
-            let llvm_config = build.ensure(native::Llvm {
-                target: build.config.build,
+            let llvm_config = builder.ensure(native::Llvm {
+                target: builder.config.build,
                 emscripten: false,
             });
             cargo.env("LLVM_CONFIG", llvm_config);
@@ -181,15 +180,15 @@ pub fn std_cargo(build: &Builder,
 
         cargo.arg("--features").arg(features)
             .arg("--manifest-path")
-            .arg(build.src.join("src/libstd/Cargo.toml"));
+            .arg(builder.src.join("src/libstd/Cargo.toml"));
 
-        if let Some(target) = build.config.target_config.get(&target) {
+        if let Some(target) = builder.config.target_config.get(&target) {
             if let Some(ref jemalloc) = target.jemalloc {
                 cargo.env("JEMALLOC_OVERRIDE", jemalloc);
             }
         }
         if target.contains("musl") {
-            if let Some(p) = build.musl_root(target) {
+            if let Some(p) = builder.musl_root(target) {
                 cargo.env("MUSL_ROOT", p);
             }
         }
@@ -219,24 +218,23 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// libraries for `target`, and this method will find them in the relevant
     /// output directory.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target_compiler = self.target_compiler;
         let target = self.target;
-        build.info(&format!("Copying stage{} std from stage{} ({} -> {} / {})",
+        builder.info(&format!("Copying stage{} std from stage{} ({} -> {} / {})",
                 target_compiler.stage,
                 compiler.stage,
                 &compiler.host,
                 target_compiler.host,
                 target));
         let libdir = builder.sysroot_libdir(target_compiler, target);
-        add_to_sysroot(&build, &libdir, &libstd_stamp(build, compiler, target));
+        add_to_sysroot(builder, &libdir, &libstd_stamp(builder, compiler, target));
 
-        if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
+        if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
             // The sanitizers are only built in stage1 or above, so the dylibs will
             // be missing in stage0 and causes panic. See the `std()` function above
             // for reason why the sanitizers are not built in stage0.
-            copy_apple_sanitizer_dylibs(&build, &build.native_dir(target), "osx", &libdir);
+            copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
         }
 
         builder.ensure(tool::CleanTools {
@@ -247,7 +245,7 @@ fn run(self, builder: &Builder) {
     }
 }
 
-fn copy_apple_sanitizer_dylibs(build: &Build, native_dir: &Path, platform: &str, into: &Path) {
+fn copy_apple_sanitizer_dylibs(builder: &Builder, native_dir: &Path, platform: &str, into: &Path) {
     for &sanitizer in &["asan", "tsan"] {
         let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
         let mut src_path = native_dir.join(sanitizer);
@@ -255,7 +253,7 @@ fn copy_apple_sanitizer_dylibs(build: &Build, native_dir: &Path, platform: &str,
         src_path.push("lib");
         src_path.push("darwin");
         src_path.push(&filename);
-        build.copy(&src_path, &into.join(filename));
+        builder.copy(&src_path, &into.join(filename));
     }
 }
 
@@ -286,15 +284,14 @@ fn make_run(run: RunConfig) {
     /// files, so we just use the nightly snapshot compiler to always build them (as
     /// no other compilers are guaranteed to be available).
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let for_compiler = self.compiler;
         let target = self.target;
         if !target.contains("pc-windows-gnu") {
             return
         }
 
-        let src_dir = &build.src.join("src/rtstartup");
-        let dst_dir = &build.native_dir(target).join("rtstartup");
+        let src_dir = &builder.src.join("src/rtstartup");
+        let dst_dir = &builder.native_dir(target).join("rtstartup");
         let sysroot_dir = &builder.sysroot_libdir(for_compiler, target);
         t!(fs::create_dir_all(dst_dir));
 
@@ -302,8 +299,8 @@ fn run(self, builder: &Builder) {
             let src_file = &src_dir.join(file.to_string() + ".rs");
             let dst_file = &dst_dir.join(file.to_string() + ".o");
             if !up_to_date(src_file, dst_file) {
-                let mut cmd = Command::new(&build.initial_rustc);
-                build.run(cmd.env("RUSTC_BOOTSTRAP", "1")
+                let mut cmd = Command::new(&builder.initial_rustc);
+                builder.run(cmd.env("RUSTC_BOOTSTRAP", "1")
                             .arg("--cfg").arg("stage0")
                             .arg("--target").arg(target)
                             .arg("--emit=obj")
@@ -311,15 +308,15 @@ fn run(self, builder: &Builder) {
                             .arg(src_file));
             }
 
-            build.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o"));
+            builder.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o"));
         }
 
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
-            let src = compiler_file(build,
-                                    build.cc(target),
+            let src = compiler_file(builder,
+                                    builder.cc(target),
                                     target,
                                     obj);
-            build.copy(&src, &sysroot_dir.join(obj));
+            builder.copy(&src, &sysroot_dir.join(obj));
         }
     }
 }
@@ -351,41 +348,41 @@ fn make_run(run: RunConfig) {
     /// the build using the `compiler` targeting the `target` architecture. The
     /// artifacts created will also be linked into the sysroot directory.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
         let compiler = self.compiler;
 
         builder.ensure(Std { compiler, target });
 
-        if build.force_use_stage1(compiler, target) {
+        if builder.force_use_stage1(compiler, target) {
             builder.ensure(Test {
-                compiler: builder.compiler(1, build.build),
+                compiler: builder.compiler(1, builder.config.build),
                 target,
             });
-            build.info(&format!("Uplifting stage1 test ({} -> {})", &build.build, target));
+            builder.info(
+                &format!("Uplifting stage1 test ({} -> {})", builder.config.build, target));
             builder.ensure(TestLink {
-                compiler: builder.compiler(1, build.build),
+                compiler: builder.compiler(1, builder.config.build),
                 target_compiler: compiler,
                 target,
             });
             return;
         }
 
-        let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
-        build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
+        let out_dir = builder.cargo_out(compiler, Mode::Libtest, target);
+        builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
         let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build");
-        test_cargo(build, &compiler, target, &mut cargo);
+        test_cargo(builder, &compiler, target, &mut cargo);
 
-        let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
-        build.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage,
+        let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
+        builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage,
                 &compiler.host, target));
-        run_cargo(build,
+        run_cargo(builder,
                   &mut cargo,
-                  &libtest_stamp(build, compiler, target),
+                  &libtest_stamp(builder, compiler, target),
                   false);
 
         builder.ensure(TestLink {
-            compiler: builder.compiler(compiler.stage, build.build),
+            compiler: builder.compiler(compiler.stage, builder.config.build),
             target_compiler: compiler,
             target,
         });
@@ -393,7 +390,7 @@ fn run(self, builder: &Builder) {
 }
 
 /// Same as `std_cargo`, but for libtest
-pub fn test_cargo(build: &Build,
+pub fn test_cargo(builder: &Builder,
                   _compiler: &Compiler,
                   _target: Interned<String>,
                   cargo: &mut Command) {
@@ -401,7 +398,7 @@ pub fn test_cargo(build: &Build,
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
     cargo.arg("--manifest-path")
-        .arg(build.src.join("src/libtest/Cargo.toml"));
+        .arg(builder.src.join("src/libtest/Cargo.toml"));
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -420,18 +417,17 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
     /// Same as `std_link`, only for libtest
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target_compiler = self.target_compiler;
         let target = self.target;
-        build.info(&format!("Copying stage{} test from stage{} ({} -> {} / {})",
+        builder.info(&format!("Copying stage{} test from stage{} ({} -> {} / {})",
                 target_compiler.stage,
                 compiler.stage,
                 &compiler.host,
                 target_compiler.host,
                 target));
-        add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target),
-                    &libtest_stamp(build, compiler, target));
+        add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
+                    &libtest_stamp(builder, compiler, target));
         builder.ensure(tool::CleanTools {
             compiler: target_compiler,
             target,
@@ -468,20 +464,20 @@ fn make_run(run: RunConfig) {
     /// the `compiler` targeting the `target` architecture. The artifacts
     /// created will also be linked into the sysroot directory.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
 
         builder.ensure(Test { compiler, target });
 
-        if build.force_use_stage1(compiler, target) {
+        if builder.force_use_stage1(compiler, target) {
             builder.ensure(Rustc {
-                compiler: builder.compiler(1, build.build),
+                compiler: builder.compiler(1, builder.config.build),
                 target,
             });
-            build.info(&format!("Uplifting stage1 rustc ({} -> {})", &build.build, target));
+            builder.info(&format!("Uplifting stage1 rustc ({} -> {})",
+                builder.config.build, target));
             builder.ensure(RustcLink {
-                compiler: builder.compiler(1, build.build),
+                compiler: builder.compiler(1, builder.config.build),
                 target_compiler: compiler,
                 target,
             });
@@ -490,71 +486,71 @@ fn run(self, builder: &Builder) {
 
         // Ensure that build scripts have a std to link against.
         builder.ensure(Std {
-            compiler: builder.compiler(self.compiler.stage, build.build),
-            target: build.build,
+            compiler: builder.compiler(self.compiler.stage, builder.config.build),
+            target: builder.config.build,
         });
         let cargo_out = builder.cargo_out(compiler, Mode::Librustc, target);
-        build.clear_if_dirty(&cargo_out, &libstd_stamp(build, compiler, target));
-        build.clear_if_dirty(&cargo_out, &libtest_stamp(build, compiler, 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::Librustc, target, "build");
-        rustc_cargo(build, &mut cargo);
+        rustc_cargo(builder, &mut cargo);
 
-        let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
-        build.info(&format!("Building stage{} compiler artifacts ({} -> {})",
+        let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
+        builder.info(&format!("Building stage{} compiler artifacts ({} -> {})",
                  compiler.stage, &compiler.host, target));
-        run_cargo(build,
+        run_cargo(builder,
                   &mut cargo,
-                  &librustc_stamp(build, compiler, target),
+                  &librustc_stamp(builder, compiler, target),
                   false);
 
         builder.ensure(RustcLink {
-            compiler: builder.compiler(compiler.stage, build.build),
+            compiler: builder.compiler(compiler.stage, builder.config.build),
             target_compiler: compiler,
             target,
         });
     }
 }
 
-pub fn rustc_cargo(build: &Build, cargo: &mut Command) {
-    cargo.arg("--features").arg(build.rustc_features())
+pub fn rustc_cargo(builder: &Builder, cargo: &mut Command) {
+    cargo.arg("--features").arg(builder.rustc_features())
          .arg("--manifest-path")
-         .arg(build.src.join("src/rustc/Cargo.toml"));
-    rustc_cargo_env(build, cargo);
+         .arg(builder.src.join("src/rustc/Cargo.toml"));
+    rustc_cargo_env(builder, cargo);
 }
 
-fn rustc_cargo_env(build: &Build, cargo: &mut Command) {
+pub fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) {
     // Set some configuration variables picked up by build scripts and
     // the compiler alike
-    cargo.env("CFG_RELEASE", build.rust_release())
-         .env("CFG_RELEASE_CHANNEL", &build.config.channel)
-         .env("CFG_VERSION", build.rust_version())
-         .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default())
-         .env("CFG_CODEGEN_BACKENDS_DIR", &build.config.rust_codegen_backends_dir);
+    cargo.env("CFG_RELEASE", builder.rust_release())
+         .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
+         .env("CFG_VERSION", builder.rust_version())
+         .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default())
+         .env("CFG_CODEGEN_BACKENDS_DIR", &builder.config.rust_codegen_backends_dir);
 
-    let libdir_relative = build.config.libdir_relative().unwrap_or(Path::new("lib"));
+    let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
 
     // If we're not building a compiler with debugging information then remove
     // these two env vars which would be set otherwise.
-    if build.config.rust_debuginfo_only_std {
+    if builder.config.rust_debuginfo_only_std {
         cargo.env_remove("RUSTC_DEBUGINFO");
         cargo.env_remove("RUSTC_DEBUGINFO_LINES");
     }
 
-    if let Some(ref ver_date) = build.rust_info.commit_date() {
+    if let Some(ref ver_date) = builder.rust_info.commit_date() {
         cargo.env("CFG_VER_DATE", ver_date);
     }
-    if let Some(ref ver_hash) = build.rust_info.sha() {
+    if let Some(ref ver_hash) = builder.rust_info.sha() {
         cargo.env("CFG_VER_HASH", ver_hash);
     }
-    if !build.unstable_features() {
+    if !builder.unstable_features() {
         cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
     }
-    if let Some(ref s) = build.config.rustc_default_linker {
+    if let Some(ref s) = builder.config.rustc_default_linker {
         cargo.env("CFG_DEFAULT_LINKER", s);
     }
-    if build.config.rustc_parallel_queries {
+    if builder.config.rustc_parallel_queries {
         cargo.env("RUSTC_PARALLEL_QUERIES", "1");
     }
 }
@@ -575,18 +571,17 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
     /// Same as `std_link`, only for librustc
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target_compiler = self.target_compiler;
         let target = self.target;
-        build.info(&format!("Copying stage{} rustc from stage{} ({} -> {} / {})",
+        builder.info(&format!("Copying stage{} rustc from stage{} ({} -> {} / {})",
                  target_compiler.stage,
                  compiler.stage,
                  &compiler.host,
                  target_compiler.host,
                  target));
-        add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target),
-                       &librustc_stamp(build, compiler, target));
+        add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
+                       &librustc_stamp(builder, compiler, target));
         builder.ensure(tool::CleanTools {
             compiler: target_compiler,
             target,
@@ -619,84 +614,39 @@ fn make_run(run: RunConfig) {
         run.builder.ensure(CodegenBackend {
             compiler: run.builder.compiler(run.builder.top_stage, run.host),
             target: run.target,
-            backend
+            backend,
         });
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
+        let backend = self.backend;
 
         builder.ensure(Rustc { compiler, target });
 
-        if build.force_use_stage1(compiler, target) {
+        if builder.force_use_stage1(compiler, target) {
             builder.ensure(CodegenBackend {
-                compiler: builder.compiler(1, build.build),
+                compiler: builder.compiler(1, builder.config.build),
                 target,
-                backend: self.backend,
+                backend,
             });
             return;
         }
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
-        let mut features = build.rustc_features().to_string();
+        let mut features = builder.rustc_features().to_string();
         cargo.arg("--manifest-path")
-            .arg(build.src.join("src/librustc_trans/Cargo.toml"));
-        rustc_cargo_env(build, &mut cargo);
-
-        match &*self.backend {
-            "llvm" | "emscripten" => {
-                // Build LLVM for our target. This will implicitly build the
-                // host LLVM if necessary.
-                let llvm_config = builder.ensure(native::Llvm {
-                    target,
-                    emscripten: self.backend == "emscripten",
-                });
-
-                if self.backend == "emscripten" {
-                    features.push_str(" emscripten");
-                }
-
-                build.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})",
-                         compiler.stage, &compiler.host, target, self.backend));
+            .arg(builder.src.join("src/librustc_trans/Cargo.toml"));
+        rustc_cargo_env(builder, &mut cargo);
 
-                // Pass down configuration from the LLVM build into the build of
-                // librustc_llvm and librustc_trans.
-                if build.is_rust_llvm(target) {
-                    cargo.env("LLVM_RUSTLLVM", "1");
-                }
-                cargo.env("LLVM_CONFIG", &llvm_config);
-                if self.backend != "emscripten" {
-                    let target_config = build.config.target_config.get(&target);
-                    if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
-                        cargo.env("CFG_LLVM_ROOT", s);
-                    }
-                }
-                // Building with a static libstdc++ is only supported on linux right now,
-                // not for MSVC or macOS
-                if build.config.llvm_static_stdcpp &&
-                   !target.contains("freebsd") &&
-                   !target.contains("windows") &&
-                   !target.contains("apple") {
-                    let file = compiler_file(build,
-                                             build.cxx(target).unwrap(),
-                                             target,
-                                             "libstdc++.a");
-                    cargo.env("LLVM_STATIC_STDCPP", file);
-                }
-                if build.config.llvm_link_shared {
-                    cargo.env("LLVM_LINK_SHARED", "1");
-                }
-            }
-            _ => panic!("unknown backend: {}", self.backend),
-        }
+        features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
 
-        let tmp_stamp = build.cargo_out(compiler, Mode::Librustc, target)
+        let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target)
             .join(".tmp.stamp");
 
-        let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
-        let files = run_cargo(build,
+        let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
+        let files = run_cargo(builder,
                               cargo.arg("--features").arg(features),
                               &tmp_stamp,
                               false);
@@ -717,12 +667,69 @@ fn run(self, builder: &Builder) {
                    codegen_backend.display(),
                    f.display());
         }
-        let stamp = codegen_backend_stamp(build, compiler, target, self.backend);
+        let stamp = codegen_backend_stamp(builder, compiler, target, backend);
         let codegen_backend = codegen_backend.to_str().unwrap();
         t!(t!(File::create(&stamp)).write_all(codegen_backend.as_bytes()));
     }
 }
 
+pub fn build_codegen_backend(builder: &Builder,
+                             cargo: &mut Command,
+                             compiler: &Compiler,
+                             target: Interned<String>,
+                             backend: Interned<String>) -> String {
+    let mut features = String::new();
+
+    match &*backend {
+        "llvm" | "emscripten" => {
+            // Build LLVM for our target. This will implicitly build the
+            // host LLVM if necessary.
+            let llvm_config = builder.ensure(native::Llvm {
+                target,
+                emscripten: backend == "emscripten",
+            });
+
+            if backend == "emscripten" {
+                features.push_str(" emscripten");
+            }
+
+            builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})",
+                     compiler.stage, &compiler.host, target, backend));
+
+            // Pass down configuration from the LLVM build into the build of
+            // librustc_llvm and librustc_trans.
+            if builder.is_rust_llvm(target) {
+                cargo.env("LLVM_RUSTLLVM", "1");
+            }
+            cargo.env("LLVM_CONFIG", &llvm_config);
+            if backend != "emscripten" {
+                let target_config = builder.config.target_config.get(&target);
+                if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
+                    cargo.env("CFG_LLVM_ROOT", s);
+                }
+            }
+            // Building with a static libstdc++ is only supported on linux right now,
+            // not for MSVC or macOS
+            if builder.config.llvm_static_stdcpp &&
+               !target.contains("freebsd") &&
+               !target.contains("windows") &&
+               !target.contains("apple") {
+                let file = compiler_file(builder,
+                                         builder.cxx(target).unwrap(),
+                                         target,
+                                         "libstdc++.a");
+                cargo.env("LLVM_STATIC_STDCPP", file);
+            }
+            if builder.config.llvm_link_shared {
+                cargo.env("LLVM_LINK_SHARED", "1");
+            }
+        }
+        _ => panic!("unknown backend: {}", backend),
+    }
+
+    features
+}
+
 /// Creates the `codegen-backends` folder for a compiler that's about to be
 /// assembled as a complete compiler.
 ///
@@ -732,7 +739,6 @@ fn run(self, builder: &Builder) {
 fn copy_codegen_backends_to_sysroot(builder: &Builder,
                                     compiler: Compiler,
                                     target_compiler: Compiler) {
-    let build = builder.build;
     let target = target_compiler.host;
 
     // Note that this step is different than all the other `*Link` steps in
@@ -751,7 +757,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
     }
 
     for backend in builder.config.rust_codegen_backends.iter() {
-        let stamp = codegen_backend_stamp(build, compiler, target, *backend);
+        let stamp = codegen_backend_stamp(builder, compiler, target, *backend);
         let mut dylib = String::new();
         t!(t!(File::open(&stamp)).read_to_string(&mut dylib));
         let file = Path::new(&dylib);
@@ -765,7 +771,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
                     backend,
                     &filename[dot..])
         };
-        build.copy(&file, &dst.join(target_filename));
+        builder.copy(&file, &dst.join(target_filename));
     }
 }
 
@@ -786,36 +792,38 @@ fn copy_lld_to_sysroot(builder: &Builder,
 
 /// Cargo's output path for the standard library in a given stage, compiled
 /// by a particular compiler for the specified target.
-pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
+pub fn libstd_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
 }
 
 /// Cargo's output path for libtest in a given stage, compiled by a particular
 /// compiler for the specified target.
-pub fn libtest_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
+pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
 }
 
 /// Cargo's output path for librustc in a given stage, compiled by a particular
 /// compiler for the specified target.
-pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
+pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
+    builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
 }
 
-fn codegen_backend_stamp(build: &Build,
+/// Cargo's output path for librustc_trans in a given stage, compiled by a particular
+/// compiler for the specified target and backend.
+fn codegen_backend_stamp(builder: &Builder,
                          compiler: Compiler,
                          target: Interned<String>,
                          backend: Interned<String>) -> PathBuf {
-    build.cargo_out(compiler, Mode::Librustc, target)
+    builder.cargo_out(compiler, Mode::Librustc, target)
         .join(format!(".librustc_trans-{}.stamp", backend))
 }
 
-fn compiler_file(build: &Build,
+pub fn compiler_file(builder: &Builder,
                  compiler: &Path,
                  target: Interned<String>,
                  file: &str) -> PathBuf {
     let mut cmd = Command::new(compiler);
-    cmd.args(build.cflags(target));
+    cmd.args(builder.cflags(target));
     cmd.arg(format!("-print-file-name={}", file));
     let out = output(&mut cmd);
     PathBuf::from(out.trim())
@@ -840,12 +848,11 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// thinks it is by default, but it's the same as the default for stages
     /// 1-3.
     fn run(self, builder: &Builder) -> Interned<PathBuf> {
-        let build = builder.build;
         let compiler = self.compiler;
         let sysroot = if compiler.stage == 0 {
-            build.out.join(&compiler.host).join("stage0-sysroot")
+            builder.out.join(&compiler.host).join("stage0-sysroot")
         } else {
-            build.out.join(&compiler.host).join(format!("stage{}", compiler.stage))
+            builder.out.join(&compiler.host).join(format!("stage{}", compiler.stage))
         };
         let _ = fs::remove_dir_all(&sysroot);
         t!(fs::create_dir_all(&sysroot));
@@ -872,14 +879,13 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// Prepare a new compiler from the artifacts in `stage`
     ///
     /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
-    /// must have been previously produced by the `stage - 1` build.build
+    /// must have been previously produced by the `stage - 1` builder.build
     /// compiler.
     fn run(self, builder: &Builder) -> Compiler {
-        let build = builder.build;
         let target_compiler = self.target_compiler;
 
         if target_compiler.stage == 0 {
-            assert_eq!(build.build, target_compiler.host,
+            assert_eq!(builder.config.build, target_compiler.host,
                 "Cannot obtain compiler for non-native build triple at stage 0");
             // The stage 0 compiler for the build triple is always pre-built.
             return target_compiler;
@@ -902,14 +908,14 @@ fn run(self, builder: &Builder) -> Compiler {
         // FIXME: It may be faster if we build just a stage 1 compiler and then
         //        use that to bootstrap this compiler forward.
         let build_compiler =
-            builder.compiler(target_compiler.stage - 1, build.build);
+            builder.compiler(target_compiler.stage - 1, builder.config.build);
 
         // Build the libraries for this compiler to link to (i.e., the libraries
         // it uses at runtime). NOTE: Crates the target compiler compiles don't
         // link to these. (FIXME: Is that correct? It seems to be correct most
         // of the time but I think we do link to these for stage2/bin compilers
         // when not performing a full bootstrap).
-        if builder.build.config.keep_stage.map_or(false, |s| target_compiler.stage <= s) {
+        if builder.config.keep_stage.map_or(false, |s| target_compiler.stage <= s) {
             builder.verbose("skipping compilation of compiler due to --keep-stage");
             let compiler = build_compiler;
             for stage in 0..min(target_compiler.stage, builder.config.keep_stage.unwrap()) {
@@ -924,7 +930,7 @@ fn run(self, builder: &Builder) -> Compiler {
                 compiler: build_compiler,
                 target: target_compiler.host,
             });
-            for &backend in build.config.rust_codegen_backends.iter() {
+            for &backend in builder.config.rust_codegen_backends.iter() {
                 builder.ensure(CodegenBackend {
                     compiler: build_compiler,
                     target: target_compiler.host,
@@ -933,7 +939,7 @@ fn run(self, builder: &Builder) -> Compiler {
             }
         }
 
-        let lld_install = if build.config.lld_enabled {
+        let lld_install = if builder.config.lld_enabled {
             Some(builder.ensure(native::Lld {
                 target: target_compiler.host,
             }))
@@ -943,7 +949,7 @@ fn run(self, builder: &Builder) -> Compiler {
 
         let stage = target_compiler.stage;
         let host = target_compiler.host;
-        build.info(&format!("Assembling stage{} compiler ({})", stage, host));
+        builder.info(&format!("Assembling stage{} compiler ({})", stage, host));
 
         // Link in all dylibs to the libdir
         let sysroot = builder.sysroot(target_compiler);
@@ -965,7 +971,7 @@ fn run(self, builder: &Builder) -> Compiler {
         }
 
         // Link the compiler binary itself into place
-        let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
+        let out_dir = builder.cargo_out(build_compiler, Mode::Librustc, host);
         let rustc = out_dir.join(exe("rustc", &*host));
         let bindir = sysroot.join("bin");
         t!(fs::create_dir_all(&bindir));
@@ -981,10 +987,10 @@ fn run(self, builder: &Builder) -> Compiler {
 ///
 /// For a particular stage this will link the file listed in `stamp` into the
 /// `sysroot_dst` provided.
-pub fn add_to_sysroot(build: &Build, sysroot_dst: &Path, stamp: &Path) {
+pub fn add_to_sysroot(builder: &Builder, sysroot_dst: &Path, stamp: &Path) {
     t!(fs::create_dir_all(&sysroot_dst));
-    for path in build.read_stamp_file(stamp) {
-        build.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
+    for path in builder.read_stamp_file(stamp) {
+        builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
     }
 }
 
@@ -1011,10 +1017,10 @@ fn stderr_isatty() -> bool {
     }
 }
 
-pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: bool)
+pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check: bool)
     -> Vec<PathBuf>
 {
-    if build.config.dry_run {
+    if builder.config.dry_run {
         return Vec::new();
     }
 
@@ -1032,7 +1038,7 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo
     // files we need to probe for later.
     let mut deps = Vec::new();
     let mut toplevel = Vec::new();
-    let ok = stream_cargo(build, cargo, &mut |msg| {
+    let ok = stream_cargo(builder, cargo, &mut |msg| {
         let filenames = match msg {
             CargoMessage::CompilerArtifact { filenames, .. } => filenames,
             _ => return,
@@ -1141,25 +1147,25 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo
     let max = max.unwrap();
     let max_path = max_path.unwrap();
     if stamp_contents == new_contents && max <= stamp_mtime {
-        build.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
+        builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
                 stamp, max, stamp_mtime));
         return deps
     }
     if max > stamp_mtime {
-        build.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
+        builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
     } else {
-        build.verbose(&format!("updating {:?} as deps changed", stamp));
+        builder.verbose(&format!("updating {:?} as deps changed", stamp));
     }
     t!(t!(File::create(stamp)).write_all(&new_contents));
     deps
 }
 
 pub fn stream_cargo(
-    build: &Build,
+    builder: &Builder,
     cargo: &mut Command,
     cb: &mut FnMut(CargoMessage),
 ) -> bool {
-    if build.config.dry_run {
+    if builder.config.dry_run {
         return true;
     }
     // Instruct Cargo to give us json messages on stdout, critically leaving
@@ -1167,7 +1173,7 @@ pub fn stream_cargo(
     cargo.arg("--message-format").arg("json")
          .stdout(Stdio::piped());
 
-    if stderr_isatty() && build.ci_env == CiEnv::None &&
+    if stderr_isatty() && builder.ci_env == CiEnv::None &&
         // if the terminal is reported as dumb, then we don't want to enable color for rustc
         env::var_os("TERM").map(|t| t != *"dumb").unwrap_or(true) {
         // since we pass message-format=json to cargo, we need to tell the rustc
@@ -1176,7 +1182,7 @@ pub fn stream_cargo(
         cargo.env("RUSTC_COLOR", "1");
     }
 
-    build.verbose(&format!("running: {:?}", cargo));
+    builder.verbose(&format!("running: {:?}", cargo));
     let mut child = match cargo.spawn() {
         Ok(child) => child,
         Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e),
index 239316d45c49c4067cd3ab74074452e296644f7b..1b4b2c5fb2a54cab90d9bf633b6dfabd4f6b8d78 100644 (file)
@@ -94,6 +94,7 @@ pub struct Config {
     pub rust_debuginfo: bool,
     pub rust_debuginfo_lines: bool,
     pub rust_debuginfo_only_std: bool,
+    pub rust_debuginfo_tools: bool,
     pub rust_rpath: bool,
     pub rustc_parallel_queries: bool,
     pub rustc_default_linker: Option<String>,
@@ -282,6 +283,7 @@ struct Rust {
     debuginfo: Option<bool>,
     debuginfo_lines: Option<bool>,
     debuginfo_only_std: Option<bool>,
+    debuginfo_tools: Option<bool>,
     experimental_parallel_queries: Option<bool>,
     debug_jemalloc: Option<bool>,
     use_jemalloc: Option<bool>,
@@ -462,6 +464,7 @@ pub fn parse(args: &[String]) -> Config {
         let mut llvm_assertions = None;
         let mut debuginfo_lines = None;
         let mut debuginfo_only_std = None;
+        let mut debuginfo_tools = None;
         let mut debug = None;
         let mut debug_jemalloc = None;
         let mut debuginfo = None;
@@ -499,6 +502,7 @@ pub fn parse(args: &[String]) -> Config {
             debuginfo = rust.debuginfo;
             debuginfo_lines = rust.debuginfo_lines;
             debuginfo_only_std = rust.debuginfo_only_std;
+            debuginfo_tools = rust.debuginfo_tools;
             optimize = rust.optimize;
             ignore_git = rust.ignore_git;
             debug_jemalloc = rust.debug_jemalloc;
@@ -582,6 +586,7 @@ pub fn parse(args: &[String]) -> Config {
         };
         config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default);
         config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default);
+        config.rust_debuginfo_tools = debuginfo_tools.unwrap_or(false);
 
         let default = debug == Some(true);
         config.debug_jemalloc = debug_jemalloc.unwrap_or(default);
index b06968d313ba201b8ed8da8318c323c268088a74..a0123da6d8ff9ba077663f4f10334a03c271baef 100755 (executable)
@@ -79,6 +79,7 @@ o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger
 o("debuginfo", "rust.debuginfo", "build with debugger metadata")
 o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata")
 o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information")
+o("debuginfo-tools", "rust.debuginfo-tools", "build extended tools with debugging information")
 o("debug-jemalloc", "rust.debug-jemalloc", "build jemalloc with --enable-debug --enable-fill")
 v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file")
 
index e1f5d34bf67235c5e2a58225e4e4903f5b6b55a4..e21a59390b7b6ff6b091d9d07efd62420c8e2898 100644 (file)
@@ -26,7 +26,7 @@
 
 use build_helper::output;
 
-use {Build, Compiler, Mode};
+use {Compiler, Mode};
 use channel;
 use util::{libdir, is_dylib, exe};
 use builder::{Builder, RunConfig, ShouldRun, Step};
 use cache::{INTERNER, Interned};
 use time;
 
-pub fn pkgname(build: &Build, component: &str) -> String {
+pub fn pkgname(builder: &Builder, component: &str) -> String {
     if component == "cargo" {
-        format!("{}-{}", component, build.cargo_package_vers())
+        format!("{}-{}", component, builder.cargo_package_vers())
     } else if component == "rls" {
-        format!("{}-{}", component, build.rls_package_vers())
+        format!("{}-{}", component, builder.rls_package_vers())
     } else if component == "rustfmt" {
-        format!("{}-{}", component, build.rustfmt_package_vers())
+        format!("{}-{}", component, builder.rustfmt_package_vers())
     } else {
         assert!(component.starts_with("rust"));
-        format!("{}-{}", component, build.rust_package_vers())
+        format!("{}-{}", component, builder.rust_package_vers())
     }
 }
 
-fn distdir(build: &Build) -> PathBuf {
-    build.out.join("dist")
+fn distdir(builder: &Builder) -> PathBuf {
+    builder.out.join("dist")
 }
 
-pub fn tmpdir(build: &Build) -> PathBuf {
-    build.out.join("tmp/dist")
+pub fn tmpdir(builder: &Builder) -> PathBuf {
+    builder.out.join("tmp/dist")
 }
 
 fn rust_installer(builder: &Builder) -> Command {
@@ -84,26 +84,25 @@ fn make_run(run: RunConfig) {
 
     /// Builds the `rust-docs` installer component.
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let host = self.host;
 
-        let name = pkgname(build, "rust-docs");
+        let name = pkgname(builder, "rust-docs");
 
-        build.info(&format!("Dist docs ({})", host));
-        if !build.config.docs {
-            build.info(&format!("\tskipping - docs disabled"));
-            return distdir(build).join(format!("{}-{}.tar.gz", name, host));
+        builder.info(&format!("Dist docs ({})", host));
+        if !builder.config.docs {
+            builder.info(&format!("\tskipping - docs disabled"));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
         }
 
         builder.default_doc(None);
 
-        let image = tmpdir(build).join(format!("{}-{}-image", name, host));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
         let _ = fs::remove_dir_all(&image);
 
         let dst = image.join("share/doc/rust/html");
         t!(fs::create_dir_all(&dst));
-        let src = build.doc_out(host);
-        build.cp_r(&src, &dst);
+        let src = builder.doc_out(host);
+        builder.cp_r(&src, &dst);
 
         let mut cmd = rust_installer(builder);
         cmd.arg("generate")
@@ -111,16 +110,16 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=Rust-documentation-is-installed.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg(format!("--package-name={}-{}", name, host))
            .arg("--component-name=rust-docs")
            .arg("--legacy-manifest-dirs=rustlib,cargo")
            .arg("--bulk-dirs=share/doc/rust/html");
-        build.run(&mut cmd);
-        build.remove_dir(&image);
+        builder.run(&mut cmd);
+        builder.remove_dir(&image);
 
-        distdir(build).join(format!("{}-{}.tar.gz", name, host))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, host))
     }
 }
 
@@ -147,26 +146,25 @@ fn make_run(run: RunConfig) {
 
     /// Builds the `rustc-docs` installer component.
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let host = self.host;
 
-        let name = pkgname(build, "rustc-docs");
+        let name = pkgname(builder, "rustc-docs");
 
-        build.info(&format!("Dist compiler docs ({})", host));
-        if !build.config.compiler_docs {
-            build.info(&format!("\tskipping - compiler docs disabled"));
-            return distdir(build).join(format!("{}-{}.tar.gz", name, host));
+        builder.info(&format!("Dist compiler docs ({})", host));
+        if !builder.config.compiler_docs {
+            builder.info(&format!("\tskipping - compiler docs disabled"));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
         }
 
         builder.default_doc(None);
 
-        let image = tmpdir(build).join(format!("{}-{}-image", name, host));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
         let _ = fs::remove_dir_all(&image);
 
         let dst = image.join("share/doc/rust/html");
         t!(fs::create_dir_all(&dst));
-        let src = build.compiler_doc_out(host);
-        build.cp_r(&src, &dst);
+        let src = builder.compiler_doc_out(host);
+        builder.cp_r(&src, &dst);
 
         let mut cmd = rust_installer(builder);
         cmd.arg("generate")
@@ -174,16 +172,16 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=Rustc-documentation-is-installed.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg(format!("--package-name={}-{}", name, host))
            .arg("--component-name=rustc-docs")
            .arg("--legacy-manifest-dirs=rustlib,cargo")
            .arg("--bulk-dirs=share/doc/rust/html");
-        build.run(&mut cmd);
-        build.remove_dir(&image);
+        builder.run(&mut cmd);
+        builder.remove_dir(&image);
 
-        distdir(build).join(format!("{}-{}.tar.gz", name, host))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, host))
     }
 }
 
@@ -207,10 +205,10 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
 }
 
 fn make_win_dist(
-    rust_root: &Path, plat_root: &Path, target_triple: Interned<String>, build: &Build
+    rust_root: &Path, plat_root: &Path, target_triple: Interned<String>, builder: &Builder
 ) {
     //Ask gcc where it keeps its stuff
-    let mut cmd = Command::new(build.cc(target_triple));
+    let mut cmd = Command::new(builder.cc(target_triple));
     cmd.arg("-print-search-dirs");
     let gcc_out = output(&mut cmd);
 
@@ -296,21 +294,21 @@ fn make_win_dist(
     let dist_bin_dir = rust_root.join("bin/");
     fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
     for src in rustc_dlls {
-        build.copy_to_folder(&src, &dist_bin_dir);
+        builder.copy_to_folder(&src, &dist_bin_dir);
     }
 
     //Copy platform tools to platform-specific bin directory
     let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
     fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
     for src in target_tools {
-        build.copy_to_folder(&src, &target_bin_dir);
+        builder.copy_to_folder(&src, &target_bin_dir);
     }
 
     //Copy platform libs to platform-specific lib directory
     let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
     for src in target_libs {
-        build.copy_to_folder(&src, &target_lib_dir);
+        builder.copy_to_folder(&src, &target_lib_dir);
     }
 }
 
@@ -336,16 +334,15 @@ fn make_run(run: RunConfig) {
     /// This contains all the bits and pieces to run the MinGW Windows targets
     /// without any extra installed software (e.g. we bundle gcc, libraries, etc).
     fn run(self, builder: &Builder) -> Option<PathBuf> {
-        let build = builder.build;
         let host = self.host;
 
         if !host.contains("pc-windows-gnu") {
             return None;
         }
 
-        build.info(&format!("Dist mingw ({})", host));
-        let name = pkgname(build, "rust-mingw");
-        let image = tmpdir(build).join(format!("{}-{}-image", name, host));
+        builder.info(&format!("Dist mingw ({})", host));
+        let name = pkgname(builder, "rust-mingw");
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
         let _ = fs::remove_dir_all(&image);
         t!(fs::create_dir_all(&image));
 
@@ -353,7 +350,7 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         // thrown away (this contains the runtime DLLs included in the rustc package
         // above) and the second argument is where to place all the MinGW components
         // (which is what we want).
-        make_win_dist(&tmpdir(build), &image, host, &build);
+        make_win_dist(&tmpdir(builder), &image, host, &builder);
 
         let mut cmd = rust_installer(builder);
         cmd.arg("generate")
@@ -361,14 +358,14 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=Rust-MinGW-is-installed.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg(format!("--package-name={}-{}", name, host))
            .arg("--component-name=rust-mingw")
            .arg("--legacy-manifest-dirs=rustlib,cargo");
-        build.run(&mut cmd);
+        builder.run(&mut cmd);
         t!(fs::remove_dir_all(&image));
-        Some(distdir(build).join(format!("{}-{}.tar.gz", name, host)))
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host)))
     }
 }
 
@@ -394,15 +391,14 @@ fn make_run(run: RunConfig) {
 
     /// Creates the `rustc` installer component.
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let compiler = self.compiler;
         let host = self.compiler.host;
 
-        build.info(&format!("Dist rustc stage{} ({})", compiler.stage, compiler.host));
-        let name = pkgname(build, "rustc");
-        let image = tmpdir(build).join(format!("{}-{}-image", name, host));
+        builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, compiler.host));
+        let name = pkgname(builder, "rustc");
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
         let _ = fs::remove_dir_all(&image);
-        let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host));
+        let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host));
         let _ = fs::remove_dir_all(&overlay);
 
         // Prepare the rustc "image", what will actually end up getting installed
@@ -411,17 +407,17 @@ fn run(self, builder: &Builder) -> PathBuf {
         // Prepare the overlay which is part of the tarball but won't actually be
         // installed
         let cp = |file: &str| {
-            build.install(&build.src.join(file), &overlay, 0o644);
+            builder.install(&builder.src.join(file), &overlay, 0o644);
         };
         cp("COPYRIGHT");
         cp("LICENSE-APACHE");
         cp("LICENSE-MIT");
         cp("README.md");
         // tiny morsel of metadata is used by rust-packaging
-        let version = build.rust_version();
-        build.create(&overlay.join("version"), &version);
-        if let Some(sha) = build.rust_sha() {
-            build.create(&overlay.join("git-commit-hash"), &sha);
+        let version = builder.rust_version();
+        builder.create(&overlay.join("version"), &version);
+        if let Some(sha) = builder.rust_sha() {
+            builder.create(&overlay.join("git-commit-hash"), &sha);
         }
 
         // On MinGW we've got a few runtime DLL dependencies that we need to
@@ -435,11 +431,11 @@ fn run(self, builder: &Builder) -> PathBuf {
         // install will *also* include the rust-mingw package, which also needs
         // licenses, so to be safe we just include it here in all MinGW packages.
         if host.contains("pc-windows-gnu") {
-            make_win_dist(&image, &tmpdir(build), host, build);
+            make_win_dist(&image, &tmpdir(builder), host, builder);
 
             let dst = image.join("share/doc");
             t!(fs::create_dir_all(&dst));
-            build.cp_r(&build.src.join("src/etc/third-party"), &dst);
+            builder.cp_r(&builder.src.join("src/etc/third-party"), &dst);
         }
 
         // Finally, wrap everything up in a nice tarball!
@@ -449,37 +445,36 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=Rust-is-ready-to-roll.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg("--non-installed-overlay").arg(&overlay)
            .arg(format!("--package-name={}-{}", name, host))
            .arg("--component-name=rustc")
            .arg("--legacy-manifest-dirs=rustlib,cargo");
-        build.run(&mut cmd);
-        build.remove_dir(&image);
-        build.remove_dir(&overlay);
+        builder.run(&mut cmd);
+        builder.remove_dir(&image);
+        builder.remove_dir(&overlay);
 
-        return distdir(build).join(format!("{}-{}.tar.gz", name, host));
+        return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
 
         fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
             let host = compiler.host;
-            let build = builder.build;
             let src = builder.sysroot(compiler);
             let libdir = libdir(&host);
 
             // Copy rustc/rustdoc binaries
             t!(fs::create_dir_all(image.join("bin")));
-            build.cp_r(&src.join("bin"), &image.join("bin"));
+            builder.cp_r(&src.join("bin"), &image.join("bin"));
 
-            build.install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755);
+            builder.install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755);
 
             // Copy runtime DLLs needed by the compiler
             if libdir != "bin" {
-                for entry in build.read_dir(&src.join(libdir)) {
+                for entry in builder.read_dir(&src.join(libdir)) {
                     let name = entry.file_name();
                     if let Some(s) = name.to_str() {
                         if is_dylib(s) {
-                            build.install(&entry.path(), &image.join(libdir), 0o644);
+                            builder.install(&entry.path(), &image.join(libdir), 0o644);
                         }
                     }
                 }
@@ -490,7 +485,7 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
             let backends_rel = backends_src.strip_prefix(&src).unwrap();
             let backends_dst = image.join(&backends_rel);
             t!(fs::create_dir_all(&backends_dst));
-            build.cp_r(&backends_src, &backends_dst);
+            builder.cp_r(&backends_src, &backends_dst);
 
             // Copy over lld if it's there
             if builder.config.lld_enabled {
@@ -505,22 +500,22 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
                     .join("bin")
                     .join(&exe);
                 t!(fs::create_dir_all(&dst.parent().unwrap()));
-                build.copy(&src, &dst);
+                builder.copy(&src, &dst);
             }
 
             // Man pages
             t!(fs::create_dir_all(image.join("share/man/man1")));
-            let man_src = build.src.join("src/doc/man");
+            let man_src = builder.src.join("src/doc/man");
             let man_dst = image.join("share/man/man1");
             let month_year = t!(time::strftime("%B %Y", &time::now()));
             // don't use our `bootstrap::util::{copy, cp_r}`, because those try
             // to hardlink, and we don't want to edit the source templates
-            for file_entry in build.read_dir(&man_src) {
+            for file_entry in builder.read_dir(&man_src) {
                 let page_src = file_entry.path();
                 let page_dst = man_dst.join(file_entry.file_name());
                 t!(fs::copy(&page_src, &page_dst));
                 // template in month/year and version number
-                build.replace_in_file(&page_dst,
+                builder.replace_in_file(&page_dst,
                                 &[("<INSERT DATE HERE>", &month_year),
                                   ("<INSERT VERSION HERE>", channel::CFG_RELEASE_NUM)]);
             }
@@ -533,7 +528,7 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
 
             // Misc license info
             let cp = |file: &str| {
-                build.install(&build.src.join(file), &image.join("share/doc/rust"), 0o644);
+                builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
             };
             cp("COPYRIGHT");
             cp("LICENSE-APACHE");
@@ -565,17 +560,16 @@ fn make_run(run: RunConfig) {
 
     /// Copies debugger scripts for `target` into the `sysroot` specified.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let host = self.host;
         let sysroot = self.sysroot;
         let dst = sysroot.join("lib/rustlib/etc");
         t!(fs::create_dir_all(&dst));
         let cp_debugger_script = |file: &str| {
-            build.install(&build.src.join("src/etc/").join(file), &dst, 0o644);
+            builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
         };
         if host.contains("windows-msvc") {
             // windbg debugger scripts
-            build.install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"),
+            builder.install(&builder.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"),
                 0o755);
 
             cp_debugger_script("natvis/intrinsic.natvis");
@@ -585,14 +579,14 @@ fn run(self, builder: &Builder) {
             cp_debugger_script("debugger_pretty_printers_common.py");
 
             // gdb debugger scripts
-            build.install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
+            builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
                     0o755);
 
             cp_debugger_script("gdb_load_rust_pretty_printers.py");
             cp_debugger_script("gdb_rust_pretty_printing.py");
 
             // lldb debugger scripts
-            build.install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"),
+            builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"),
                     0o755);
 
             cp_debugger_script("lldb_rust_formatters.py");
@@ -616,33 +610,33 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(Std {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
 
-        let name = pkgname(build, "rust-std");
-        build.info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target));
+        let name = pkgname(builder, "rust-std");
+        builder.info(&format!("Dist std stage{} ({} -> {})",
+            compiler.stage, &compiler.host, target));
 
         // The only true set of target libraries came from the build triple, so
         // let's reduce redundant work by only producing archives from that host.
-        if compiler.host != build.build {
-            build.info(&format!("\tskipping, not a build host"));
-            return distdir(build).join(format!("{}-{}.tar.gz", name, target));
+        if compiler.host != builder.config.build {
+            builder.info(&format!("\tskipping, not a build host"));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
         }
 
         // We want to package up as many target libraries as possible
         // for the `rust-std` package, so if this is a host target we
         // depend on librustc and otherwise we just depend on libtest.
-        if build.hosts.iter().any(|t| t == target) {
+        if builder.hosts.iter().any(|t| t == target) {
             builder.ensure(compile::Rustc { compiler, target });
         } else {
-            if build.no_std(target) == Some(true) {
+            if builder.no_std(target) == Some(true) {
                 // the `test` doesn't compile for no-std targets
                 builder.ensure(compile::Std { compiler, target });
             } else {
@@ -650,16 +644,16 @@ fn run(self, builder: &Builder) -> PathBuf {
             }
         }
 
-        let image = tmpdir(build).join(format!("{}-{}-image", name, target));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
         let _ = fs::remove_dir_all(&image);
 
         let dst = image.join("lib/rustlib").join(target);
         t!(fs::create_dir_all(&dst));
         let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
         src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
-        build.cp_filtered(&src, &dst, &|path| {
+        builder.cp_filtered(&src, &dst, &|path| {
             let name = path.file_name().and_then(|s| s.to_str());
-            name != Some(build.config.rust_codegen_backends_dir.as_str()) &&
+            name != Some(builder.config.rust_codegen_backends_dir.as_str()) &&
                 name != Some("bin")
 
         });
@@ -670,14 +664,14 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=std-is-standing-at-the-ready.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg(format!("--package-name={}-{}", name, target))
            .arg(format!("--component-name=rust-std-{}", target))
            .arg("--legacy-manifest-dirs=rustlib,cargo");
-        build.run(&mut cmd);
-        build.remove_dir(&image);
-        distdir(build).join(format!("{}-{}.tar.gz", name, target))
+        builder.run(&mut cmd);
+        builder.remove_dir(&image);
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
     }
 }
 
@@ -693,50 +687,49 @@ impl Step for Analysis {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("analysis").default_condition(builder.build.config.extended)
+        run.path("analysis").default_condition(builder.config.extended)
     }
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(Analysis {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
         });
     }
 
     /// Creates a tarball of save-analysis metadata, if available.
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
-        assert!(build.config.extended);
-        build.info(&format!("Dist analysis"));
-        let name = pkgname(build, "rust-analysis");
+        assert!(builder.config.extended);
+        builder.info(&format!("Dist analysis"));
+        let name = pkgname(builder, "rust-analysis");
 
-        if &compiler.host != build.build {
-            build.info(&format!("\tskipping, not a build host"));
-            return distdir(build).join(format!("{}-{}.tar.gz", name, target));
+        if &compiler.host != builder.config.build {
+            builder.info(&format!("\tskipping, not a build host"));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
         }
 
         builder.ensure(Std { compiler, target });
 
         // Package save-analysis from stage1 if not doing a full bootstrap, as the
         // stage2 artifacts is simply copied from stage1 in that case.
-        let compiler = if build.force_use_stage1(compiler, target) {
+        let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
             compiler.clone()
         };
 
-        let image = tmpdir(build).join(format!("{}-{}-image", name, target));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
 
-        let src = build.stage_out(compiler, Mode::Libstd)
-            .join(target).join(build.cargo_dir()).join("deps");
+        let src = builder.stage_out(compiler, Mode::Libstd)
+            .join(target).join(builder.cargo_dir()).join("deps");
 
         let image_src = src.join("save-analysis");
         let dst = image.join("lib/rustlib").join(target).join("analysis");
         t!(fs::create_dir_all(&dst));
-        build.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst));
-        build.cp_r(&image_src, &dst);
+        builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst));
+        builder.cp_r(&image_src, &dst);
 
         let mut cmd = rust_installer(builder);
         cmd.arg("generate")
@@ -744,18 +737,18 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=save-analysis-saved.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg(format!("--package-name={}-{}", name, target))
            .arg(format!("--component-name=rust-analysis-{}", target))
            .arg("--legacy-manifest-dirs=rustlib,cargo");
-        build.run(&mut cmd);
-        build.remove_dir(&image);
-        distdir(build).join(format!("{}-{}.tar.gz", name, target))
+        builder.run(&mut cmd);
+        builder.remove_dir(&image);
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
     }
 }
 
-fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_dir: &Path) {
+fn copy_src_dirs(builder: &Builder, src_dirs: &[&str], exclude_dirs: &[&str], dst_dir: &Path) {
     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
         let spath = match path.to_str() {
             Some(path) => path,
@@ -794,7 +787,8 @@ fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
     for item in src_dirs {
         let dst = &dst_dir.join(item);
         t!(fs::create_dir_all(dst));
-        build.cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
+        builder.cp_filtered(
+            &builder.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
     }
 }
 
@@ -817,11 +811,10 @@ fn make_run(run: RunConfig) {
 
     /// Creates the `rust-src` installer component
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
-        build.info(&format!("Dist src"));
+        builder.info(&format!("Dist src"));
 
-        let name = pkgname(build, "rust-src");
-        let image = tmpdir(build).join(format!("{}-image", name));
+        let name = pkgname(builder, "rust-src");
+        let image = tmpdir(builder).join(format!("{}-image", name));
         let _ = fs::remove_dir_all(&image);
 
         let dst = image.join("lib/rustlib/src");
@@ -866,9 +859,9 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src/jemalloc/test/unit",
         ];
 
-        copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
+        copy_src_dirs(builder, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
         for file in src_files.iter() {
-            build.copy(&build.src.join(file), &dst_src.join(file));
+            builder.copy(&builder.src.join(file), &dst_src.join(file));
         }
 
         // Create source tarball in rust-installer format
@@ -878,15 +871,15 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=Awesome-Source.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg(format!("--package-name={}", name))
            .arg("--component-name=rust-src")
            .arg("--legacy-manifest-dirs=rustlib,cargo");
-        build.run(&mut cmd);
+        builder.run(&mut cmd);
 
-        build.remove_dir(&image);
-        distdir(build).join(&format!("{}.tar.gz", name))
+        builder.remove_dir(&image);
+        distdir(builder).join(&format!("{}.tar.gz", name))
     }
 }
 
@@ -912,12 +905,11 @@ fn make_run(run: RunConfig) {
 
     /// Creates the plain source tarball
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
-        build.info(&format!("Create plain source tarball"));
+        builder.info(&format!("Create plain source tarball"));
 
         // Make sure that the root folder of tarball has the correct name
-        let plain_name = format!("{}-src", pkgname(build, "rustc"));
-        let plain_dst_src = tmpdir(build).join(&plain_name);
+        let plain_name = format!("{}-src", pkgname(builder, "rustc"));
+        let plain_dst_src = tmpdir(builder).join(&plain_name);
         let _ = fs::remove_dir_all(&plain_dst_src);
         t!(fs::create_dir_all(&plain_dst_src));
 
@@ -937,68 +929,68 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src",
         ];
 
-        copy_src_dirs(build, &src_dirs[..], &[], &plain_dst_src);
+        copy_src_dirs(builder, &src_dirs[..], &[], &plain_dst_src);
 
         // Copy the files normally
         for item in &src_files {
-            build.copy(&build.src.join(item), &plain_dst_src.join(item));
+            builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
         }
 
         // Create the version file
-        build.create(&plain_dst_src.join("version"), &build.rust_version());
-        if let Some(sha) = build.rust_sha() {
-            build.create(&plain_dst_src.join("git-commit-hash"), &sha);
+        builder.create(&plain_dst_src.join("version"), &builder.rust_version());
+        if let Some(sha) = builder.rust_sha() {
+            builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
         }
 
         // If we're building from git sources, we need to vendor a complete distribution.
-        if build.rust_info.is_git() {
+        if builder.rust_info.is_git() {
             // Get cargo-vendor installed, if it isn't already.
             let mut has_cargo_vendor = false;
-            let mut cmd = Command::new(&build.initial_cargo);
+            let mut cmd = Command::new(&builder.initial_cargo);
             for line in output(cmd.arg("install").arg("--list")).lines() {
                 has_cargo_vendor |= line.starts_with("cargo-vendor ");
             }
             if !has_cargo_vendor {
-                let mut cmd = Command::new(&build.initial_cargo);
+                let mut cmd = Command::new(&builder.initial_cargo);
                 cmd.arg("install")
                    .arg("--force")
                    .arg("--debug")
                    .arg("--vers").arg(CARGO_VENDOR_VERSION)
                    .arg("cargo-vendor")
-                   .env("RUSTC", &build.initial_rustc);
-                if let Some(dir) = build.openssl_install_dir(build.config.build) {
+                   .env("RUSTC", &builder.initial_rustc);
+                if let Some(dir) = builder.openssl_install_dir(builder.config.build) {
                     builder.ensure(native::Openssl {
-                        target: build.config.build,
+                        target: builder.config.build,
                     });
                     cmd.env("OPENSSL_DIR", dir);
                 }
-                build.run(&mut cmd);
+                builder.run(&mut cmd);
             }
 
             // Vendor all Cargo dependencies
-            let mut cmd = Command::new(&build.initial_cargo);
+            let mut cmd = Command::new(&builder.initial_cargo);
             cmd.arg("vendor")
                .current_dir(&plain_dst_src.join("src"));
-            build.run(&mut cmd);
+            builder.run(&mut cmd);
         }
 
         // Create plain source tarball
-        let plain_name = format!("rustc-{}-src", build.rust_package_vers());
-        let mut tarball = distdir(build).join(&format!("{}.tar.gz", plain_name));
+        let plain_name = format!("rustc-{}-src", builder.rust_package_vers());
+        let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name));
         tarball.set_extension(""); // strip .gz
         tarball.set_extension(""); // strip .tar
         if let Some(dir) = tarball.parent() {
-            build.create_dir(&dir);
+            builder.create_dir(&dir);
         }
-        build.info(&format!("running installer"));
+        builder.info(&format!("running installer"));
         let mut cmd = rust_installer(builder);
         cmd.arg("tarball")
            .arg("--input").arg(&plain_name)
            .arg("--output").arg(&tarball)
            .arg("--work-dir=.")
-           .current_dir(tmpdir(build));
-        build.run(&mut cmd);
-        distdir(build).join(&format!("{}.tar.gz", plain_name))
+           .current_dir(tmpdir(builder));
+        builder.run(&mut cmd);
+        distdir(builder).join(&format!("{}.tar.gz", plain_name))
     }
 }
 
@@ -1043,52 +1035,51 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
 
-        build.info(&format!("Dist cargo stage{} ({})", stage, target));
-        let src = build.src.join("src/tools/cargo");
+        builder.info(&format!("Dist cargo stage{} ({})", stage, target));
+        let src = builder.src.join("src/tools/cargo");
         let etc = src.join("src/etc");
-        let release_num = build.release_num("cargo");
-        let name = pkgname(build, "cargo");
-        let version = builder.cargo_info.version(build, &release_num);
+        let release_num = builder.release_num("cargo");
+        let name = pkgname(builder, "cargo");
+        let version = builder.cargo_info.version(builder, &release_num);
 
-        let tmp = tmpdir(build);
+        let tmp = tmpdir(builder);
         let image = tmp.join("cargo-image");
         drop(fs::remove_dir_all(&image));
-        build.create_dir(&image);
+        builder.create_dir(&image);
 
         // Prepare the image directory
-        build.create_dir(&image.join("share/zsh/site-functions"));
-        build.create_dir(&image.join("etc/bash_completion.d"));
+        builder.create_dir(&image.join("share/zsh/site-functions"));
+        builder.create_dir(&image.join("etc/bash_completion.d"));
         let cargo = builder.ensure(tool::Cargo {
-            compiler: builder.compiler(stage, build.build),
+            compiler: builder.compiler(stage, builder.config.build),
             target
         });
-        build.install(&cargo, &image.join("bin"), 0o755);
+        builder.install(&cargo, &image.join("bin"), 0o755);
         for man in t!(etc.join("man").read_dir()) {
             let man = t!(man);
-            build.install(&man.path(), &image.join("share/man/man1"), 0o644);
+            builder.install(&man.path(), &image.join("share/man/man1"), 0o644);
         }
-        build.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
-        build.copy(&etc.join("cargo.bashcomp.sh"),
+        builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
+        builder.copy(&etc.join("cargo.bashcomp.sh"),
              &image.join("etc/bash_completion.d/cargo"));
         let doc = image.join("share/doc/cargo");
-        build.install(&src.join("README.md"), &doc, 0o644);
-        build.install(&src.join("LICENSE-MIT"), &doc, 0o644);
-        build.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
-        build.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
+        builder.install(&src.join("README.md"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
 
         // Prepare the overlay
         let overlay = tmp.join("cargo-overlay");
         drop(fs::remove_dir_all(&overlay));
-        build.create_dir(&overlay);
-        build.install(&src.join("README.md"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
-        build.create(&overlay.join("version"), &version);
+        builder.create_dir(&overlay);
+        builder.install(&src.join("README.md"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
+        builder.create(&overlay.join("version"), &version);
 
         // Generate the installer tarball
         let mut cmd = rust_installer(builder);
@@ -1097,14 +1088,14 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=Rust-is-ready-to-roll.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg("--non-installed-overlay").arg(&overlay)
            .arg(format!("--package-name={}-{}", name, target))
            .arg("--component-name=cargo")
            .arg("--legacy-manifest-dirs=rustlib,cargo");
-        build.run(&mut cmd);
-        distdir(build).join(format!("{}-{}.tar.gz", name, target))
+        builder.run(&mut cmd);
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
     }
 }
 
@@ -1130,18 +1121,17 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) -> Option<PathBuf> {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
-        assert!(build.config.extended);
+        assert!(builder.config.extended);
 
-        build.info(&format!("Dist RLS stage{} ({})", stage, target));
-        let src = build.src.join("src/tools/rls");
-        let release_num = build.release_num("rls");
-        let name = pkgname(build, "rls");
-        let version = build.rls_info.version(build, &release_num);
+        builder.info(&format!("Dist RLS stage{} ({})", stage, target));
+        let src = builder.src.join("src/tools/rls");
+        let release_num = builder.release_num("rls");
+        let name = pkgname(builder, "rls");
+        let version = builder.rls_info.version(builder, &release_num);
 
-        let tmp = tmpdir(build);
+        let tmp = tmpdir(builder);
         let image = tmp.join("rls-image");
         drop(fs::remove_dir_all(&image));
         t!(fs::create_dir_all(&image));
@@ -1150,24 +1140,24 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         // We expect RLS to build, because we've exited this step above if tool
         // state for RLS isn't testing.
         let rls = builder.ensure(tool::Rls {
-            compiler: builder.compiler(stage, build.build),
+            compiler: builder.compiler(stage, builder.config.build),
             target, extra_features: Vec::new()
         }).or_else(|| { println!("Unable to build RLS, skipping dist"); None })?;
 
-        build.install(&rls, &image.join("bin"), 0o755);
+        builder.install(&rls, &image.join("bin"), 0o755);
         let doc = image.join("share/doc/rls");
-        build.install(&src.join("README.md"), &doc, 0o644);
-        build.install(&src.join("LICENSE-MIT"), &doc, 0o644);
-        build.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+        builder.install(&src.join("README.md"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
 
         // Prepare the overlay
         let overlay = tmp.join("rls-overlay");
         drop(fs::remove_dir_all(&overlay));
         t!(fs::create_dir_all(&overlay));
-        build.install(&src.join("README.md"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
-        build.create(&overlay.join("version"), &version);
+        builder.install(&src.join("README.md"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+        builder.create(&overlay.join("version"), &version);
 
         // Generate the installer tarball
         let mut cmd = rust_installer(builder);
@@ -1176,15 +1166,15 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=RLS-ready-to-serve.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg("--non-installed-overlay").arg(&overlay)
            .arg(format!("--package-name={}-{}", name, target))
            .arg("--legacy-manifest-dirs=rustlib,cargo")
            .arg("--component-name=rls-preview");
 
-        build.run(&mut cmd);
-        Some(distdir(build).join(format!("{}-{}.tar.gz", name, target)))
+        builder.run(&mut cmd);
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
     }
 }
 
@@ -1211,46 +1201,45 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) -> Option<PathBuf> {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
 
-        build.info(&format!("Dist Rustfmt stage{} ({})", stage, target));
-        let src = build.src.join("src/tools/rustfmt");
-        let release_num = build.release_num("rustfmt");
-        let name = pkgname(build, "rustfmt");
-        let version = build.rustfmt_info.version(build, &release_num);
+        builder.info(&format!("Dist Rustfmt stage{} ({})", stage, target));
+        let src = builder.src.join("src/tools/rustfmt");
+        let release_num = builder.release_num("rustfmt");
+        let name = pkgname(builder, "rustfmt");
+        let version = builder.rustfmt_info.version(builder, &release_num);
 
-        let tmp = tmpdir(build);
+        let tmp = tmpdir(builder);
         let image = tmp.join("rustfmt-image");
         drop(fs::remove_dir_all(&image));
-        build.create_dir(&image);
+        builder.create_dir(&image);
 
         // Prepare the image directory
         let rustfmt = builder.ensure(tool::Rustfmt {
-            compiler: builder.compiler(stage, build.build),
+            compiler: builder.compiler(stage, builder.config.build),
             target, extra_features: Vec::new()
         }).or_else(|| { println!("Unable to build Rustfmt, skipping dist"); None })?;
         let cargofmt = builder.ensure(tool::Cargofmt {
-            compiler: builder.compiler(stage, build.build),
+            compiler: builder.compiler(stage, builder.config.build),
             target, extra_features: Vec::new()
         }).or_else(|| { println!("Unable to build Cargofmt, skipping dist"); None })?;
 
-        build.install(&rustfmt, &image.join("bin"), 0o755);
-        build.install(&cargofmt, &image.join("bin"), 0o755);
+        builder.install(&rustfmt, &image.join("bin"), 0o755);
+        builder.install(&cargofmt, &image.join("bin"), 0o755);
         let doc = image.join("share/doc/rustfmt");
-        build.install(&src.join("README.md"), &doc, 0o644);
-        build.install(&src.join("LICENSE-MIT"), &doc, 0o644);
-        build.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+        builder.install(&src.join("README.md"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+        builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
 
         // Prepare the overlay
         let overlay = tmp.join("rustfmt-overlay");
         drop(fs::remove_dir_all(&overlay));
-        build.create_dir(&overlay);
-        build.install(&src.join("README.md"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
-        build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
-        build.create(&overlay.join("version"), &version);
+        builder.create_dir(&overlay);
+        builder.install(&src.join("README.md"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+        builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+        builder.create(&overlay.join("version"), &version);
 
         // Generate the installer tarball
         let mut cmd = rust_installer(builder);
@@ -1259,15 +1248,15 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
            .arg("--rel-manifest-dir=rustlib")
            .arg("--success-message=rustfmt-ready-to-fmt.")
            .arg("--image-dir").arg(&image)
-           .arg("--work-dir").arg(&tmpdir(build))
-           .arg("--output-dir").arg(&distdir(build))
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
            .arg("--non-installed-overlay").arg(&overlay)
            .arg(format!("--package-name={}-{}", name, target))
            .arg("--legacy-manifest-dirs=rustlib,cargo")
            .arg("--component-name=rustfmt-preview");
 
-        build.run(&mut cmd);
-        Some(distdir(build).join(format!("{}-{}.tar.gz", name, target)))
+        builder.run(&mut cmd);
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
     }
 }
 
@@ -1291,18 +1280,17 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     fn make_run(run: RunConfig) {
         run.builder.ensure(Extended {
             stage: run.builder.top_stage,
-            host: run.builder.build.build,
+            host: run.builder.config.build,
             target: run.target,
         });
     }
 
     /// Creates a combined installer for the specified target in the provided stage.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
 
-        build.info(&format!("Dist extended stage{} ({})", stage, target));
+        builder.info(&format!("Dist extended stage{} ({})", stage, target));
 
         let rustc_installer = builder.ensure(Rustc {
             compiler: builder.compiler(stage, target),
@@ -1322,21 +1310,21 @@ fn run(self, builder: &Builder) {
             target,
         });
 
-        let tmp = tmpdir(build);
+        let tmp = tmpdir(builder);
         let overlay = tmp.join("extended-overlay");
-        let etc = build.src.join("src/etc/installer");
+        let etc = builder.src.join("src/etc/installer");
         let work = tmp.join("work");
 
         let _ = fs::remove_dir_all(&overlay);
-        build.install(&build.src.join("COPYRIGHT"), &overlay, 0o644);
-        build.install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644);
-        build.install(&build.src.join("LICENSE-MIT"), &overlay, 0o644);
-        let version = build.rust_version();
-        build.create(&overlay.join("version"), &version);
-        if let Some(sha) = build.rust_sha() {
-            build.create(&overlay.join("git-commit-hash"), &sha);
+        builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644);
+        builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644);
+        builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644);
+        let version = builder.rust_version();
+        builder.create(&overlay.join("version"), &version);
+        if let Some(sha) = builder.rust_sha() {
+            builder.create(&overlay.join("git-commit-hash"), &sha);
         }
-        build.install(&etc.join("README.md"), &overlay, 0o644);
+        builder.install(&etc.join("README.md"), &overlay, 0o644);
 
         // When rust-std package split from rustc, we needed to ensure that during
         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
@@ -1349,7 +1337,7 @@ fn run(self, builder: &Builder) {
         tarballs.extend(rustfmt_installer.clone());
         tarballs.push(analysis_installer);
         tarballs.push(std_installer);
-        if build.config.docs {
+        if builder.config.docs {
             tarballs.push(docs_installer);
         }
         if target.contains("pc-windows-gnu") {
@@ -1367,17 +1355,17 @@ fn run(self, builder: &Builder) {
             .arg("--rel-manifest-dir=rustlib")
             .arg("--success-message=Rust-is-ready-to-roll.")
             .arg("--work-dir").arg(&work)
-            .arg("--output-dir").arg(&distdir(build))
-            .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target))
+            .arg("--output-dir").arg(&distdir(builder))
+            .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--input-tarballs").arg(input_tarballs)
             .arg("--non-installed-overlay").arg(&overlay);
-        build.run(&mut cmd);
+        builder.run(&mut cmd);
 
         let mut license = String::new();
-        license += &build.read(&build.src.join("COPYRIGHT"));
-        license += &build.read(&build.src.join("LICENSE-APACHE"));
-        license += &build.read(&build.src.join("LICENSE-MIT"));
+        license += &builder.read(&builder.src.join("COPYRIGHT"));
+        license += &builder.read(&builder.src.join("LICENSE-APACHE"));
+        license += &builder.read(&builder.src.join("LICENSE-MIT"));
         license.push_str("\n");
         license.push_str("\n");
 
@@ -1432,14 +1420,14 @@ fn filter(contents: &str, marker: &str) -> String {
                     .arg("--scripts").arg(pkg.join(component))
                     .arg("--nopayload")
                     .arg(pkg.join(component).with_extension("pkg"));
-                build.run(&mut cmd);
+                builder.run(&mut cmd);
             };
 
             let prepare = |name: &str| {
-                build.create_dir(&pkg.join(name));
-                build.cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)),
+                builder.create_dir(&pkg.join(name));
+                builder.cp_r(&work.join(&format!("{}-{}", pkgname(builder, name), target)),
                         &pkg.join(name));
-                build.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
+                builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
                 pkgbuild(name);
             };
             prepare("rustc");
@@ -1453,20 +1441,20 @@ fn filter(contents: &str, marker: &str) -> String {
             }
 
             // create an 'uninstall' package
-            build.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
+            builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
             pkgbuild("uninstall");
 
-            build.create_dir(&pkg.join("res"));
-            build.create(&pkg.join("res/LICENSE.txt"), &license);
-            build.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
+            builder.create_dir(&pkg.join("res"));
+            builder.create(&pkg.join("res/LICENSE.txt"), &license);
+            builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
             let mut cmd = Command::new("productbuild");
             cmd.arg("--distribution").arg(xform(&etc.join("pkg/Distribution.xml")))
                 .arg("--resources").arg(pkg.join("res"))
-                .arg(distdir(build).join(format!("{}-{}.pkg",
-                                                    pkgname(build, "rust"),
+                .arg(distdir(builder).join(format!("{}-{}.pkg",
+                                                    pkgname(builder, "rust"),
                                                     target)))
                 .arg("--package-path").arg(&pkg);
-            build.run(&mut cmd);
+            builder.run(&mut cmd);
         }
 
         if target.contains("windows") {
@@ -1474,7 +1462,7 @@ fn filter(contents: &str, marker: &str) -> String {
             let _ = fs::remove_dir_all(&exe);
 
             let prepare = |name: &str| {
-                build.create_dir(&exe.join(name));
+                builder.create_dir(&exe.join(name));
                 let dir = if name == "rust-std" || name == "rust-analysis" {
                     format!("{}-{}", name, target)
                 } else if name == "rls" {
@@ -1482,10 +1470,10 @@ fn filter(contents: &str, marker: &str) -> String {
                 } else {
                     name.to_string()
                 };
-                build.cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target))
+                builder.cp_r(&work.join(&format!("{}-{}", pkgname(builder, name), target))
                             .join(dir),
                         &exe.join(name));
-                build.remove(&exe.join(name).join("manifest.in"));
+                builder.remove(&exe.join(name).join("manifest.in"));
             };
             prepare("rustc");
             prepare("cargo");
@@ -1499,11 +1487,11 @@ fn filter(contents: &str, marker: &str) -> String {
                 prepare("rust-mingw");
             }
 
-            build.install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644);
-            build.install(&etc.join("exe/modpath.iss"), &exe, 0o644);
-            build.install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
-            build.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
-            build.create(&exe.join("LICENSE.txt"), &license);
+            builder.install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644);
+            builder.install(&etc.join("exe/modpath.iss"), &exe, 0o644);
+            builder.install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
+            builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
+            builder.create(&exe.join("LICENSE.txt"), &license);
 
             // Generate exe installer
             let mut cmd = Command::new("iscc");
@@ -1512,10 +1500,10 @@ fn filter(contents: &str, marker: &str) -> String {
             if target.contains("windows-gnu") {
                 cmd.arg("/dMINGW");
             }
-            add_env(build, &mut cmd, target);
-            build.run(&mut cmd);
-            build.install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)),
-                    &distdir(build),
+            add_env(builder, &mut cmd, target);
+            builder.run(&mut cmd);
+            builder.install(&exe.join(format!("{}-{}.exe", pkgname(builder, "rust"), target)),
+                    &distdir(builder),
                     0o755);
 
             // Generate msi installer
@@ -1525,7 +1513,7 @@ fn filter(contents: &str, marker: &str) -> String {
             let light = wix.join("bin/light.exe");
 
             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
-            build.run(Command::new(&heat)
+            builder.run(Command::new(&heat)
                             .current_dir(&exe)
                             .arg("dir")
                             .arg("rustc")
@@ -1534,7 +1522,7 @@ fn filter(contents: &str, marker: &str) -> String {
                             .arg("-dr").arg("Rustc")
                             .arg("-var").arg("var.RustcDir")
                             .arg("-out").arg(exe.join("RustcGroup.wxs")));
-            build.run(Command::new(&heat)
+            builder.run(Command::new(&heat)
                             .current_dir(&exe)
                             .arg("dir")
                             .arg("rust-docs")
@@ -1544,7 +1532,7 @@ fn filter(contents: &str, marker: &str) -> String {
                             .arg("-var").arg("var.DocsDir")
                             .arg("-out").arg(exe.join("DocsGroup.wxs"))
                             .arg("-t").arg(etc.join("msi/squash-components.xsl")));
-            build.run(Command::new(&heat)
+            builder.run(Command::new(&heat)
                             .current_dir(&exe)
                             .arg("dir")
                             .arg("cargo")
@@ -1554,7 +1542,7 @@ fn filter(contents: &str, marker: &str) -> String {
                             .arg("-var").arg("var.CargoDir")
                             .arg("-out").arg(exe.join("CargoGroup.wxs"))
                             .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
-            build.run(Command::new(&heat)
+            builder.run(Command::new(&heat)
                             .current_dir(&exe)
                             .arg("dir")
                             .arg("rust-std")
@@ -1564,7 +1552,7 @@ fn filter(contents: &str, marker: &str) -> String {
                             .arg("-var").arg("var.StdDir")
                             .arg("-out").arg(exe.join("StdGroup.wxs")));
             if rls_installer.is_some() {
-                build.run(Command::new(&heat)
+                builder.run(Command::new(&heat)
                                 .current_dir(&exe)
                                 .arg("dir")
                                 .arg("rls")
@@ -1575,7 +1563,7 @@ fn filter(contents: &str, marker: &str) -> String {
                                 .arg("-out").arg(exe.join("RlsGroup.wxs"))
                                 .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
             }
-            build.run(Command::new(&heat)
+            builder.run(Command::new(&heat)
                             .current_dir(&exe)
                             .arg("dir")
                             .arg("rust-analysis")
@@ -1586,7 +1574,7 @@ fn filter(contents: &str, marker: &str) -> String {
                             .arg("-out").arg(exe.join("AnalysisGroup.wxs"))
                             .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
             if target.contains("windows-gnu") {
-                build.run(Command::new(&heat)
+                builder.run(Command::new(&heat)
                                 .current_dir(&exe)
                                 .arg("dir")
                                 .arg("rust-mingw")
@@ -1612,7 +1600,7 @@ fn filter(contents: &str, marker: &str) -> String {
                     .arg("-arch").arg(&arch)
                     .arg("-out").arg(&output)
                     .arg(&input);
-                add_env(build, &mut cmd, target);
+                add_env(builder, &mut cmd, target);
 
                 if rls_installer.is_some() {
                     cmd.arg("-dRlsDir=rls");
@@ -1620,7 +1608,7 @@ fn filter(contents: &str, marker: &str) -> String {
                 if target.contains("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
-                build.run(&mut cmd);
+                builder.run(&mut cmd);
             };
             candle(&xform(&etc.join("msi/rust.wxs")));
             candle(&etc.join("msi/ui.wxs"));
@@ -1638,11 +1626,11 @@ fn filter(contents: &str, marker: &str) -> String {
                 candle("GccGroup.wxs".as_ref());
             }
 
-            build.create(&exe.join("LICENSE.rtf"), &rtf);
-            build.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
-            build.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
+            builder.create(&exe.join("LICENSE.rtf"), &rtf);
+            builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
+            builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
 
-            let filename = format!("{}-{}.msi", pkgname(build, "rust"), target);
+            let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target);
             let mut cmd = Command::new(&light);
             cmd.arg("-nologo")
                 .arg("-ext").arg("WixUIExtension")
@@ -1668,28 +1656,28 @@ fn filter(contents: &str, marker: &str) -> String {
             // ICE57 wrongly complains about the shortcuts
             cmd.arg("-sice:ICE57");
 
-            build.run(&mut cmd);
+            builder.run(&mut cmd);
 
-            if !build.config.dry_run {
-                t!(fs::rename(exe.join(&filename), distdir(build).join(&filename)));
+            if !builder.config.dry_run {
+                t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
             }
         }
     }
 }
 
-fn add_env(build: &Build, cmd: &mut Command, target: Interned<String>) {
+fn add_env(builder: &Builder, cmd: &mut Command, target: Interned<String>) {
     let mut parts = channel::CFG_RELEASE_NUM.split('.');
-    cmd.env("CFG_RELEASE_INFO", build.rust_version())
+    cmd.env("CFG_RELEASE_INFO", builder.rust_version())
        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
-       .env("CFG_RELEASE", build.rust_release())
+       .env("CFG_RELEASE", builder.rust_release())
        .env("CFG_VER_MAJOR", parts.next().unwrap())
        .env("CFG_VER_MINOR", parts.next().unwrap())
        .env("CFG_VER_PATCH", parts.next().unwrap())
        .env("CFG_VER_BUILD", "0") // just needed to build
-       .env("CFG_PACKAGE_VERS", build.rust_package_vers())
-       .env("CFG_PACKAGE_NAME", pkgname(build, "rust"))
+       .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
+       .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
        .env("CFG_BUILD", target)
-       .env("CFG_CHANNEL", &build.config.channel);
+       .env("CFG_CHANNEL", &builder.config.channel);
 
     if target.contains("windows-gnu") {
        cmd.env("CFG_MINGW", "1")
@@ -1722,18 +1710,17 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let mut cmd = builder.tool_cmd(Tool::BuildManifest);
-        if build.config.dry_run {
+        if builder.config.dry_run {
             return;
         }
-        let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
+        let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
             panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
         });
-        let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
+        let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
             panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
         });
-        let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
+        let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
             panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
         });
         let mut pass = String::new();
@@ -1742,15 +1729,15 @@ fn run(self, builder: &Builder) {
         let today = output(Command::new("date").arg("+%Y-%m-%d"));
 
         cmd.arg(sign);
-        cmd.arg(distdir(build));
+        cmd.arg(distdir(builder));
         cmd.arg(today.trim());
-        cmd.arg(build.rust_package_vers());
-        cmd.arg(build.package_vers(&build.release_num("cargo")));
-        cmd.arg(build.package_vers(&build.release_num("rls")));
-        cmd.arg(build.package_vers(&build.release_num("rustfmt")));
+        cmd.arg(builder.rust_package_vers());
+        cmd.arg(builder.package_vers(&builder.release_num("cargo")));
+        cmd.arg(builder.package_vers(&builder.release_num("rls")));
+        cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
         cmd.arg(addr);
 
-        build.create_dir(&distdir(build));
+        builder.create_dir(&distdir(builder));
 
         let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
         t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
index 620e125a43da1977f1bb01e748d0525eae6ea078..ae22260c564edf0bb8b5dea95a625246d8b5b145 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Documentation generation for rustbuild.
+//! Documentation generation for rustbuilder.
 //!
 //! This module implements generation for all bits and pieces of documentation
 //! for the Rust project. This notably includes suites like the rust book, the
@@ -23,7 +23,7 @@
 use std::io;
 use std::path::{PathBuf, Path};
 
-use {Build, Mode};
+use Mode;
 use build_helper::up_to_date;
 
 use util::symlink_dir;
@@ -47,7 +47,7 @@ impl Step for $name {
 
             fn should_run(run: ShouldRun) -> ShouldRun {
                 let builder = run.builder;
-                run.path($path).default_condition(builder.build.config.docs)
+                run.path($path).default_condition(builder.config.docs)
             }
 
             fn make_run(run: RunConfig) {
@@ -94,7 +94,7 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// This will not actually generate any documentation if the documentation has
     /// already been generated.
     fn run(self, builder: &Builder) {
-        let src = builder.build.src.join("src/doc");
+        let src = builder.src.join("src/doc");
         builder.ensure(RustbookSrc {
             target: self.target,
             name: self.name,
@@ -114,7 +114,7 @@ impl Step for UnstableBook {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/doc/unstable-book").default_condition(builder.build.config.docs)
+        run.path("src/doc/unstable-book").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -130,7 +130,7 @@ fn run(self, builder: &Builder) {
         builder.ensure(RustbookSrc {
             target: self.target,
             name: INTERNER.intern_str("unstable-book"),
-            src: builder.build.md_doc_out(self.target),
+            src: builder.md_doc_out(self.target),
         })
     }
 }
@@ -147,7 +147,7 @@ impl Step for CargoBook {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/tools/cargo/src/doc/book").default_condition(builder.build.config.docs)
+        run.path("src/tools/cargo/src/doc/book").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -158,22 +158,20 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
-
         let target = self.target;
         let name = self.name;
-        let src = build.src.join("src/tools/cargo/src/doc");
+        let src = builder.src.join("src/tools/cargo/src/doc");
 
-        let out = build.doc_out(target);
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
 
         let out = out.join(name);
 
-        build.info(&format!("Cargo Book ({}) - {}", target, name));
+        builder.info(&format!("Cargo Book ({}) - {}", target, name));
 
         let _ = fs::remove_dir_all(&out);
 
-        build.run(builder.tool_cmd(Tool::Rustbook)
+        builder.run(builder.tool_cmd(Tool::Rustbook)
                        .arg("build")
                        .arg(&src)
                        .arg("-d")
@@ -200,11 +198,10 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// This will not actually generate any documentation if the documentation has
     /// already been generated.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
         let name = self.name;
         let src = self.src;
-        let out = build.doc_out(target);
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
 
         let out = out.join(name);
@@ -215,9 +212,9 @@ fn run(self, builder: &Builder) {
         if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
             return
         }
-        build.info(&format!("Rustbook ({}) - {}", target, name));
+        builder.info(&format!("Rustbook ({}) - {}", target, name));
         let _ = fs::remove_dir_all(&out);
-        build.run(rustbook_cmd
+        builder.run(rustbook_cmd
                        .arg("build")
                        .arg(&src)
                        .arg("-d")
@@ -238,12 +235,12 @@ impl Step for TheBook {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/doc/book").default_condition(builder.build.config.docs)
+        run.path("src/doc/book").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(TheBook {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
             name: "book",
         });
@@ -259,7 +256,6 @@ fn make_run(run: RunConfig) {
     /// * Index page
     /// * Redirect pages
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
         let name = self.name;
@@ -283,12 +279,12 @@ fn run(self, builder: &Builder) {
 
         // build the index page
         let index = format!("{}/index.md", name);
-        build.info(&format!("Documenting book index ({})", target));
+        builder.info(&format!("Documenting book index ({})", target));
         invoke_rustdoc(builder, compiler, target, &index);
 
         // build the redirect pages
-        build.info(&format!("Documenting book redirect pages ({})", target));
-        for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) {
+        builder.info(&format!("Documenting book redirect pages ({})", target));
+        for file in t!(fs::read_dir(builder.src.join("src/doc/book/redirects"))) {
             let file = t!(file);
             let path = file.path();
             let path = path.to_str().unwrap();
@@ -299,13 +295,12 @@ fn run(self, builder: &Builder) {
 }
 
 fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String>, markdown: &str) {
-    let build = builder.build;
-    let out = build.doc_out(target);
+    let out = builder.doc_out(target);
 
-    let path = build.src.join("src/doc").join(markdown);
+    let path = builder.src.join("src/doc").join(markdown);
 
-    let favicon = build.src.join("src/doc/favicon.inc");
-    let footer = build.src.join("src/doc/footer.inc");
+    let favicon = builder.src.join("src/doc/favicon.inc");
+    let footer = builder.src.join("src/doc/footer.inc");
     let version_info = out.join("version_info.html");
 
     let mut cmd = builder.rustdoc_cmd(compiler.host);
@@ -323,7 +318,7 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String
         .arg("--markdown-css")
         .arg("../rust.css");
 
-    build.run(&mut cmd);
+    builder.run(&mut cmd);
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -338,12 +333,12 @@ impl Step for Standalone {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/doc").default_condition(builder.build.config.docs)
+        run.path("src/doc").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(Standalone {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
         });
     }
@@ -357,31 +352,30 @@ fn make_run(run: RunConfig) {
     ///
     /// In the end, this is just a glorified wrapper around rustdoc!
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
         let compiler = self.compiler;
-        build.info(&format!("Documenting standalone ({})", target));
-        let out = build.doc_out(target);
+        builder.info(&format!("Documenting standalone ({})", target));
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
 
-        let favicon = build.src.join("src/doc/favicon.inc");
-        let footer = build.src.join("src/doc/footer.inc");
-        let full_toc = build.src.join("src/doc/full-toc.inc");
-        t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css")));
+        let favicon = builder.src.join("src/doc/favicon.inc");
+        let footer = builder.src.join("src/doc/footer.inc");
+        let full_toc = builder.src.join("src/doc/full-toc.inc");
+        t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
 
-        let version_input = build.src.join("src/doc/version_info.html.template");
+        let version_input = builder.src.join("src/doc/version_info.html.template");
         let version_info = out.join("version_info.html");
 
-        if !build.config.dry_run && !up_to_date(&version_input, &version_info) {
+        if !builder.config.dry_run && !up_to_date(&version_input, &version_info) {
             let mut info = String::new();
             t!(t!(File::open(&version_input)).read_to_string(&mut info));
-            let info = info.replace("VERSION", &build.rust_release())
-                           .replace("SHORT_HASH", build.rust_info.sha_short().unwrap_or(""))
-                           .replace("STAMP", build.rust_info.sha().unwrap_or(""));
+            let info = info.replace("VERSION", &builder.rust_release())
+                           .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or(""))
+                           .replace("STAMP", builder.rust_info.sha().unwrap_or(""));
             t!(t!(File::create(&version_info)).write_all(info.as_bytes()));
         }
 
-        for file in t!(fs::read_dir(build.src.join("src/doc"))) {
+        for file in t!(fs::read_dir(builder.src.join("src/doc"))) {
             let file = t!(file);
             let path = file.path();
             let filename = path.file_name().unwrap().to_str().unwrap();
@@ -396,7 +390,7 @@ fn run(self, builder: &Builder) {
                up_to_date(&favicon, &html) &&
                up_to_date(&full_toc, &html) &&
                up_to_date(&version_info, &html) &&
-               (build.config.dry_run || up_to_date(&rustdoc, &html)) {
+               (builder.config.dry_run || up_to_date(&rustdoc, &html)) {
                 continue
             }
 
@@ -416,7 +410,7 @@ fn run(self, builder: &Builder) {
             } else {
                 cmd.arg("--markdown-css").arg("rust.css");
             }
-            build.run(&mut cmd);
+            builder.run(&mut cmd);
         }
     }
 }
@@ -433,7 +427,7 @@ impl Step for Std {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.all_krates("std").default_condition(builder.build.config.docs)
+        run.all_krates("std").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -448,22 +442,21 @@ fn make_run(run: RunConfig) {
     /// This will generate all documentation for the standard library and its
     /// dependencies. This is largely just a wrapper around `cargo doc`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
-        build.info(&format!("Documenting stage{} std ({})", stage, target));
-        let out = build.doc_out(target);
+        builder.info(&format!("Documenting stage{} std ({})", stage, target));
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
-        let compiler = builder.compiler(stage, build.build);
+        let compiler = builder.compiler(stage, builder.config.build);
         let rustdoc = builder.rustdoc(compiler.host);
-        let compiler = if build.force_use_stage1(compiler, target) {
+        let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
             compiler
         };
 
         builder.ensure(compile::Std { compiler, target });
-        let out_dir = build.stage_out(compiler, Mode::Libstd)
+        let out_dir = builder.stage_out(compiler, Mode::Libstd)
                            .join(target).join("doc");
 
         // Here what we're doing is creating a *symlink* (directory junction on
@@ -479,9 +472,9 @@ fn run(self, builder: &Builder) {
         //
         // This way rustdoc generates output directly into the output, and rustdoc
         // will also directly handle merging.
-        let my_out = build.crate_doc_out(target);
-        build.clear_if_dirty(&my_out, &rustdoc);
-        t!(symlink_dir_force(&build.config, &my_out, &out_dir));
+        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::Libstd, target, "doc");
         compile::std_cargo(builder, &compiler, target, &mut cargo);
@@ -497,8 +490,8 @@ fn run(self, builder: &Builder) {
             t!(fs::create_dir_all(out_dir.join(krate)));
         }
 
-        build.run(&mut cargo);
-        build.cp_r(&my_out, &out);
+        builder.run(&mut cargo);
+        builder.cp_r(&my_out, &out);
     }
 }
 
@@ -514,7 +507,7 @@ impl Step for Test {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.krate("test").default_condition(builder.build.config.docs)
+        run.krate("test").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -529,15 +522,14 @@ fn make_run(run: RunConfig) {
     /// This will generate all documentation for libtest and its dependencies. This
     /// is largely just a wrapper around `cargo doc`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
-        build.info(&format!("Documenting stage{} test ({})", stage, target));
-        let out = build.doc_out(target);
+        builder.info(&format!("Documenting stage{} test ({})", stage, target));
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
-        let compiler = builder.compiler(stage, build.build);
+        let compiler = builder.compiler(stage, builder.config.build);
         let rustdoc = builder.rustdoc(compiler.host);
-        let compiler = if build.force_use_stage1(compiler, target) {
+        let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
             compiler
@@ -547,21 +539,21 @@ fn run(self, builder: &Builder) {
         builder.ensure(Std { stage, target });
 
         builder.ensure(compile::Test { compiler, target });
-        let out_dir = build.stage_out(compiler, Mode::Libtest)
+        let out_dir = builder.stage_out(compiler, Mode::Libtest)
                            .join(target).join("doc");
 
         // See docs in std above for why we symlink
-        let my_out = build.crate_doc_out(target);
-        build.clear_if_dirty(&my_out, &rustdoc);
+        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::Libtest, target, "doc");
-        compile::test_cargo(build, &compiler, target, &mut cargo);
+        compile::test_cargo(builder, &compiler, target, &mut cargo);
 
         cargo.arg("--no-deps").arg("-p").arg("test");
 
-        build.run(&mut cargo);
-        build.cp_r(&my_out, &out);
+        builder.run(&mut cargo);
+        builder.cp_r(&my_out, &out);
     }
 }
 
@@ -578,7 +570,7 @@ impl Step for WhitelistedRustc {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.krate("rustc-main").default_condition(builder.build.config.docs)
+        run.krate("rustc-main").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -598,15 +590,14 @@ fn make_run(run: RunConfig) {
     /// here as we want to be able to keep it separate from the standard
     /// documentation. This is largely just a wrapper around `cargo doc`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
-        build.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target));
-        let out = build.doc_out(target);
+        builder.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target));
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
-        let compiler = builder.compiler(stage, build.build);
+        let compiler = builder.compiler(stage, builder.config.build);
         let rustdoc = builder.rustdoc(compiler.host);
-        let compiler = if build.force_use_stage1(compiler, target) {
+        let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
             compiler
@@ -616,16 +607,16 @@ fn run(self, builder: &Builder) {
         builder.ensure(Std { stage, target });
 
         builder.ensure(compile::Rustc { compiler, target });
-        let out_dir = build.stage_out(compiler, Mode::Librustc)
+        let out_dir = builder.stage_out(compiler, Mode::Librustc)
                            .join(target).join("doc");
 
         // See docs in std above for why we symlink
-        let my_out = build.crate_doc_out(target);
-        build.clear_if_dirty(&my_out, &rustdoc);
+        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::Librustc, target, "doc");
-        compile::rustc_cargo(build, &mut cargo);
+        compile::rustc_cargo(builder, &mut cargo);
 
         // We don't want to build docs for internal compiler dependencies in this
         // step (there is another step for that). Therefore, we whitelist the crates
@@ -635,8 +626,8 @@ fn run(self, builder: &Builder) {
             cargo.arg("-p").arg(krate);
         }
 
-        build.run(&mut cargo);
-        build.cp_r(&my_out, &out);
+        builder.run(&mut cargo);
+        builder.cp_r(&my_out, &out);
     }
 }
 
@@ -653,7 +644,7 @@ impl Step for Rustc {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.krate("rustc-main").default_condition(builder.build.config.docs)
+        run.krate("rustc-main").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -670,22 +661,21 @@ fn make_run(run: RunConfig) {
     /// we do not merge it with the other documentation from std, test and
     /// proc_macros. This is largely just a wrapper around `cargo doc`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let target = self.target;
-        build.info(&format!("Documenting stage{} compiler ({})", stage, target));
-        let out = build.compiler_doc_out(target);
+        builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
+        let out = builder.compiler_doc_out(target);
         t!(fs::create_dir_all(&out));
-        let compiler = builder.compiler(stage, build.build);
+        let compiler = builder.compiler(stage, builder.config.build);
         let rustdoc = builder.rustdoc(compiler.host);
-        let compiler = if build.force_use_stage1(compiler, target) {
+        let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
             compiler
         };
 
-        if !build.config.compiler_docs {
-            build.info(&format!("\tskipping - compiler docs disabled"));
+        if !builder.config.compiler_docs {
+            builder.info(&format!("\tskipping - compiler docs disabled"));
             return;
         }
 
@@ -693,16 +683,16 @@ fn run(self, builder: &Builder) {
         builder.ensure(Std { stage, target });
 
         builder.ensure(compile::Rustc { compiler, target });
-        let out_dir = build.stage_out(compiler, Mode::Librustc)
+        let out_dir = builder.stage_out(compiler, Mode::Librustc)
                            .join(target).join("doc");
         // 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.
-        build.clear_if_dirty(&out, &rustdoc);
+        builder.clear_if_dirty(&out, &rustdoc);
         t!(symlink_dir_force(&builder.config, &out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
         cargo.env("RUSTDOCFLAGS", "--document-private-items");
-        compile::rustc_cargo(build, &mut cargo);
+        compile::rustc_cargo(builder, &mut cargo);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
         cargo.arg("--no-deps");
@@ -711,19 +701,19 @@ fn run(self, builder: &Builder) {
         let mut compiler_crates = HashSet::new();
         for root_crate in &["rustc", "rustc_driver"] {
             let interned_root_crate = INTERNER.intern_str(root_crate);
-            find_compiler_crates(&build, &interned_root_crate, &mut compiler_crates);
+            find_compiler_crates(builder, &interned_root_crate, &mut compiler_crates);
         }
 
         for krate in &compiler_crates {
             cargo.arg("-p").arg(krate);
         }
 
-        build.run(&mut cargo);
+        builder.run(&mut cargo);
     }
 }
 
 fn find_compiler_crates(
-    build: &Build,
+    builder: &Builder,
     name: &Interned<String>,
     crates: &mut HashSet<Interned<String>>
 ) {
@@ -731,9 +721,9 @@ fn find_compiler_crates(
     crates.insert(*name);
 
     // Look for dependencies.
-    for dep in build.crates.get(name).unwrap().deps.iter() {
-        if build.crates.get(dep).unwrap().is_local(build) {
-            find_compiler_crates(build, dep, crates);
+    for dep in builder.crates.get(name).unwrap().deps.iter() {
+        if builder.crates.get(dep).unwrap().is_local(builder) {
+            find_compiler_crates(builder, dep, crates);
         }
     }
 }
@@ -750,7 +740,7 @@ impl Step for ErrorIndex {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/tools/error_index_generator").default_condition(builder.build.config.docs)
+        run.path("src/tools/error_index_generator").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -762,21 +752,20 @@ fn make_run(run: RunConfig) {
     /// Generates the HTML rendered error-index by running the
     /// `error_index_generator` tool.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
 
-        build.info(&format!("Documenting error index ({})", target));
-        let out = build.doc_out(target);
+        builder.info(&format!("Documenting error index ({})", target));
+        let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
         let mut index = builder.tool_cmd(Tool::ErrorIndex);
         index.arg("html");
         index.arg(out.join("error-index.html"));
 
         // FIXME: shouldn't have to pass this env var
-        index.env("CFG_BUILD", &build.build)
-             .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir());
+        index.env("CFG_BUILD", &builder.config.build)
+             .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir());
 
-        build.run(&mut index);
+        builder.run(&mut index);
     }
 }
 
@@ -792,7 +781,7 @@ impl Step for UnstableBookGen {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/tools/unstable-book-gen").default_condition(builder.build.config.docs)
+        run.path("src/tools/unstable-book-gen").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -802,23 +791,22 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let target = self.target;
 
         builder.ensure(compile::Std {
-            compiler: builder.compiler(builder.top_stage, build.build),
+            compiler: builder.compiler(builder.top_stage, builder.config.build),
             target,
         });
 
-        build.info(&format!("Generating unstable book md files ({})", target));
-        let out = build.md_doc_out(target).join("unstable-book");
-        build.create_dir(&out);
-        build.remove_dir(&out);
+        builder.info(&format!("Generating unstable book md files ({})", target));
+        let out = builder.md_doc_out(target).join("unstable-book");
+        builder.create_dir(&out);
+        builder.remove_dir(&out);
         let mut cmd = builder.tool_cmd(Tool::UnstableBookGen);
-        cmd.arg(build.src.join("src"));
+        cmd.arg(builder.src.join("src"));
         cmd.arg(out);
 
-        build.run(&mut cmd);
+        builder.run(&mut cmd);
     }
 }
 
index d71fdb8a30c70d01be928a1fa2d0e30127b674c5..b37a007e86390249fec901326a0220ddd6ab11ba 100644 (file)
@@ -62,8 +62,7 @@ fn install_sh(
     stage: u32,
     host: Option<Interned<String>>
 ) {
-    let build = builder.build;
-    build.info(&format!("Install {} stage{} ({:?})", package, stage, host));
+    builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
 
     let prefix_default = PathBuf::from("/usr/local");
     let sysconfdir_default = PathBuf::from("/etc");
@@ -72,15 +71,15 @@ fn install_sh(
     let bindir_default = PathBuf::from("bin");
     let libdir_default = PathBuf::from("lib");
     let mandir_default = datadir_default.join("man");
-    let prefix = build.config.prefix.as_ref().map_or(prefix_default, |p| {
+    let prefix = builder.config.prefix.as_ref().map_or(prefix_default, |p| {
         fs::canonicalize(p).expect(&format!("could not canonicalize {}", p.display()))
     });
-    let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
-    let datadir = build.config.datadir.as_ref().unwrap_or(&datadir_default);
-    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
-    let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
-    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
-    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);
+    let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
+    let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default);
+    let docdir = builder.config.docdir.as_ref().unwrap_or(&docdir_default);
+    let bindir = builder.config.bindir.as_ref().unwrap_or(&bindir_default);
+    let libdir = builder.config.libdir.as_ref().unwrap_or(&libdir_default);
+    let mandir = builder.config.mandir.as_ref().unwrap_or(&mandir_default);
 
     let sysconfdir = prefix.join(sysconfdir);
     let datadir = prefix.join(datadir);
@@ -99,18 +98,18 @@ fn install_sh(
     let libdir = add_destdir(&libdir, &destdir);
     let mandir = add_destdir(&mandir, &destdir);
 
-    let empty_dir = build.out.join("tmp/empty_dir");
+    let empty_dir = builder.out.join("tmp/empty_dir");
 
     t!(fs::create_dir_all(&empty_dir));
     let package_name = if let Some(host) = host {
-        format!("{}-{}", pkgname(build, name), host)
+        format!("{}-{}", pkgname(builder, name), host)
     } else {
-        pkgname(build, name)
+        pkgname(builder, name)
     };
 
     let mut cmd = Command::new("sh");
     cmd.current_dir(&empty_dir)
-        .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
+        .arg(sanitize_sh(&tmpdir(builder).join(&package_name).join("install.sh")))
         .arg(format!("--prefix={}", sanitize_sh(&prefix)))
         .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
         .arg(format!("--datadir={}", sanitize_sh(&datadir)))
@@ -119,7 +118,7 @@ fn install_sh(
         .arg(format!("--libdir={}", sanitize_sh(&libdir)))
         .arg(format!("--mandir={}", sanitize_sh(&mandir)))
         .arg("--disable-ldconfig");
-    build.run(&mut cmd);
+    builder.run(&mut cmd);
     t!(fs::remove_dir_all(&empty_dir));
 }
 
@@ -180,7 +179,7 @@ fn make_run(run: RunConfig) {
                 run.builder.ensure($name {
                     stage: run.builder.top_stage,
                     target: run.target,
-                    host: run.builder.build.build,
+                    host: run.builder.config.build,
                 });
             }
 
@@ -197,7 +196,7 @@ fn run($sel, $builder: &Builder) {
         install_docs(builder, self.stage, self.target);
     };
     Std, "src/libstd", true, only_hosts: true, {
-        for target in &builder.build.targets {
+        for target in &builder.targets {
             builder.ensure(dist::Std {
                 compiler: builder.compiler(self.stage, self.host),
                 target: *target
index db5891afd6b1fa59ac73c7c7a9590511d64299c4..d952cb5bfc4bcab8c59fa3412243d63b13581206 100644 (file)
@@ -29,7 +29,6 @@
 use cmake;
 use cc;
 
-use Build;
 use util::{self, exe};
 use build_helper::up_to_date;
 use builder::{Builder, RunConfig, ShouldRun, Step};
@@ -60,39 +59,38 @@ fn make_run(run: RunConfig) {
 
     /// Compile LLVM for `target`.
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let target = self.target;
         let emscripten = self.emscripten;
 
         // If we're using a custom LLVM bail out here, but we can only use a
         // custom LLVM for the build triple.
         if !self.emscripten {
-            if let Some(config) = build.config.target_config.get(&target) {
+            if let Some(config) = builder.config.target_config.get(&target) {
                 if let Some(ref s) = config.llvm_config {
-                    check_llvm_version(build, s);
+                    check_llvm_version(builder, s);
                     return s.to_path_buf()
                 }
             }
         }
 
-        let rebuild_trigger = build.src.join("src/rustllvm/llvm-rebuild-trigger");
+        let rebuild_trigger = builder.src.join("src/rustllvm/llvm-rebuild-trigger");
         let mut rebuild_trigger_contents = String::new();
         t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents));
 
         let (out_dir, llvm_config_ret_dir) = if emscripten {
-            let dir = build.emscripten_llvm_out(target);
+            let dir = builder.emscripten_llvm_out(target);
             let config_dir = dir.join("bin");
             (dir, config_dir)
         } else {
-            let mut dir = build.llvm_out(build.config.build);
-            if !build.config.build.contains("msvc") || build.config.ninja {
+            let mut dir = builder.llvm_out(builder.config.build);
+            if !builder.config.build.contains("msvc") || builder.config.ninja {
                 dir.push("build");
             }
-            (build.llvm_out(target), dir.join("bin"))
+            (builder.llvm_out(target), dir.join("bin"))
         };
         let done_stamp = out_dir.join("llvm-finished-building");
         let build_llvm_config = llvm_config_ret_dir
-            .join(exe("llvm-config", &*build.config.build));
+            .join(exe("llvm-config", &*builder.config.build));
         if done_stamp.exists() {
             let mut done_contents = String::new();
             t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
@@ -104,17 +102,17 @@ fn run(self, builder: &Builder) -> PathBuf {
             }
         }
 
-        let _folder = build.fold_output(|| "llvm");
+        let _folder = builder.fold_output(|| "llvm");
         let descriptor = if emscripten { "Emscripten " } else { "" };
-        build.info(&format!("Building {}LLVM for {}", descriptor, target));
-        let _time = util::timeit(&build);
+        builder.info(&format!("Building {}LLVM for {}", descriptor, target));
+        let _time = util::timeit(&builder);
         t!(fs::create_dir_all(&out_dir));
 
         // http://llvm.org/docs/CMake.html
         let root = if self.emscripten { "src/llvm-emscripten" } else { "src/llvm" };
-        let mut cfg = cmake::Config::new(build.src.join(root));
+        let mut cfg = cmake::Config::new(builder.src.join(root));
 
-        let profile = match (build.config.llvm_optimize, build.config.llvm_release_debuginfo) {
+        let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
             (false, _) => "Debug",
             (true, false) => "Release",
             (true, true) => "RelWithDebInfo",
@@ -125,7 +123,7 @@ fn run(self, builder: &Builder) -> PathBuf {
         let llvm_targets = if self.emscripten {
             "JSBackend"
         } else {
-            match build.config.llvm_targets {
+            match builder.config.llvm_targets {
                 Some(ref s) => s,
                 None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;MSP430;Sparc;NVPTX;Hexagon",
             }
@@ -134,10 +132,10 @@ fn run(self, builder: &Builder) -> PathBuf {
         let llvm_exp_targets = if self.emscripten {
             ""
         } else {
-            &build.config.llvm_experimental_targets[..]
+            &builder.config.llvm_experimental_targets[..]
         };
 
-        let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
+        let assertions = if builder.config.llvm_assertions {"ON"} else {"OFF"};
 
         cfg.out_dir(&out_dir)
            .profile(profile)
@@ -151,7 +149,8 @@ fn run(self, builder: &Builder) -> PathBuf {
            .define("WITH_POLLY", "OFF")
            .define("LLVM_ENABLE_TERMINFO", "OFF")
            .define("LLVM_ENABLE_LIBEDIT", "OFF")
-           .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string())
+           .define("LLVM_ENABLE_LIBXML2", "OFF")
+           .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
            .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
            .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
 
@@ -183,22 +182,22 @@ fn run(self, builder: &Builder) -> PathBuf {
             cfg.define("LLVM_BUILD_32_BITS", "ON");
         }
 
-        if let Some(num_linkers) = build.config.llvm_link_jobs {
+        if let Some(num_linkers) = builder.config.llvm_link_jobs {
             if num_linkers > 0 {
                 cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string());
             }
         }
 
         // http://llvm.org/docs/HowToCrossCompileLLVM.html
-        if target != build.build && !emscripten {
+        if target != builder.config.build && !emscripten {
             builder.ensure(Llvm {
-                target: build.build,
+                target: builder.config.build,
                 emscripten: false,
             });
             // FIXME: if the llvm root for the build triple is overridden then we
             //        should use llvm-tblgen from there, also should verify that it
             //        actually exists most of the time in normal installs of LLVM.
-            let host = build.llvm_out(build.build).join("bin/llvm-tblgen");
+            let host = builder.llvm_out(builder.config.build).join("bin/llvm-tblgen");
             cfg.define("CMAKE_CROSSCOMPILING", "True")
                .define("LLVM_TABLEGEN", &host);
 
@@ -208,10 +207,10 @@ fn run(self, builder: &Builder) -> PathBuf {
                cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
             }
 
-            cfg.define("LLVM_NATIVE_BUILD", build.llvm_out(build.build).join("build"));
+            cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build"));
         }
 
-        configure_cmake(build, target, &mut cfg, false);
+        configure_cmake(builder, target, &mut cfg, false);
 
         // FIXME: we don't actually need to build all LLVM tools and all LLVM
         //        libraries here, e.g. we just want a few components and a few
@@ -230,12 +229,12 @@ fn run(self, builder: &Builder) -> PathBuf {
     }
 }
 
-fn check_llvm_version(build: &Build, llvm_config: &Path) {
-    if !build.config.llvm_version_check {
+fn check_llvm_version(builder: &Builder, llvm_config: &Path) {
+    if !builder.config.llvm_version_check {
         return
     }
 
-    if build.config.dry_run {
+    if builder.config.dry_run {
         return;
     }
 
@@ -251,15 +250,15 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
     panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
 }
 
-fn configure_cmake(build: &Build,
+fn configure_cmake(builder: &Builder,
                    target: Interned<String>,
                    cfg: &mut cmake::Config,
                    building_dist_binaries: bool) {
-    if build.config.ninja {
+    if builder.config.ninja {
         cfg.generator("Ninja");
     }
     cfg.target(&target)
-       .host(&build.config.build);
+       .host(&builder.config.build);
 
     let sanitize_cc = |cc: &Path| {
         if target.contains("msvc") {
@@ -272,29 +271,29 @@ fn configure_cmake(build: &Build,
     // MSVC with CMake uses msbuild by default which doesn't respect these
     // vars that we'd otherwise configure. In that case we just skip this
     // entirely.
-    if target.contains("msvc") && !build.config.ninja {
+    if target.contains("msvc") && !builder.config.ninja {
         return
     }
 
-    let cc = build.cc(target);
-    let cxx = build.cxx(target).unwrap();
+    let cc = builder.cc(target);
+    let cxx = builder.cxx(target).unwrap();
 
     // Handle msvc + ninja + ccache specially (this is what the bots use)
     if target.contains("msvc") &&
-       build.config.ninja &&
-       build.config.ccache.is_some() {
+       builder.config.ninja &&
+       builder.config.ccache.is_some() {
         let mut cc = env::current_exe().expect("failed to get cwd");
         cc.set_file_name("sccache-plus-cl.exe");
 
        cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
           .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
        cfg.env("SCCACHE_PATH",
-               build.config.ccache.as_ref().unwrap())
+               builder.config.ccache.as_ref().unwrap())
           .env("SCCACHE_TARGET", target);
 
     // If ccache is configured we inform the build a little differently hwo
     // to invoke ccache while also invoking our compilers.
-    } else if let Some(ref ccache) = build.config.ccache {
+    } else if let Some(ref ccache) = builder.config.ccache {
        cfg.define("CMAKE_C_COMPILER", ccache)
           .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
           .define("CMAKE_CXX_COMPILER", ccache)
@@ -304,16 +303,16 @@ fn configure_cmake(build: &Build,
           .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
     }
 
-    cfg.build_arg("-j").build_arg(build.jobs().to_string());
-    cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
-    let mut cxxflags = build.cflags(target).join(" ");
+    cfg.build_arg("-j").build_arg(builder.jobs().to_string());
+    cfg.define("CMAKE_C_FLAGS", builder.cflags(target).join(" "));
+    let mut cxxflags = builder.cflags(target).join(" ");
     if building_dist_binaries {
-        if build.config.llvm_static_stdcpp && !target.contains("windows") {
+        if builder.config.llvm_static_stdcpp && !target.contains("windows") {
             cxxflags.push_str(" -static-libstdc++");
         }
     }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
-    if let Some(ar) = build.ar(target) {
+    if let Some(ar) = builder.ar(target) {
         if ar.is_absolute() {
             // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
             // tries to resolve this path in the LLVM build directory.
@@ -349,26 +348,25 @@ fn run(self, builder: &Builder) -> PathBuf {
             return PathBuf::from("lld-out-dir-test-gen");
         }
         let target = self.target;
-        let build = builder.build;
 
         let llvm_config = builder.ensure(Llvm {
             target: self.target,
             emscripten: false,
         });
 
-        let out_dir = build.lld_out(target);
+        let out_dir = builder.lld_out(target);
         let done_stamp = out_dir.join("lld-finished-building");
         if done_stamp.exists() {
             return out_dir
         }
 
-        let _folder = build.fold_output(|| "lld");
-        build.info(&format!("Building LLD for {}", target));
-        let _time = util::timeit(&build);
+        let _folder = builder.fold_output(|| "lld");
+        builder.info(&format!("Building LLD for {}", target));
+        let _time = util::timeit(&builder);
         t!(fs::create_dir_all(&out_dir));
 
-        let mut cfg = cmake::Config::new(build.src.join("src/tools/lld"));
-        configure_cmake(build, target, &mut cfg, true);
+        let mut cfg = cmake::Config::new(builder.src.join("src/tools/lld"));
+        configure_cmake(builder, target, &mut cfg, true);
 
         cfg.out_dir(&out_dir)
            .profile("Release")
@@ -404,16 +402,15 @@ fn run(self, builder: &Builder) {
         if builder.config.dry_run {
             return;
         }
-        let build = builder.build;
         let target = self.target;
-        let dst = build.test_helpers_out(target);
-        let src = build.src.join("src/test/auxiliary/rust_test_helpers.c");
+        let dst = builder.test_helpers_out(target);
+        let src = builder.src.join("src/test/auxiliary/rust_test_helpers.c");
         if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
             return
         }
 
-        let _folder = build.fold_output(|| "build_test_helpers");
-        build.info(&format!("Building test helpers"));
+        let _folder = builder.fold_output(|| "build_test_helpers");
+        builder.info(&format!("Building test helpers"));
         t!(fs::create_dir_all(&dst));
         let mut cfg = cc::Build::new();
 
@@ -421,20 +418,20 @@ fn run(self, builder: &Builder) {
         // extra configuration, so inform gcc of these compilers. Note, though, that
         // on MSVC we still need gcc's detection of env vars (ugh).
         if !target.contains("msvc") {
-            if let Some(ar) = build.ar(target) {
+            if let Some(ar) = builder.ar(target) {
                 cfg.archiver(ar);
             }
-            cfg.compiler(build.cc(target));
+            cfg.compiler(builder.cc(target));
         }
 
         cfg.cargo_metadata(false)
            .out_dir(&dst)
            .target(&target)
-           .host(&build.build)
+           .host(&builder.config.build)
            .opt_level(0)
            .warnings(false)
            .debug(false)
-           .file(build.src.join("src/test/auxiliary/rust_test_helpers.c"))
+           .file(builder.src.join("src/test/auxiliary/rust_test_helpers.c"))
            .compile("rust_test_helpers");
     }
 }
@@ -459,9 +456,8 @@ fn run(self, builder: &Builder) {
         if builder.config.dry_run {
             return;
         }
-        let build = builder.build;
         let target = self.target;
-        let out = match build.openssl_dir(target) {
+        let out = match builder.openssl_dir(target) {
             Some(dir) => dir,
             None => return,
         };
@@ -497,7 +493,8 @@ fn run(self, builder: &Builder) {
                 }
 
                 // Ensure the hash is correct.
-                let mut shasum = if target.contains("apple") || build.build.contains("netbsd") {
+                let mut shasum = if target.contains("apple") ||
+                    builder.config.build.contains("netbsd") {
                     let mut cmd = Command::new("shasum");
                     cmd.arg("-a").arg("256");
                     cmd
@@ -530,10 +527,10 @@ fn run(self, builder: &Builder) {
             t!(fs::rename(&tmp, &tarball));
         }
         let obj = out.join(format!("openssl-{}", OPENSSL_VERS));
-        let dst = build.openssl_install_dir(target).unwrap();
+        let dst = builder.openssl_install_dir(target).unwrap();
         drop(fs::remove_dir_all(&obj));
         drop(fs::remove_dir_all(&dst));
-        build.run(Command::new("tar").arg("zxf").arg(&tarball).current_dir(&out));
+        builder.run(Command::new("tar").arg("zxf").arg(&tarball).current_dir(&out));
 
         let mut configure = Command::new("perl");
         configure.arg(obj.join("Configure"));
@@ -583,8 +580,8 @@ fn run(self, builder: &Builder) {
             _ => panic!("don't know how to configure OpenSSL for {}", target),
         };
         configure.arg(os);
-        configure.env("CC", build.cc(target));
-        for flag in build.cflags(target) {
+        configure.env("CC", builder.cc(target));
+        for flag in builder.cflags(target) {
             configure.arg(flag);
         }
         // There is no specific os target for android aarch64 or x86_64,
@@ -596,7 +593,7 @@ fn run(self, builder: &Builder) {
         if target == "sparc64-unknown-netbsd" {
             // Need -m64 to get assembly generated correctly for sparc64.
             configure.arg("-m64");
-            if build.build.contains("netbsd") {
+            if builder.config.build.contains("netbsd") {
                 // Disable sparc64 asm on NetBSD builders, it uses
                 // m4(1)'s -B flag, which NetBSD m4 does not support.
                 configure.arg("no-asm");
@@ -609,12 +606,12 @@ fn run(self, builder: &Builder) {
             configure.arg("no-asm");
         }
         configure.current_dir(&obj);
-        build.info(&format!("Configuring openssl for {}", target));
-        build.run_quiet(&mut configure);
-        build.info(&format!("Building openssl for {}", target));
-        build.run_quiet(Command::new("make").arg("-j1").current_dir(&obj));
-        build.info(&format!("Installing openssl for {}", target));
-        build.run_quiet(Command::new("make").arg("install").arg("-j1").current_dir(&obj));
+        builder.info(&format!("Configuring openssl for {}", target));
+        builder.run_quiet(&mut configure);
+        builder.info(&format!("Building openssl for {}", target));
+        builder.run_quiet(Command::new("make").arg("-j1").current_dir(&obj));
+        builder.info(&format!("Installing openssl for {}", target));
+        builder.run_quiet(Command::new("make").arg("install").arg("-j1").current_dir(&obj));
 
         let mut f = t!(File::create(&stamp));
         t!(f.write_all(OPENSSL_VERS.as_bytes()));
index 1b1cec5f18c07d530795f35ee5df4d4faa8145e8..c7f514da939a60639b7082ed5a8b7b64a2a80f0f 100644 (file)
@@ -140,14 +140,18 @@ pub fn check(build: &mut Build) {
             continue;
         }
 
-        cmd_finder.must_have(build.cc(*target));
-        if let Some(ar) = build.ar(*target) {
-            cmd_finder.must_have(ar);
+        if !build.config.dry_run {
+            cmd_finder.must_have(build.cc(*target));
+            if let Some(ar) = build.ar(*target) {
+                cmd_finder.must_have(ar);
+            }
         }
     }
 
     for host in &build.hosts {
-        cmd_finder.must_have(build.cxx(*host).unwrap());
+        if !build.config.dry_run {
+            cmd_finder.must_have(build.cxx(*host).unwrap());
+        }
 
         // The msvc hosts don't use jemalloc, turn it off globally to
         // avoid packaging the dummy liballoc_jemalloc on that platform.
index 29c8cd1568a39a0db6af388a44ffd24d4ecd7029..08bbd68c756b40063e8982265f3a3d7d69020154 100644 (file)
@@ -32,7 +32,7 @@
 use native;
 use tool::{self, Tool};
 use util::{self, dylib_path, dylib_path_var};
-use {Build, Mode};
+use Mode;
 use toolstate::ToolState;
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
@@ -65,28 +65,28 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-fn try_run(build: &Build, cmd: &mut Command) -> bool {
-    if !build.fail_fast {
-        if !build.try_run(cmd) {
-            let mut failures = build.delayed_failures.borrow_mut();
+fn try_run(builder: &Builder, cmd: &mut Command) -> bool {
+    if !builder.fail_fast {
+        if !builder.try_run(cmd) {
+            let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
             return false;
         }
     } else {
-        build.run(cmd);
+        builder.run(cmd);
     }
     true
 }
 
-fn try_run_quiet(build: &Build, cmd: &mut Command) -> bool {
-    if !build.fail_fast {
-        if !build.try_run_quiet(cmd) {
-            let mut failures = build.delayed_failures.borrow_mut();
+fn try_run_quiet(builder: &Builder, cmd: &mut Command) -> bool {
+    if !builder.fail_fast {
+        if !builder.try_run_quiet(cmd) {
+            let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
             return false;
         }
     } else {
-        build.run_quiet(cmd);
+        builder.run_quiet(cmd);
     }
     true
 }
@@ -106,21 +106,20 @@ impl Step for Linkcheck {
     /// This tool in `src/tools` will verify the validity of all our links in the
     /// documentation to ensure we don't have a bunch of dead ones.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let host = self.host;
 
-        build.info(&format!("Linkcheck ({})", host));
+        builder.info(&format!("Linkcheck ({})", host));
 
         builder.default_doc(None);
 
-        let _time = util::timeit(&build);
-        try_run(build, builder.tool_cmd(Tool::Linkchecker)
-                              .arg(build.out.join(host).join("doc")));
+        let _time = util::timeit(&builder);
+        try_run(builder, builder.tool_cmd(Tool::Linkchecker)
+                              .arg(builder.out.join(host).join("doc")));
     }
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/tools/linkchecker").default_condition(builder.build.config.docs)
+        run.path("src/tools/linkchecker").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig) {
@@ -154,19 +153,18 @@ fn make_run(run: RunConfig) {
     /// This tool in `src/tools` will check out a few Rust projects and run `cargo
     /// test` to ensure that we don't regress the test suites there.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = builder.compiler(self.stage, self.host);
         builder.ensure(compile::Rustc { compiler, target: compiler.host });
 
         // Note that this is a short, cryptic, and not scoped directory name. This
         // is currently to minimize the length of path on Windows where we otherwise
         // quickly run into path name limit constraints.
-        let out_dir = build.out.join("ct");
+        let out_dir = builder.out.join("ct");
         t!(fs::create_dir_all(&out_dir));
 
-        let _time = util::timeit(&build);
+        let _time = util::timeit(&builder);
         let mut cmd = builder.tool_cmd(Tool::CargoTest);
-        try_run(build, cmd.arg(&build.initial_cargo)
+        try_run(builder, cmd.arg(&builder.initial_cargo)
                           .arg(&out_dir)
                           .env("RUSTC", builder.rustc(compiler))
                           .env("RUSTDOC", builder.rustdoc(compiler.host)));
@@ -196,13 +194,12 @@ fn make_run(run: RunConfig) {
 
     /// Runs `cargo test` for `cargo` packaged with Rust.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = builder.compiler(self.stage, self.host);
 
         builder.ensure(tool::Cargo { compiler, target: self.host });
         let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test");
-        cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
-        if !build.fail_fast {
+        cargo.arg("--manifest-path").arg(builder.src.join("src/tools/cargo/Cargo.toml"));
+        if !builder.fail_fast {
             cargo.arg("--no-fail-fast");
         }
 
@@ -213,7 +210,7 @@ fn run(self, builder: &Builder) {
         // available.
         cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
 
-        try_run(build, cargo.env("PATH", &path_for_cargo(builder, compiler)));
+        try_run(builder, cargo.env("PATH", &path_for_cargo(builder, compiler)));
     }
 }
 
@@ -240,12 +237,20 @@ fn make_run(run: RunConfig) {
 
     /// Runs `cargo test` for the rls.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() });
+        let build_result = builder.ensure(tool::Rls {
+            compiler,
+            target: self.host,
+            extra_features: Vec::new(),
+        });
+        if build_result.is_none() {
+            eprintln!("failed to test rls: could not build");
+            return;
+        }
+
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
                                                  host,
@@ -257,8 +262,8 @@ fn run(self, builder: &Builder) {
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        if try_run(build, &mut cargo) {
-            build.save_toolstate("rls", ToolState::TestPass);
+        if try_run(builder, &mut cargo) {
+            builder.save_toolstate("rls", ToolState::TestPass);
         }
     }
 }
@@ -286,12 +291,20 @@ fn make_run(run: RunConfig) {
 
     /// Runs `cargo test` for rustfmt.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() });
+        let build_result = builder.ensure(tool::Rustfmt {
+            compiler,
+            target: self.host,
+            extra_features: Vec::new(),
+        });
+        if build_result.is_none() {
+            eprintln!("failed to test rustfmt: could not build");
+            return;
+        }
+
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
                                                  host,
@@ -303,8 +316,8 @@ fn run(self, builder: &Builder) {
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        if try_run(build, &mut cargo) {
-            build.save_toolstate("rustfmt", ToolState::TestPass);
+        if try_run(builder, &mut cargo) {
+            builder.save_toolstate("rustfmt", ToolState::TestPass);
         }
     }
 }
@@ -321,7 +334,7 @@ impl Step for Miri {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        let test_miri = run.builder.build.config.test_miri;
+        let test_miri = run.builder.config.test_miri;
         run.path("src/tools/miri").default_condition(test_miri)
     }
 
@@ -334,7 +347,6 @@ fn make_run(run: RunConfig) {
 
     /// Runs `cargo test` for miri.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let host = self.host;
         let compiler = builder.compiler(stage, host);
@@ -346,7 +358,7 @@ fn run(self, builder: &Builder) {
         });
         if let Some(miri) = miri {
             let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
-            cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml"));
+            cargo.arg("--manifest-path").arg(builder.src.join("src/tools/miri/Cargo.toml"));
 
             // Don't build tests dynamically, just a pain to work with
             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
@@ -358,8 +370,8 @@ fn run(self, builder: &Builder) {
 
             builder.add_rustc_lib_path(compiler, &mut cargo);
 
-            if try_run(build, &mut cargo) {
-                build.save_toolstate("miri", ToolState::TestPass);
+            if try_run(builder, &mut cargo) {
+                builder.save_toolstate("miri", ToolState::TestPass);
             }
         } else {
             eprintln!("failed to test miri: could not build");
@@ -391,7 +403,6 @@ fn make_run(run: RunConfig) {
 
     /// Runs `cargo test` for clippy.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let stage = self.stage;
         let host = self.host;
         let compiler = builder.compiler(stage, host);
@@ -403,7 +414,7 @@ fn run(self, builder: &Builder) {
         });
         if let Some(clippy) = clippy {
             let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
-            cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml"));
+            cargo.arg("--manifest-path").arg(builder.src.join("src/tools/clippy/Cargo.toml"));
 
             // Don't build tests dynamically, just a pain to work with
             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
@@ -418,8 +429,8 @@ fn run(self, builder: &Builder) {
 
             builder.add_rustc_lib_path(compiler, &mut cargo);
 
-            if try_run(build, &mut cargo) {
-                build.save_toolstate("clippy-driver", ToolState::TestPass);
+            if try_run(builder, &mut cargo) {
+                builder.save_toolstate("clippy-driver", ToolState::TestPass);
             }
         } else {
             eprintln!("failed to test clippy: could not build");
@@ -466,14 +477,14 @@ fn run(self, builder: &Builder) {
            .env("RUSTC_STAGE", self.compiler.stage.to_string())
            .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
            .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
-           .env("CFG_RELEASE_CHANNEL", &builder.build.config.channel)
+           .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
            .env("RUSTDOC_REAL", builder.rustdoc(self.compiler.host))
-           .env("RUSTDOC_CRATE_VERSION", builder.build.rust_version())
+           .env("RUSTDOC_CRATE_VERSION", builder.rust_version())
            .env("RUSTC_BOOTSTRAP", "1");
-        if let Some(linker) = builder.build.linker(self.compiler.host) {
+        if let Some(linker) = builder.linker(self.compiler.host) {
             cmd.env("RUSTC_TARGET_LINKER", linker);
         }
-        try_run(builder.build, &mut cmd);
+        try_run(builder, &mut cmd);
     }
 }
 
@@ -514,6 +525,42 @@ fn run(self, builder: &Builder) {
     }
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct RustdocUi {
+    pub host: Interned<String>,
+    pub target: Interned<String>,
+    pub compiler: Compiler,
+}
+
+impl Step for RustdocUi {
+    type Output = ();
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/test/rustdoc-ui")
+    }
+
+    fn make_run(run: RunConfig) {
+        let compiler = run.builder.compiler(run.builder.top_stage, run.host);
+        run.builder.ensure(RustdocUi {
+            host: run.host,
+            target: run.target,
+            compiler,
+        });
+    }
+
+    fn run(self, builder: &Builder) {
+        builder.ensure(Compiletest {
+            compiler: self.compiler,
+            target: self.target,
+            mode: "ui",
+            suite: "rustdoc-ui",
+            compare_mode: None,
+        })
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Tidy;
 
@@ -528,21 +575,19 @@ impl Step for Tidy {
     /// otherwise just implements a few lint-like checks that are specific to the
     /// compiler itself.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
-
         let mut cmd = builder.tool_cmd(Tool::Tidy);
-        cmd.arg(build.src.join("src"));
-        cmd.arg(&build.initial_cargo);
-        if !build.config.vendor {
+        cmd.arg(builder.src.join("src"));
+        cmd.arg(&builder.initial_cargo);
+        if !builder.config.vendor {
             cmd.arg("--no-vendor");
         }
-        if build.config.quiet_tests {
+        if builder.config.quiet_tests {
             cmd.arg("--quiet");
         }
 
-        let _folder = build.fold_output(|| "tidy");
+        let _folder = builder.fold_output(|| "tidy");
         builder.info(&format!("tidy check"));
-        try_run(build, &mut cmd);
+        try_run(builder, &mut cmd);
     }
 
     fn should_run(run: ShouldRun) -> ShouldRun {
@@ -554,8 +599,8 @@ fn make_run(run: RunConfig) {
     }
 }
 
-fn testdir(build: &Build, host: Interned<String>) -> PathBuf {
-    build.out.join(host).join("test")
+fn testdir(builder: &Builder, host: Interned<String>) -> PathBuf {
+    builder.out.join(host).join("test")
 }
 
 macro_rules! default_test {
@@ -564,6 +609,14 @@ macro_rules! default_test {
     }
 }
 
+macro_rules! default_test_with_compare_mode {
+    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr,
+                   compare_mode: $compare_mode:expr }) => {
+        test_with_compare_mode!($name { path: $path, mode: $mode, suite: $suite, default: true,
+                                        host: false, compare_mode: $compare_mode });
+    }
+}
+
 macro_rules! host_test {
     ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
         test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true });
@@ -571,12 +624,29 @@ macro_rules! host_test {
 }
 
 macro_rules! test {
+    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
+                   host: $host:expr }) => {
+        test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
+                                  host: $host, compare_mode: None });
+    }
+}
+
+macro_rules! test_with_compare_mode {
+    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
+                   host: $host:expr, compare_mode: $compare_mode:expr }) => {
+        test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
+                                  host: $host, compare_mode: Some($compare_mode) });
+    }
+}
+
+macro_rules! test_definitions {
     ($name:ident {
         path: $path:expr,
         mode: $mode:expr,
         suite: $suite:expr,
         default: $default:expr,
-        host: $host:expr
+        host: $host:expr,
+        compare_mode: $compare_mode:expr
     }) => {
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub struct $name {
@@ -608,16 +678,18 @@ fn run(self, builder: &Builder) {
                     target: self.target,
                     mode: $mode,
                     suite: $suite,
+                    compare_mode: $compare_mode,
                 })
             }
         }
     }
 }
 
-default_test!(Ui {
+default_test_with_compare_mode!(Ui {
     path: "src/test/ui",
     mode: "ui",
-    suite: "ui"
+    suite: "ui",
+    compare_mode: "nll"
 });
 
 default_test!(RunPass {
@@ -778,6 +850,7 @@ struct Compiletest {
     target: Interned<String>,
     mode: &'static str,
     suite: &'static str,
+    compare_mode: Option<&'static str>,
 }
 
 impl Step for Compiletest {
@@ -793,25 +866,25 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// compiletest `mode` and `suite` arguments. For example `mode` can be
     /// "run-pass" or `suite` can be something like `debuginfo`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
         let mode = self.mode;
         let suite = self.suite;
+        let compare_mode = self.compare_mode;
 
         // Skip codegen tests if they aren't enabled in configuration.
-        if !build.config.codegen_tests && suite == "codegen" {
+        if !builder.config.codegen_tests && suite == "codegen" {
             return;
         }
 
         if suite == "debuginfo" {
             // Skip debuginfo tests on MSVC
-            if build.build.contains("msvc") {
+            if builder.config.build.contains("msvc") {
                 return;
             }
 
             if mode == "debuginfo-XXX" {
-                return if build.build.contains("apple") {
+                return if builder.config.build.contains("apple") {
                     builder.ensure(Compiletest {
                         mode: "debuginfo-lldb",
                         ..self
@@ -851,34 +924,44 @@ fn run(self, builder: &Builder) {
         cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
         cmd.arg("--rustc-path").arg(builder.rustc(compiler));
 
+        let is_rustdoc_ui = suite.ends_with("rustdoc-ui");
+
         // Avoid depending on rustdoc when we don't need it.
-        if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) {
+        if mode == "rustdoc" ||
+           (mode == "run-make" && suite.ends_with("fulldeps")) ||
+           (mode == "ui" && is_rustdoc_ui) {
             cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));
         }
 
-        cmd.arg("--src-base").arg(build.src.join("src/test").join(suite));
-        cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite));
+        cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));
+        cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
         cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
         cmd.arg("--mode").arg(mode);
         cmd.arg("--target").arg(target);
         cmd.arg("--host").arg(&*compiler.host);
-        cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(build.build));
+        cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
 
-        if let Some(ref nodejs) = build.config.nodejs {
+        if let Some(ref nodejs) = builder.config.nodejs {
             cmd.arg("--nodejs").arg(nodejs);
         }
 
-        let mut flags = vec!["-Crpath".to_string()];
-        if build.config.rust_optimize_tests {
-            flags.push("-O".to_string());
-        }
-        if build.config.rust_debuginfo_tests {
-            flags.push("-g".to_string());
+        let mut flags = if is_rustdoc_ui {
+            Vec::new()
+        } else {
+            vec!["-Crpath".to_string()]
+        };
+        if !is_rustdoc_ui {
+            if builder.config.rust_optimize_tests {
+                flags.push("-O".to_string());
+            }
+            if builder.config.rust_debuginfo_tests {
+                flags.push("-g".to_string());
+            }
         }
         flags.push("-Zunstable-options".to_string());
-        flags.push(build.config.cmd.rustc_args().join(" "));
+        flags.push(builder.config.cmd.rustc_args().join(" "));
 
-        if let Some(linker) = build.linker(target) {
+        if let Some(linker) = builder.linker(target) {
             cmd.arg("--linker").arg(linker);
         }
 
@@ -887,69 +970,69 @@ fn run(self, builder: &Builder) {
 
         let mut targetflags = flags.clone();
         targetflags.push(format!("-Lnative={}",
-                                 build.test_helpers_out(target).display()));
+                                 builder.test_helpers_out(target).display()));
         cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
 
-        cmd.arg("--docck-python").arg(build.python());
+        cmd.arg("--docck-python").arg(builder.python());
 
-        if build.build.ends_with("apple-darwin") {
+        if builder.config.build.ends_with("apple-darwin") {
             // Force /usr/bin/python on macOS for LLDB tests because we're loading the
             // LLDB plugin's compiled module which only works with the system python
             // (namely not Homebrew-installed python)
             cmd.arg("--lldb-python").arg("/usr/bin/python");
         } else {
-            cmd.arg("--lldb-python").arg(build.python());
+            cmd.arg("--lldb-python").arg(builder.python());
         }
 
-        if let Some(ref gdb) = build.config.gdb {
+        if let Some(ref gdb) = builder.config.gdb {
             cmd.arg("--gdb").arg(gdb);
         }
-        if let Some(ref vers) = build.lldb_version {
+        if let Some(ref vers) = builder.lldb_version {
             cmd.arg("--lldb-version").arg(vers);
         }
-        if let Some(ref dir) = build.lldb_python_dir {
+        if let Some(ref dir) = builder.lldb_python_dir {
             cmd.arg("--lldb-python-dir").arg(dir);
         }
 
-        cmd.args(&build.config.cmd.test_args());
+        cmd.args(&builder.config.cmd.test_args());
 
-        if build.is_verbose() {
+        if builder.is_verbose() {
             cmd.arg("--verbose");
         }
 
-        if build.config.quiet_tests {
+        if builder.config.quiet_tests {
             cmd.arg("--quiet");
         }
 
-        if build.config.llvm_enabled {
+        if builder.config.llvm_enabled {
             let llvm_config = builder.ensure(native::Llvm {
-                target: build.config.build,
+                target: builder.config.build,
                 emscripten: false,
             });
-            if !build.config.dry_run {
+            if !builder.config.dry_run {
                 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
                 cmd.arg("--llvm-version").arg(llvm_version);
             }
-            if !build.is_rust_llvm(target) {
+            if !builder.is_rust_llvm(target) {
                 cmd.arg("--system-llvm");
             }
 
             // Only pass correct values for these flags for the `run-make` suite as it
             // requires that a C++ compiler was configured which isn't always the case.
-            if !build.config.dry_run && suite == "run-make-fulldeps" {
+            if !builder.config.dry_run && suite == "run-make-fulldeps" {
                 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
                 let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
-                cmd.arg("--cc").arg(build.cc(target))
-                .arg("--cxx").arg(build.cxx(target).unwrap())
-                .arg("--cflags").arg(build.cflags(target).join(" "))
+                cmd.arg("--cc").arg(builder.cc(target))
+                .arg("--cxx").arg(builder.cxx(target).unwrap())
+                .arg("--cflags").arg(builder.cflags(target).join(" "))
                 .arg("--llvm-components").arg(llvm_components.trim())
                 .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
-                if let Some(ar) = build.ar(target) {
+                if let Some(ar) = builder.ar(target) {
                     cmd.arg("--ar").arg(ar);
                 }
             }
         }
-        if suite == "run-make-fulldeps" && !build.config.llvm_enabled {
+        if suite == "run-make-fulldeps" && !builder.config.llvm_enabled {
             builder.info(
                 &format!("Ignoring run-make test suite as they generally don't work without LLVM"));
             return;
@@ -963,7 +1046,7 @@ fn run(self, builder: &Builder) {
                .arg("--llvm-cxxflags").arg("");
         }
 
-        if build.remote_tested(target) {
+        if builder.remote_tested(target) {
             cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
         }
 
@@ -973,42 +1056,51 @@ fn run(self, builder: &Builder) {
         // Note that if we encounter `PATH` we make sure to append to our own `PATH`
         // rather than stomp over it.
         if target.contains("msvc") {
-            for &(ref k, ref v) in build.cc[&target].env() {
+            for &(ref k, ref v) in builder.cc[&target].env() {
                 if k != "PATH" {
                     cmd.env(k, v);
                 }
             }
         }
         cmd.env("RUSTC_BOOTSTRAP", "1");
-        build.add_rust_test_threads(&mut cmd);
+        builder.add_rust_test_threads(&mut cmd);
 
-        if build.config.sanitizers {
+        if builder.config.sanitizers {
             cmd.env("SANITIZER_SUPPORT", "1");
         }
 
-        if build.config.profiler {
+        if builder.config.profiler {
             cmd.env("PROFILER_SUPPORT", "1");
         }
 
-        cmd.env("RUST_TEST_TMPDIR", build.out.join("tmp"));
+        cmd.env("RUST_TEST_TMPDIR", builder.out.join("tmp"));
 
         cmd.arg("--adb-path").arg("adb");
         cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
         if target.contains("android") {
             // Assume that cc for this target comes from the android sysroot
             cmd.arg("--android-cross-path")
-               .arg(build.cc(target).parent().unwrap().parent().unwrap());
+               .arg(builder.cc(target).parent().unwrap().parent().unwrap());
         } else {
             cmd.arg("--android-cross-path").arg("");
         }
 
-        build.ci_env.force_coloring_in_ci(&mut cmd);
+        builder.ci_env.force_coloring_in_ci(&mut cmd);
 
-        let _folder = build.fold_output(|| format!("test_{}", suite));
+        let _folder = builder.fold_output(|| format!("test_{}", suite));
         builder.info(&format!("Check compiletest suite={} mode={} ({} -> {})",
                  suite, mode, &compiler.host, target));
-        let _time = util::timeit(&build);
-        try_run(build, &mut cmd);
+        let _time = util::timeit(&builder);
+        try_run(builder, &mut cmd);
+
+        if let Some(compare_mode) = compare_mode {
+            cmd.arg("--compare-mode").arg(compare_mode);
+            let _folder = builder.fold_output(|| format!("test_{}_{}", suite, compare_mode));
+            builder.info(&format!("Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
+                                  suite, mode, compare_mode, &compiler.host, target));
+            let _time = util::timeit(&builder);
+            try_run(builder, &mut cmd);
+        }
     }
 }
 
@@ -1034,16 +1126,15 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
     /// `compiler`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
 
         builder.ensure(compile::Test { compiler, target: compiler.host });
 
         // Do a breadth-first traversal of the `src/doc` directory and just run
         // tests for all files that end in `*.md`
-        let mut stack = vec![build.src.join(self.path)];
-        let _time = util::timeit(&build);
-        let _folder = build.fold_output(|| format!("test_{}", self.name));
+        let mut stack = vec![builder.src.join(self.path)];
+        let _time = util::timeit(&builder);
+        let _folder = builder.fold_output(|| format!("test_{}", self.name));
 
         let mut files = Vec::new();
         while let Some(p) = stack.pop() {
@@ -1057,7 +1148,7 @@ fn run(self, builder: &Builder) {
             }
 
             // The nostarch directory in the book is for no starch, and so isn't
-            // guaranteed to build. We don't care if it doesn't build, so skip it.
+            // guaranteed to builder. We don't care if it doesn't build, so skip it.
             if p.to_str().map_or(false, |p| p.contains("nostarch")) {
                 continue;
             }
@@ -1075,7 +1166,7 @@ fn run(self, builder: &Builder) {
                 } else {
                     ToolState::TestFail
                 };
-                build.save_toolstate(self.name, toolstate);
+                builder.save_toolstate(self.name, toolstate);
             }
         }
     }
@@ -1153,32 +1244,30 @@ fn make_run(run: RunConfig) {
     /// generate a markdown file from the error indexes of the code base which is
     /// then passed to `rustdoc --test`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
 
         builder.ensure(compile::Std { compiler, target: compiler.host });
 
-        let dir = testdir(build, compiler.host);
+        let dir = testdir(builder, compiler.host);
         t!(fs::create_dir_all(&dir));
         let output = dir.join("error-index.md");
 
         let mut tool = builder.tool_cmd(Tool::ErrorIndex);
         tool.arg("markdown")
             .arg(&output)
-            .env("CFG_BUILD", &build.build)
-            .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir());
+            .env("CFG_BUILD", &builder.config.build)
+            .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir());
 
 
-        let _folder = build.fold_output(|| "test_error_index");
-        build.info(&format!("Testing error-index stage{}", compiler.stage));
-        let _time = util::timeit(&build);
-        build.run(&mut tool);
+        let _folder = builder.fold_output(|| "test_error_index");
+        builder.info(&format!("Testing error-index stage{}", compiler.stage));
+        let _time = util::timeit(&builder);
+        builder.run(&mut tool);
         markdown_test(builder, compiler, &output);
     }
 }
 
 fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool {
-    let build = builder.build;
     match File::open(markdown) {
         Ok(mut file) => {
             let mut contents = String::new();
@@ -1190,20 +1279,20 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool
         Err(_) => {},
     }
 
-    build.info(&format!("doc tests for: {}", markdown.display()));
+    builder.info(&format!("doc tests for: {}", markdown.display()));
     let mut cmd = builder.rustdoc_cmd(compiler.host);
-    build.add_rust_test_threads(&mut cmd);
+    builder.add_rust_test_threads(&mut cmd);
     cmd.arg("--test");
     cmd.arg(markdown);
     cmd.env("RUSTC_BOOTSTRAP", "1");
 
-    let test_args = build.config.cmd.test_args().join(" ");
+    let test_args = builder.config.cmd.test_args().join(" ");
     cmd.arg("--test-args").arg(test_args);
 
-    if build.config.quiet_tests {
-        try_run_quiet(build, &mut cmd)
+    if builder.config.quiet_tests {
+        try_run_quiet(builder, &mut cmd)
     } else {
-        try_run(build, &mut cmd)
+        try_run(builder, &mut cmd)
     }
 }
 
@@ -1387,7 +1476,6 @@ fn make_run(run: RunConfig) {
     /// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
     /// arguments, and those arguments are discovered from `cargo metadata`.
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
         let mode = self.mode;
@@ -1401,7 +1489,7 @@ fn run(self, builder: &Builder) {
         // libstd, then what we're actually testing is the libstd produced in
         // stage1. Reflect that here by updating the compiler that we're working
         // with automatically.
-        let compiler = if build.force_use_stage1(compiler, target) {
+        let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
             compiler.clone()
@@ -1413,11 +1501,11 @@ fn run(self, builder: &Builder) {
                 compile::std_cargo(builder, &compiler, target, &mut cargo);
             }
             Mode::Libtest => {
-                compile::test_cargo(build, &compiler, target, &mut cargo);
+                compile::test_cargo(builder, &compiler, target, &mut cargo);
             }
             Mode::Librustc => {
                 builder.ensure(compile::Rustc { compiler, target });
-                compile::rustc_cargo(build, &mut cargo);
+                compile::rustc_cargo(builder, &mut cargo);
             }
             _ => panic!("can only test libraries"),
         };
@@ -1427,10 +1515,10 @@ fn run(self, builder: &Builder) {
         // Pass in some standard flags then iterate over the graph we've discovered
         // in `cargo metadata` with the maps above and figure out what `-p`
         // arguments need to get passed.
-        if test_kind.subcommand() == "test" && !build.fail_fast {
+        if test_kind.subcommand() == "test" && !builder.fail_fast {
             cargo.arg("--no-fail-fast");
         }
-        if build.doc_tests {
+        if builder.doc_tests {
             cargo.arg("--doc");
         }
 
@@ -1446,21 +1534,21 @@ fn run(self, builder: &Builder) {
         cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
         cargo.arg("--");
-        cargo.args(&build.config.cmd.test_args());
+        cargo.args(&builder.config.cmd.test_args());
 
-        if build.config.quiet_tests {
+        if builder.config.quiet_tests {
             cargo.arg("--quiet");
         }
 
         if target.contains("emscripten") {
             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
-                      build.config.nodejs.as_ref().expect("nodejs not configured"));
+                      builder.config.nodejs.as_ref().expect("nodejs not configured"));
         } else if target.starts_with("wasm32") {
             // Warn about running tests without the `wasm_syscall` feature enabled.
             // The javascript shim implements the syscall interface so that test
             // output can be correctly reported.
-            if !build.config.wasm_syscall {
-                build.info(&format!("Libstd was built without `wasm_syscall` feature enabled: \
+            if !builder.config.wasm_syscall {
+                builder.info(&format!("Libstd was built without `wasm_syscall` feature enabled: \
                           test output may not be visible."));
             }
 
@@ -1468,25 +1556,25 @@ fn run(self, builder: &Builder) {
             // incompatible with `-C prefer-dynamic`, so disable that here
             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
 
-            let node = build.config.nodejs.as_ref()
+            let node = builder.config.nodejs.as_ref()
                 .expect("nodejs not configured");
             let runner = format!("{} {}/src/etc/wasm32-shim.js",
                                  node.display(),
-                                 build.src.display());
+                                 builder.src.display());
             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner);
-        } else if build.remote_tested(target) {
+        } else if builder.remote_tested(target) {
             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
                       format!("{} run",
                               builder.tool_exe(Tool::RemoteTestClient).display()));
         }
 
-        let _folder = build.fold_output(|| {
+        let _folder = builder.fold_output(|| {
             format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate)
         });
-        build.info(&format!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage,
+        builder.info(&format!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage,
                 &compiler.host, target));
-        let _time = util::timeit(&build);
-        try_run(build, &mut cargo);
+        let _time = util::timeit(&builder);
+        try_run(builder, &mut cargo);
     }
 }
 
@@ -1523,7 +1611,6 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let test_kind = self.test_kind;
 
         let compiler = builder.compiler(builder.top_stage, self.host);
@@ -1534,27 +1621,27 @@ fn run(self, builder: &Builder) {
                                                  target,
                                                  test_kind.subcommand(),
                                                  "src/tools/rustdoc");
-        if test_kind.subcommand() == "test" && !build.fail_fast {
+        if test_kind.subcommand() == "test" && !builder.fail_fast {
             cargo.arg("--no-fail-fast");
         }
 
         cargo.arg("-p").arg("rustdoc:0.0.0");
 
         cargo.arg("--");
-        cargo.args(&build.config.cmd.test_args());
+        cargo.args(&builder.config.cmd.test_args());
 
-        if build.config.quiet_tests {
+        if builder.config.quiet_tests {
             cargo.arg("--quiet");
         }
 
-        let _folder = build.fold_output(|| {
+        let _folder = builder.fold_output(|| {
             format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage)
         });
-        build.info(&format!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage,
+        builder.info(&format!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage,
                 &compiler.host, target));
-        let _time = util::timeit(&build);
+        let _time = util::timeit(&builder);
 
-        try_run(build, &mut cargo);
+        try_run(builder, &mut cargo);
     }
 }
 
@@ -1590,17 +1677,16 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
-        if !build.remote_tested(target) {
+        if !builder.remote_tested(target) {
             return
         }
 
         builder.ensure(compile::Test { compiler, target });
 
-        build.info(&format!("REMOTE copy libs to emulator ({})", target));
-        t!(fs::create_dir_all(build.out.join("tmp")));
+        builder.info(&format!("REMOTE copy libs to emulator ({})", target));
+        t!(fs::create_dir_all(builder.out.join("tmp")));
 
         let server = builder.ensure(tool::RemoteTestServer { compiler, target });
 
@@ -1610,18 +1696,18 @@ fn run(self, builder: &Builder) {
         cmd.arg("spawn-emulator")
            .arg(target)
            .arg(&server)
-           .arg(build.out.join("tmp"));
-        if let Some(rootfs) = build.qemu_rootfs(target) {
+           .arg(builder.out.join("tmp"));
+        if let Some(rootfs) = builder.qemu_rootfs(target) {
             cmd.arg(rootfs);
         }
-        build.run(&mut cmd);
+        builder.run(&mut cmd);
 
         // Push all our dylibs to the emulator
         for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
             let f = t!(f);
             let name = f.file_name().into_string().unwrap();
             if util::is_dylib(&name) {
-                build.run(Command::new(&tool)
+                builder.run(Command::new(&tool)
                                   .arg("push")
                                   .arg(f.path()));
             }
@@ -1645,10 +1731,8 @@ fn make_run(run: RunConfig) {
 
     /// Run "distcheck", a 'make check' from a tarball
     fn run(self, builder: &Builder) {
-        let build = builder.build;
-
-        build.info(&format!("Distcheck"));
-        let dir = build.out.join("tmp").join("distcheck");
+        builder.info(&format!("Distcheck"));
+        let dir = builder.out.join("tmp").join("distcheck");
         let _ = fs::remove_dir_all(&dir);
         t!(fs::create_dir_all(&dir));
 
@@ -1661,18 +1745,18 @@ fn run(self, builder: &Builder) {
            .arg(builder.ensure(dist::PlainSourceTarball))
            .arg("--strip-components=1")
            .current_dir(&dir);
-        build.run(&mut cmd);
-        build.run(Command::new("./configure")
-                         .args(&build.config.configure_args)
+        builder.run(&mut cmd);
+        builder.run(Command::new("./configure")
+                         .args(&builder.config.configure_args)
                          .arg("--enable-vendor")
                          .current_dir(&dir));
-        build.run(Command::new(build_helper::make(&build.build))
+        builder.run(Command::new(build_helper::make(&builder.config.build))
                          .arg("check")
                          .current_dir(&dir));
 
         // Now make sure that rust-src has all of libstd's dependencies
-        build.info(&format!("Distcheck rust-src"));
-        let dir = build.out.join("tmp").join("distcheck-src");
+        builder.info(&format!("Distcheck rust-src"));
+        let dir = builder.out.join("tmp").join("distcheck-src");
         let _ = fs::remove_dir_all(&dir);
         t!(fs::create_dir_all(&dir));
 
@@ -1681,10 +1765,10 @@ fn run(self, builder: &Builder) {
            .arg(builder.ensure(dist::Src))
            .arg("--strip-components=1")
            .current_dir(&dir);
-        build.run(&mut cmd);
+        builder.run(&mut cmd);
 
         let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
-        build.run(Command::new(&build.initial_cargo)
+        builder.run(Command::new(&builder.initial_cargo)
                          .arg("generate-lockfile")
                          .arg("--manifest-path")
                          .arg(&toml)
@@ -1702,25 +1786,24 @@ impl Step for Bootstrap {
 
     /// Test the build system itself
     fn run(self, builder: &Builder) {
-        let build = builder.build;
-        let mut cmd = Command::new(&build.initial_cargo);
+        let mut cmd = Command::new(&builder.initial_cargo);
         cmd.arg("test")
-           .current_dir(build.src.join("src/bootstrap"))
+           .current_dir(builder.src.join("src/bootstrap"))
            .env("RUSTFLAGS", "-Cdebuginfo=2")
-           .env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
+           .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
            .env("RUSTC_BOOTSTRAP", "1")
-           .env("RUSTC", &build.initial_rustc);
+           .env("RUSTC", &builder.initial_rustc);
         if let Some(flags) = option_env!("RUSTFLAGS") {
             // Use the same rustc flags for testing as for "normal" compilation,
             // so that Cargo doesn’t recompile the entire dependency graph every time:
             // https://github.com/rust-lang/rust/issues/49215
             cmd.env("RUSTFLAGS", flags);
         }
-        if !build.fail_fast {
+        if !builder.fail_fast {
             cmd.arg("--no-fail-fast");
         }
-        cmd.arg("--").args(&build.config.cmd.test_args());
-        try_run(build, &mut cmd);
+        cmd.arg("--").args(&builder.config.cmd.test_args());
+        try_run(builder, &mut cmd);
     }
 
     fn should_run(run: ShouldRun) -> ShouldRun {
index 97507bc08698a737882a93a62491aeebe8bdfe8b..6c29bd84fe4673b407da036a821a3d3add99d55a 100644 (file)
@@ -38,7 +38,6 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     }
 
     fn run(self, builder: &Builder) {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
         let mode = self.mode;
@@ -46,7 +45,7 @@ fn run(self, builder: &Builder) {
         // 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 = build.stage_out(compiler, Mode::Tool);
+        let tools_dir = builder.stage_out(compiler, Mode::Tool);
         let compiler = if builder.force_use_stage1(compiler, target) {
             builder.compiler(1, compiler.host)
         } else {
@@ -55,13 +54,13 @@ fn run(self, builder: &Builder) {
 
         for &cur_mode in &[Mode::Libstd, Mode::Libtest, Mode::Librustc] {
             let stamp = match cur_mode {
-                Mode::Libstd => libstd_stamp(build, compiler, target),
-                Mode::Libtest => libtest_stamp(build, compiler, target),
-                Mode::Librustc => librustc_stamp(build, compiler, target),
+                Mode::Libstd => libstd_stamp(builder, compiler, target),
+                Mode::Libtest => libtest_stamp(builder, compiler, target),
+                Mode::Librustc => librustc_stamp(builder, compiler, target),
                 _ => panic!(),
             };
 
-            if build.clear_if_dirty(&tools_dir, &stamp) {
+            if builder.clear_if_dirty(&tools_dir, &stamp) {
                 break;
             }
 
@@ -97,7 +96,6 @@ fn should_run(run: ShouldRun) -> ShouldRun {
     /// This will build the specified tool with the specified `host` compiler in
     /// `stage` into the normal cargo output directory.
     fn run(self, builder: &Builder) -> Option<PathBuf> {
-        let build = builder.build;
         let compiler = self.compiler;
         let target = self.target;
         let tool = self.tool;
@@ -114,10 +112,10 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
         cargo.arg("--features").arg(self.extra_features.join(" "));
 
-        let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
-        build.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
+        let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
+        builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
         let mut duplicates = Vec::new();
-        let is_expected = compile::stream_cargo(build, &mut cargo, &mut |msg| {
+        let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| {
             // Only care about big things like the RLS/Cargo for now
             if tool != "rls" && tool != "cargo" {
                 return
@@ -156,7 +154,7 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
                     }
                 }
 
-                let mut artifacts = build.tool_artifacts.borrow_mut();
+                let mut artifacts = builder.tool_artifacts.borrow_mut();
                 let prev_artifacts = artifacts
                     .entry(target)
                     .or_insert_with(Default::default);
@@ -190,7 +188,7 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
             panic!("tools should not compile multiple copies of the same crate");
         }
 
-        build.save_toolstate(tool, if is_expected {
+        builder.save_toolstate(tool, if is_expected {
             ToolState::TestFail
         } else {
             ToolState::BuildFail
@@ -203,10 +201,10 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
                 return None;
             }
         } else {
-            let cargo_out = build.cargo_out(compiler, Mode::Tool, target)
+            let cargo_out = builder.cargo_out(compiler, Mode::Tool, target)
                 .join(exe(tool, &compiler.host));
-            let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host));
-            build.copy(&cargo_out, &bin);
+            let bin = builder.tools_dir(compiler).join(exe(tool, &compiler.host));
+            builder.copy(&cargo_out, &bin);
             Some(bin)
         }
     }
@@ -219,16 +217,15 @@ pub fn prepare_tool_cargo(
     command: &'static str,
     path: &'static str,
 ) -> Command {
-    let build = builder.build;
     let mut cargo = builder.cargo(compiler, Mode::Tool, target, command);
-    let dir = build.src.join(path);
+    let dir = builder.src.join(path);
     cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
 
     // We don't want to build tools dynamically as they'll be running across
     // stages and such and it's just easier if they're not dynamically linked.
     cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
 
-    if let Some(dir) = build.openssl_install_dir(target) {
+    if let Some(dir) = builder.openssl_install_dir(target) {
         cargo.env("OPENSSL_STATIC", "1");
         cargo.env("OPENSSL_DIR", dir);
         cargo.env("LIBZ_SYS_STATIC", "1");
@@ -238,10 +235,10 @@ pub fn prepare_tool_cargo(
     // own copy
     cargo.env("LZMA_API_STATIC", "1");
 
-    cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);
-    cargo.env("CFG_VERSION", build.rust_version());
+    cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
+    cargo.env("CFG_VERSION", builder.rust_version());
 
-    let info = GitInfo::new(&build.config, &dir);
+    let info = GitInfo::new(&builder.config, &dir);
     if let Some(sha) = info.sha() {
         cargo.env("CFG_COMMIT_HASH", sha);
     }
@@ -269,8 +266,8 @@ pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                 match tool {
                     $(Tool::$name =>
                         self.ensure($name {
-                            compiler: self.compiler(stage, self.build.build),
-                            target: self.build.build,
+                            compiler: self.compiler(stage, self.config.build),
+                            target: self.config.build,
                         }),
                     )+
                 }
@@ -304,7 +301,7 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
             fn make_run(run: RunConfig) {
                 run.builder.ensure($name {
-                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
                     target: run.target,
                 });
             }
@@ -354,7 +351,7 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(RemoteTestServer {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
         });
     }
@@ -393,26 +390,25 @@ fn make_run(run: RunConfig) {
     }
 
     fn run(self, builder: &Builder) -> PathBuf {
-        let build = builder.build;
         let target_compiler = builder.compiler(builder.top_stage, self.host);
         let target = target_compiler.host;
         let build_compiler = if target_compiler.stage == 0 {
-            builder.compiler(0, builder.build.build)
+            builder.compiler(0, builder.config.build)
         } else if target_compiler.stage >= 2 {
             // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of
             // building rustdoc itself.
-            builder.compiler(target_compiler.stage, builder.build.build)
+            builder.compiler(target_compiler.stage, builder.config.build)
         } else {
             // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
             // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
             // compilers, which isn't what we want.
-            builder.compiler(target_compiler.stage - 1, builder.build.build)
+            builder.compiler(target_compiler.stage - 1, builder.config.build)
         };
 
         builder.ensure(compile::Rustc { compiler: build_compiler, target });
         builder.ensure(compile::Rustc {
             compiler: build_compiler,
-            target: builder.build.build,
+            target: builder.config.build,
         });
 
         let mut cargo = prepare_tool_cargo(builder,
@@ -425,15 +421,15 @@ fn run(self, builder: &Builder) -> PathBuf {
         cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string())
              .env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string());
 
-        let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
-        build.info(&format!("Building rustdoc for stage{} ({})",
+        let _folder = builder.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
+        builder.info(&format!("Building rustdoc for stage{} ({})",
             target_compiler.stage, target_compiler.host));
-        build.run(&mut cargo);
+        builder.run(&mut cargo);
 
         // Cargo adds a number of paths to the dylib search path on windows, which results in
         // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
         // rustdoc a different name.
-        let tool_rustdoc = build.cargo_out(build_compiler, Mode::Tool, target)
+        let tool_rustdoc = builder.cargo_out(build_compiler, Mode::Tool, target)
             .join(exe("rustdoc-tool-binary", &target_compiler.host));
 
         // don't create a stage0-sysroot/bin directory.
@@ -443,7 +439,7 @@ fn run(self, builder: &Builder) -> PathBuf {
             t!(fs::create_dir_all(&bindir));
             let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host));
             let _ = fs::remove_file(&bin_rustdoc);
-            build.copy(&tool_rustdoc, &bin_rustdoc);
+            builder.copy(&tool_rustdoc, &bin_rustdoc);
             bin_rustdoc
         } else {
             tool_rustdoc
@@ -464,12 +460,12 @@ impl Step for Cargo {
 
     fn should_run(run: ShouldRun) -> ShouldRun {
         let builder = run.builder;
-        run.path("src/tools/cargo").default_condition(builder.build.config.extended)
+        run.path("src/tools/cargo").default_condition(builder.config.extended)
     }
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(Cargo {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
         });
     }
@@ -482,7 +478,7 @@ fn run(self, builder: &Builder) -> PathBuf {
         // compiler to be available, so we need to depend on that.
         builder.ensure(compile::Rustc {
             compiler: self.compiler,
-            target: builder.build.build,
+            target: builder.config.build,
         });
         builder.ensure(ToolBuild {
             compiler: self.compiler,
@@ -518,12 +514,12 @@ impl Step for $name {
 
             fn should_run(run: ShouldRun) -> ShouldRun {
                 let builder = run.builder;
-                run.path($path).default_condition(builder.build.config.extended)
+                run.path($path).default_condition(builder.config.extended)
             }
 
             fn make_run(run: RunConfig) {
                 run.builder.ensure($name {
-                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
                     target: run.target,
                     extra_features: Vec::new(),
                 });
@@ -554,7 +550,7 @@ fn run(mut $sel, $builder: &Builder) -> Option<PathBuf> {
         // compiler to be available, so we need to depend on that.
         builder.ensure(compile::Rustc {
             compiler: self.compiler,
-            target: builder.build.build,
+            target: builder.config.build,
         });
     };
     Miri, miri, "src/tools/miri", "miri", {};
@@ -575,7 +571,7 @@ fn run(mut $sel, $builder: &Builder) -> Option<PathBuf> {
         // compiler to be available, so we need to depend on that.
         builder.ensure(compile::Rustc {
             compiler: self.compiler,
-            target: builder.build.build,
+            target: builder.config.build,
         });
     };
     Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", {};
@@ -586,7 +582,7 @@ impl<'a> Builder<'a> {
     /// `host`.
     pub fn tool_cmd(&self, tool: Tool) -> Command {
         let mut cmd = Command::new(self.tool_exe(tool));
-        let compiler = self.compiler(self.tool_default_stage(tool), self.build.build);
+        let compiler = self.compiler(self.tool_default_stage(tool), self.config.build);
         self.prepare_tool_cmd(compiler, &mut cmd);
         cmd
     }
index f8c7032369890b8472a66083dee9ae9b467d6abe..9a2b9e90440e53d909f8016a981585f16b2b4356 100644 (file)
@@ -22,7 +22,7 @@
 use std::time::{SystemTime, Instant};
 
 use config::Config;
-use Build;
+use builder::Builder;
 
 /// Returns the `name` as the filename of a static library for `target`.
 pub fn staticlib(name: &str, target: &str) -> String {
@@ -104,8 +104,8 @@ pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf {
 pub struct TimeIt(bool, Instant);
 
 /// Returns an RAII structure that prints out how long it took to drop.
-pub fn timeit(build: &Build) -> TimeIt {
-    TimeIt(build.config.dry_run, Instant::now())
+pub fn timeit(builder: &Builder) -> TimeIt {
+    TimeIt(builder.config.dry_run, Instant::now())
 }
 
 impl Drop for TimeIt {
index 853923ad947cd2ced021be50f5e7ef8e93c73c51..56eda5480715bc1b5517f4d916f5b27b7718ad34 100644 (file)
@@ -25,6 +25,12 @@ ENV RUST_CONFIGURE_ARGS \
   --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \
   --set rust.lld
 
+# Some run-make tests have assertions about code size, and enabling debug
+# assertions in libstd causes the binary to be much bigger than it would
+# otherwise normally be. We already test libstd with debug assertions in lots of
+# other contexts as well
+ENV NO_DEBUG_ASSERTIONS=1
+
 ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \
   src/test/run-make \
   src/test/ui \
index fea8685a605d6859b52fcd4a3806d016b5826e06..3098587a8a4ccc11f1e09e4cb40be02d604d3a01 100644 (file)
@@ -138,31 +138,31 @@ To keep each code block testable, we want the whole program in each block, but
 we don't want the reader to see every line every time.  Here's what we put in
 our source code:
 
-```text
-    First, we set `x` to five:
+``````markdown
+First, we set `x` to five:
 
-    ```
-    let x = 5;
-    # let y = 6;
-    # println!("{}", x + y);
-    ```
+```
+let x = 5;
+# let y = 6;
+# println!("{}", x + y);
+```
 
-    Next, we set `y` to six:
+Next, we set `y` to six:
 
-    ```
-    # let x = 5;
-    let y = 6;
-    # println!("{}", x + y);
-    ```
+```
+# let x = 5;
+let y = 6;
+# println!("{}", x + y);
+```
 
-    Finally, we print the sum of `x` and `y`:
+Finally, we print the sum of `x` and `y`:
 
-    ```
-    # let x = 5;
-    # let y = 6;
-    println!("{}", x + y);
-    ```
 ```
+# let x = 5;
+# let y = 6;
+println!("{}", x + y);
+```
+``````
 
 By repeating all parts of the example, you can ensure that your example still
 compiles, while only showing the parts that are relevant to that part of your
index bf97fb4686180f981f7c9e4983606f9910455f1b..7f110d6a3d22c20e4550047121fad058f565312e 100644 (file)
@@ -373,3 +373,19 @@ This is an internal flag intended for the standard library and compiler that app
 `#[unstable]` attribute to any dependent crate that doesn't have another stability attribute. This
 allows `rustdoc` to be able to generate documentation for the compiler crates and the standard
 library, as an equivalent command-line argument is provided to `rustc` when building those crates.
+
+### `doc_alias` feature
+
+This feature allows you to add alias(es) to an item when using the `rustdoc` search through the
+`doc(alias)` attribute. Example:
+
+```rust,no_run
+#![feature(doc_alias)]
+
+#[doc(alias = "x")]
+#[doc(alias = "big")]
+pub struct BigX;
+```
+
+Then, when looking for it through the `rustdoc` search, if you enter "x" or
+"big", search will show the `BigX` struct first.
diff --git a/src/doc/unstable-book/src/language-features/doc-alias.md b/src/doc/unstable-book/src/language-features/doc-alias.md
new file mode 100644 (file)
index 0000000..647ac0c
--- /dev/null
@@ -0,0 +1,23 @@
+# `doc_alias`
+
+The tracking issue for this feature is: [#50146]
+
+[#50146]: https://github.com/rust-lang/rust/issues/50146
+
+------------------------
+
+You can add alias(es) to an item when using the `rustdoc` search through the
+`doc(alias)` attribute. Example:
+
+```rust,no_run
+#![feature(doc_alias)]
+
+#[doc(alias = "x")]
+#[doc(alias = "big")]
+pub struct BigX;
+```
+
+Then, when looking for it through the `rustdoc` search, if you enter "x" or
+"big", search will show the `BigX` struct first.
+
+Note that this feature is currently hidden behind the `feature(doc_alias)` gate.
diff --git a/src/doc/unstable-book/src/library-features/slice-rsplit.md b/src/doc/unstable-book/src/library-features/slice-rsplit.md
deleted file mode 100644 (file)
index 8c2954f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# `slice_rsplit`
-
-The tracking issue for this feature is: [#41020]
-
-[#41020]: https://github.com/rust-lang/rust/issues/41020
-
-------------------------
-
-The `slice_rsplit` feature enables two methods on slices:
-`slice.rsplit(predicate)` and `slice.rsplit_mut(predicate)`.
index 68a617e0ffed4371e21570a16d975e2c964fc02f..c0372d24ed50151f87e617c385a8d27a79e2f5bc 100644 (file)
@@ -48,9 +48,6 @@ fn __rust_realloc(ptr: *mut u8,
     #[allocator]
     #[rustc_allocator_nounwind]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
-    #[cold]
-    #[rustc_allocator_nounwind]
-    fn __rust_oom() -> !;
     #[rustc_allocator_nounwind]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
     #[rustc_allocator_nounwind]
@@ -107,16 +104,6 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
         let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0);
         ptr as *mut Opaque
     }
-
-    #[inline]
-    fn oom(&self) -> ! {
-        unsafe {
-            #[cfg(not(stage0))]
-            __rust_oom();
-            #[cfg(stage0)]
-            __rust_oom(&mut 0);
-        }
-    }
 }
 
 unsafe impl Alloc for Global {
@@ -144,11 +131,6 @@ unsafe fn realloc(&mut self,
     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        GlobalAlloc::oom(self)
-    }
 }
 
 /// The allocator for unique pointers.
@@ -165,7 +147,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
         if !ptr.is_null() {
             ptr as *mut u8
         } else {
-            Global.oom()
+            oom()
         }
     }
 }
@@ -182,19 +164,33 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
     }
 }
 
+#[cfg(stage0)]
+pub fn oom() -> ! {
+    unsafe { ::core::intrinsics::abort() }
+}
+
+#[cfg(not(stage0))]
+pub fn oom() -> ! {
+    extern {
+        #[lang = "oom"]
+        fn oom_impl() -> !;
+    }
+    unsafe { oom_impl() }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate test;
     use self::test::Bencher;
     use boxed::Box;
-    use alloc::{Global, Alloc, Layout};
+    use alloc::{Global, Alloc, Layout, oom};
 
     #[test]
     fn allocate_zeroed() {
         unsafe {
             let layout = Layout::from_size_align(1024, 1).unwrap();
             let ptr = Global.alloc_zeroed(layout.clone())
-                .unwrap_or_else(|_| Global.oom());
+                .unwrap_or_else(|_| oom());
 
             let mut i = ptr.cast::<u8>().as_ptr();
             let end = i.offset(layout.size() as isize);
index 225b055d8ee8296129faae4ddacef105172a1186..f5980f4599e45ea8906263819e177dfe233eae41 100644 (file)
@@ -31,7 +31,7 @@
 use core::{isize, usize};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, box_free};
+use alloc::{Global, Alloc, Layout, box_free, oom};
 use boxed::Box;
 use string::String;
 use vec::Vec;
@@ -553,7 +553,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         // Initialize the real ArcInner
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
index aceb6ff8abe2a7a6d914f3d8d250cf2ca853c393..5ebd2cc6146371febfa208b013699eadee9e963a 100644 (file)
@@ -429,6 +429,7 @@ fn from(slice: &'a [T]) -> Box<[T]> {
 
 #[stable(feature = "box_from_slice", since = "1.17.0")]
 impl<'a> From<&'a str> for Box<str> {
+    #[inline]
     fn from(s: &'a str) -> Box<str> {
         unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
     }
@@ -436,6 +437,7 @@ fn from(s: &'a str) -> Box<str> {
 
 #[stable(feature = "boxed_str_conv", since = "1.19.0")]
 impl From<Box<str>> for Box<[u8]> {
+    #[inline]
     fn from(s: Box<str>) -> Self {
         unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) }
     }
index c604df7049e0c02e10f53809f5c610986200b1a9..3984379ea860dd3eabbb099da3c691cb78fcab61 100644 (file)
@@ -1287,8 +1287,7 @@ fn into_iter(self) -> IntoIter<K, V> {
 #[stable(feature = "btree_drop", since = "1.7.0")]
 impl<K, V> Drop for IntoIter<K, V> {
     fn drop(&mut self) {
-        for _ in &mut *self {
-        }
+        self.for_each(drop);
         unsafe {
             let leaf_node = ptr::read(&self.front).into_node();
             if let Some(first_parent) = leaf_node.deallocate_and_ascend() {
@@ -2156,8 +2155,8 @@ pub fn key(&self) -> &K {
     /// assert_eq!(map["poneyland"], 43);
     /// ```
     #[stable(feature = "entry_and_modify", since = "1.26.0")]
-    pub fn and_modify<F>(self, mut f: F) -> Self
-        where F: FnMut(&mut V)
+    pub fn and_modify<F>(self, f: F) -> Self
+        where F: FnOnce(&mut V)
     {
         match self {
             Occupied(mut entry) => {
index faac38ca7ce15d5a35fe1e09f06f4b223b009fc7..16f0630b91134dd62965aa04d75663b98cc402f6 100644 (file)
@@ -59,7 +59,7 @@ unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
     }
 
     fn oom(&mut self, _: AllocErr) -> ! {
-        CoreAlloc::oom(self)
+        unsafe { ::core::intrinsics::abort() }
     }
 
     fn usable_size(&self, layout: &Layout) -> (usize, usize) {
index 3a106a2ff5c3debd6e19205a2f49a6fbc7b5b600..6399be98cd5197f9d3d2eae08d30ae746c35c9ce 100644 (file)
@@ -75,7 +75,7 @@
 #![deny(missing_debug_implementations)]
 
 #![cfg_attr(test, allow(deprecated))] // rand
-#![cfg_attr(not(test), feature(core_float))]
+#![cfg_attr(all(not(test), stage0), feature(float_internals))]
 #![cfg_attr(not(test), feature(exact_size_is_empty))]
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(rand, test))]
@@ -90,6 +90,8 @@
 #![feature(collections_range)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
+#![cfg_attr(stage0, feature(core_slice_ext))]
+#![cfg_attr(stage0, feature(core_str_ext))]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(needs_allocator)]
-#![feature(nonnull_cast)]
 #![feature(nonzero)]
 #![feature(optin_builtin_traits)]
 #![feature(pattern)]
 #![feature(ptr_offset_from)]
 #![feature(rustc_attrs)]
 #![feature(slice_get_slice)]
-#![feature(slice_rsplit)]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(str_internals)]
 #![feature(inclusive_range_fields)]
 #![cfg_attr(stage0, feature(generic_param_attrs))]
 
-#![cfg_attr(not(test), feature(fn_traits, swap_with_slice, i128))]
+#![cfg_attr(not(test), feature(fn_traits, i128))]
 #![cfg_attr(test, feature(test))]
 
 // Allow testing this library
index 129b3bc676432f058912c01ae3e834467ff34b0d..9844de9a57d70274c4bf91cc93d79da0e381acf4 100644 (file)
@@ -1019,7 +1019,7 @@ impl<'a, T, F> Drop for DrainFilter<'a, T, F>
     where F: FnMut(&mut T) -> bool,
 {
     fn drop(&mut self) {
-        for _ in self { }
+        self.for_each(drop);
     }
 }
 
index 405814c021afef423e4599e514c9e6d19683ba78..7ef0a27fc7258876768fb3abfaac3396e9ff8da4 100644 (file)
@@ -14,7 +14,7 @@
 use core::ptr::{self, NonNull, Unique};
 use core::slice;
 
-use alloc::{Alloc, Layout, Global};
+use alloc::{Alloc, Layout, Global, oom};
 use alloc::CollectionAllocErr;
 use alloc::CollectionAllocErr::*;
 use boxed::Box;
@@ -86,8 +86,8 @@ fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
         unsafe {
             let elem_size = mem::size_of::<T>();
 
-            let alloc_size = cap.checked_mul(elem_size).expect("capacity overflow");
-            alloc_guard(alloc_size).expect("capacity overflow");
+            let alloc_size = cap.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
+            alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
 
             // handles ZSTs and `cap = 0` alike
             let ptr = if alloc_size == 0 {
@@ -101,7 +101,7 @@ fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
                 };
                 match result {
                     Ok(ptr) => ptr,
-                    Err(_) => a.oom(),
+                    Err(_) => oom(),
                 }
             };
 
@@ -310,13 +310,13 @@ pub fn double(&mut self) {
                     // `from_size_align_unchecked`.
                     let new_cap = 2 * self.cap;
                     let new_size = new_cap * elem_size;
-                    alloc_guard(new_size).expect("capacity overflow");
+                    alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
                     let ptr_res = self.a.realloc(NonNull::from(self.ptr).as_opaque(),
                                                  cur,
                                                  new_size);
                     match ptr_res {
                         Ok(ptr) => (new_cap, ptr.cast().into()),
-                        Err(_) => self.a.oom(),
+                        Err(_) => oom(),
                     }
                 }
                 None => {
@@ -325,7 +325,7 @@ pub fn double(&mut self) {
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
                         Ok(ptr) => (new_cap, ptr.into()),
-                        Err(_) => self.a.oom(),
+                        Err(_) => oom(),
                     }
                 }
             };
@@ -369,7 +369,7 @@ pub fn double_in_place(&mut self) -> bool {
             // overflow and the alignment is sufficiently small.
             let new_cap = 2 * self.cap;
             let new_size = new_cap * elem_size;
-            alloc_guard(new_size).expect("capacity overflow");
+            alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
             match self.a.grow_in_place(NonNull::from(self.ptr).as_opaque(), old_layout, new_size) {
                 Ok(_) => {
                     // We can't directly divide `size`.
@@ -441,8 +441,8 @@ pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize)
 
     pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve_exact(used_cap, needed_extra_cap) {
-            Err(CapacityOverflow) => panic!("capacity overflow"),
-            Err(AllocErr) => self.a.oom(),
+            Err(CapacityOverflow) => capacity_overflow(),
+            Err(AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -551,8 +551,8 @@ pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize)
     /// The same as try_reserve, but errors are lowered to a call to oom().
     pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve(used_cap, needed_extra_cap) {
-            Err(CapacityOverflow) => panic!("capacity overflow"),
-            Err(AllocErr) => self.a.oom(),
+            Err(CapacityOverflow) => capacity_overflow(),
+            Err(AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -592,7 +592,7 @@ pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) ->
             }
 
             let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)
-                              .expect("capacity overflow");
+                .unwrap_or_else(|_| capacity_overflow());
 
             // Here, `cap < used_cap + needed_extra_cap <= new_cap`
             // (regardless of whether `self.cap - used_cap` wrapped).
@@ -600,7 +600,7 @@ pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) ->
 
             let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
             // FIXME: may crash and burn on over-reserve
-            alloc_guard(new_layout.size()).expect("capacity overflow");
+            alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
             match self.a.grow_in_place(
                 NonNull::from(self.ptr).as_opaque(), old_layout, new_layout.size(),
             ) {
@@ -667,7 +667,7 @@ pub fn shrink_to_fit(&mut self, amount: usize) {
                                      old_layout,
                                      new_size) {
                     Ok(p) => self.ptr = p.cast().into(),
-                    Err(_) => self.a.oom(),
+                    Err(_) => oom(),
                 }
             }
             self.cap = amount;
@@ -732,6 +732,13 @@ fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
     }
 }
 
+// One central function responsible for reporting capacity overflows. This'll
+// ensure that the code generation related to these panics is minimal as there's
+// only one location which panics rather than a bunch throughout the module.
+fn capacity_overflow() -> ! {
+    panic!("capacity overflow")
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
index de0422d82bb76aaa77fce3a616e60e461b18a555..8fb8e111754a903e49819309c66c9004e0224e11 100644 (file)
 use core::ptr::{self, NonNull};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, Opaque, box_free};
+use alloc::{Global, Alloc, Layout, Opaque, box_free, oom};
 use string::String;
 use vec::Vec;
 
@@ -668,7 +668,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         // Initialize the real RcBox
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
index 56c53fca62cb1be2ffaf0da408e664ce1e27ab77..4594263c01f23ec38ea72983213392662e303deb 100644 (file)
 use core::mem::size_of;
 use core::mem;
 use core::ptr;
-use core::slice as core_slice;
+#[cfg(stage0)] use core::slice::SliceExt;
 use core::{u8, u16, u32};
 
 use borrow::{Borrow, BorrowMut, ToOwned};
 pub use core::slice::{SplitMut, ChunksMut, Split};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 pub use core::slice::{RSplit, RSplitMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
@@ -171,1064 +171,12 @@ pub fn to_vec<T>(s: &[T]) -> Vec<T>
     }
 }
 
-#[lang = "slice"]
+#[cfg_attr(stage0, lang = "slice")]
+#[cfg_attr(not(stage0), lang = "slice_alloc")]
 #[cfg(not(test))]
 impl<T> [T] {
-    /// Returns the number of elements in the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let a = [1, 2, 3];
-    /// assert_eq!(a.len(), 3);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn len(&self) -> usize {
-        core_slice::SliceExt::len(self)
-    }
-
-    /// Returns `true` if the slice has a length of 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let a = [1, 2, 3];
-    /// assert!(!a.is_empty());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        core_slice::SliceExt::is_empty(self)
-    }
-
-    /// Returns the first element of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&10), v.first());
-    ///
-    /// let w: &[i32] = &[];
-    /// assert_eq!(None, w.first());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn first(&self) -> Option<&T> {
-        core_slice::SliceExt::first(self)
-    }
-
-    /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some(first) = x.first_mut() {
-    ///     *first = 5;
-    /// }
-    /// assert_eq!(x, &[5, 1, 2]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn first_mut(&mut self) -> Option<&mut T> {
-        core_slice::SliceExt::first_mut(self)
-    }
-
-    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[0, 1, 2];
-    ///
-    /// if let Some((first, elements)) = x.split_first() {
-    ///     assert_eq!(first, &0);
-    ///     assert_eq!(elements, &[1, 2]);
-    /// }
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_first(&self) -> Option<(&T, &[T])> {
-        core_slice::SliceExt::split_first(self)
-    }
-
-    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some((first, elements)) = x.split_first_mut() {
-    ///     *first = 3;
-    ///     elements[0] = 4;
-    ///     elements[1] = 5;
-    /// }
-    /// assert_eq!(x, &[3, 4, 5]);
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        core_slice::SliceExt::split_first_mut(self)
-    }
-
-    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[0, 1, 2];
-    ///
-    /// if let Some((last, elements)) = x.split_last() {
-    ///     assert_eq!(last, &2);
-    ///     assert_eq!(elements, &[0, 1]);
-    /// }
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_last(&self) -> Option<(&T, &[T])> {
-        core_slice::SliceExt::split_last(self)
-
-    }
-
-    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some((last, elements)) = x.split_last_mut() {
-    ///     *last = 3;
-    ///     elements[0] = 4;
-    ///     elements[1] = 5;
-    /// }
-    /// assert_eq!(x, &[4, 5, 3]);
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        core_slice::SliceExt::split_last_mut(self)
-    }
-
-    /// Returns the last element of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&30), v.last());
-    ///
-    /// let w: &[i32] = &[];
-    /// assert_eq!(None, w.last());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn last(&self) -> Option<&T> {
-        core_slice::SliceExt::last(self)
-    }
-
-    /// Returns a mutable pointer to the last item in the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some(last) = x.last_mut() {
-    ///     *last = 10;
-    /// }
-    /// assert_eq!(x, &[0, 1, 10]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn last_mut(&mut self) -> Option<&mut T> {
-        core_slice::SliceExt::last_mut(self)
-    }
-
-    /// Returns a reference to an element or subslice depending on the type of
-    /// index.
-    ///
-    /// - If given a position, returns a reference to the element at that
-    ///   position or `None` if out of bounds.
-    /// - If given a range, returns the subslice corresponding to that range,
-    ///   or `None` if out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&40), v.get(1));
-    /// assert_eq!(Some(&[10, 40][..]), v.get(0..2));
-    /// assert_eq!(None, v.get(3));
-    /// assert_eq!(None, v.get(0..4));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn get<I>(&self, index: I) -> Option<&I::Output>
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get(self, index)
-    }
-
-    /// Returns a mutable reference to an element or subslice depending on the
-    /// type of index (see [`get`]) or `None` if the index is out of bounds.
-    ///
-    /// [`get`]: #method.get
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some(elem) = x.get_mut(1) {
-    ///     *elem = 42;
-    /// }
-    /// assert_eq!(x, &[0, 42, 2]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get_mut(self, index)
-    }
-
-    /// Returns a reference to an element or subslice, without doing bounds
-    /// checking.
-    ///
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`get`].
-    ///
-    /// [`get`]: #method.get
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[1, 2, 4];
-    ///
-    /// unsafe {
-    ///     assert_eq!(x.get_unchecked(1), &2);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get_unchecked(self, index)
-    }
-
-    /// Returns a mutable reference to an element or subslice, without doing
-    /// bounds checking.
-    ///
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`get_mut`].
-    ///
-    /// [`get_mut`]: #method.get_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [1, 2, 4];
-    ///
-    /// unsafe {
-    ///     let elem = x.get_unchecked_mut(1);
-    ///     *elem = 13;
-    /// }
-    /// assert_eq!(x, &[1, 13, 4]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get_unchecked_mut(self, index)
-    }
-
-    /// Returns a raw pointer to the slice's buffer.
-    ///
-    /// The caller must ensure that the slice outlives the pointer this
-    /// function returns, or else it will end up pointing to garbage.
-    ///
-    /// Modifying the container referenced by this slice may cause its buffer
-    /// to be reallocated, which would also make any pointers to it invalid.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[1, 2, 4];
-    /// let x_ptr = x.as_ptr();
-    ///
-    /// unsafe {
-    ///     for i in 0..x.len() {
-    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize));
-    ///     }
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_ptr(&self) -> *const T {
-        core_slice::SliceExt::as_ptr(self)
-    }
-
-    /// Returns an unsafe mutable pointer to the slice's buffer.
-    ///
-    /// The caller must ensure that the slice outlives the pointer this
-    /// function returns, or else it will end up pointing to garbage.
-    ///
-    /// Modifying the container referenced by this slice may cause its buffer
-    /// to be reallocated, which would also make any pointers to it invalid.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [1, 2, 4];
-    /// let x_ptr = x.as_mut_ptr();
-    ///
-    /// unsafe {
-    ///     for i in 0..x.len() {
-    ///         *x_ptr.offset(i as isize) += 2;
-    ///     }
-    /// }
-    /// assert_eq!(x, &[3, 4, 6]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_mut_ptr(&mut self) -> *mut T {
-        core_slice::SliceExt::as_mut_ptr(self)
-    }
-
-    /// Swaps two elements in the slice.
-    ///
-    /// # Arguments
-    ///
-    /// * a - The index of the first element
-    /// * b - The index of the second element
-    ///
-    /// # Panics
-    ///
-    /// Panics if `a` or `b` are out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = ["a", "b", "c", "d"];
-    /// v.swap(1, 3);
-    /// assert!(v == ["a", "d", "c", "b"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn swap(&mut self, a: usize, b: usize) {
-        core_slice::SliceExt::swap(self, a, b)
-    }
-
-    /// Reverses the order of elements in the slice, in place.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [1, 2, 3];
-    /// v.reverse();
-    /// assert!(v == [3, 2, 1]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn reverse(&mut self) {
-        core_slice::SliceExt::reverse(self)
-    }
-
-    /// Returns an iterator over the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[1, 2, 4];
-    /// let mut iterator = x.iter();
-    ///
-    /// assert_eq!(iterator.next(), Some(&1));
-    /// assert_eq!(iterator.next(), Some(&2));
-    /// assert_eq!(iterator.next(), Some(&4));
-    /// assert_eq!(iterator.next(), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn iter(&self) -> Iter<T> {
-        core_slice::SliceExt::iter(self)
-    }
-
-    /// Returns an iterator that allows modifying each value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [1, 2, 4];
-    /// for elem in x.iter_mut() {
-    ///     *elem += 2;
-    /// }
-    /// assert_eq!(x, &[3, 4, 6]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn iter_mut(&mut self) -> IterMut<T> {
-        core_slice::SliceExt::iter_mut(self)
-    }
-
-    /// Returns an iterator over all contiguous windows of length
-    /// `size`. The windows overlap. If the slice is shorter than
-    /// `size`, the iterator returns no values.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let slice = ['r', 'u', 's', 't'];
-    /// let mut iter = slice.windows(2);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
-    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
-    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// If the slice is shorter than `size`:
-    ///
-    /// ```
-    /// let slice = ['f', 'o', 'o'];
-    /// let mut iter = slice.windows(4);
-    /// assert!(iter.next().is_none());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn windows(&self, size: usize) -> Windows<T> {
-        core_slice::SliceExt::windows(self, size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a
-    /// time. The chunks are slices and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last chunk will
-    /// not have length `chunk_size`.
-    ///
-    /// See [`exact_chunks`] for a variant of this iterator that returns chunks
-    /// of always exactly `chunk_size` elements.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let slice = ['l', 'o', 'r', 'e', 'm'];
-    /// let mut iter = slice.chunks(2);
-    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
-    /// assert_eq!(iter.next().unwrap(), &['m']);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// [`exact_chunks`]: #method.exact_chunks
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
-        core_slice::SliceExt::chunks(self, chunk_size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a
-    /// time. The chunks are slices and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last up to `chunk_size-1`
-    /// elements will be omitted.
-    ///
-    /// Due to each chunk having exactly `chunk_size` elements, the compiler
-    /// can often optimize the resulting code better than in the case of
-    /// [`chunks`].
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(exact_chunks)]
-    ///
-    /// let slice = ['l', 'o', 'r', 'e', 'm'];
-    /// let mut iter = slice.exact_chunks(2);
-    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// [`chunks`]: #method.chunks
-    #[unstable(feature = "exact_chunks", issue = "47115")]
-    #[inline]
-    pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
-        core_slice::SliceExt::exact_chunks(self, chunk_size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a time.
-    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last chunk will not
-    /// have length `chunk_size`.
-    ///
-    /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
-    /// of always exactly `chunk_size` elements.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = &mut [0, 0, 0, 0, 0];
-    /// let mut count = 1;
-    ///
-    /// for chunk in v.chunks_mut(2) {
-    ///     for elem in chunk.iter_mut() {
-    ///         *elem += count;
-    ///     }
-    ///     count += 1;
-    /// }
-    /// assert_eq!(v, &[1, 1, 2, 2, 3]);
-    /// ```
-    ///
-    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
-        core_slice::SliceExt::chunks_mut(self, chunk_size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a time.
-    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last up to `chunk_size-1`
-    /// elements will be omitted.
-    ///
-    ///
-    /// Due to each chunk having exactly `chunk_size` elements, the compiler
-    /// can often optimize the resulting code better than in the case of
-    /// [`chunks_mut`].
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(exact_chunks)]
-    ///
-    /// let v = &mut [0, 0, 0, 0, 0];
-    /// let mut count = 1;
-    ///
-    /// for chunk in v.exact_chunks_mut(2) {
-    ///     for elem in chunk.iter_mut() {
-    ///         *elem += count;
-    ///     }
-    ///     count += 1;
-    /// }
-    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
-    /// ```
-    ///
-    /// [`chunks_mut`]: #method.chunks_mut
-    #[unstable(feature = "exact_chunks", issue = "47115")]
-    #[inline]
-    pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
-        core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
-    }
-
-    /// Divides one slice into two at an index.
-    ///
-    /// The first will contain all indices from `[0, mid)` (excluding
-    /// the index `mid` itself) and the second will contain all
-    /// indices from `[mid, len)` (excluding the index `len` itself).
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid > len`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [1, 2, 3, 4, 5, 6];
-    ///
-    /// {
-    ///    let (left, right) = v.split_at(0);
-    ///    assert!(left == []);
-    ///    assert!(right == [1, 2, 3, 4, 5, 6]);
-    /// }
-    ///
-    /// {
-    ///     let (left, right) = v.split_at(2);
-    ///     assert!(left == [1, 2]);
-    ///     assert!(right == [3, 4, 5, 6]);
-    /// }
-    ///
-    /// {
-    ///     let (left, right) = v.split_at(6);
-    ///     assert!(left == [1, 2, 3, 4, 5, 6]);
-    ///     assert!(right == []);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
-        core_slice::SliceExt::split_at(self, mid)
-    }
-
-    /// Divides one mutable slice into two at an index.
-    ///
-    /// The first will contain all indices from `[0, mid)` (excluding
-    /// the index `mid` itself) and the second will contain all
-    /// indices from `[mid, len)` (excluding the index `len` itself).
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid > len`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [1, 0, 3, 0, 5, 6];
-    /// // scoped to restrict the lifetime of the borrows
-    /// {
-    ///     let (left, right) = v.split_at_mut(2);
-    ///     assert!(left == [1, 0]);
-    ///     assert!(right == [3, 0, 5, 6]);
-    ///     left[1] = 2;
-    ///     right[1] = 4;
-    /// }
-    /// assert!(v == [1, 2, 3, 4, 5, 6]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
-        core_slice::SliceExt::split_at_mut(self, mid)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`. The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let slice = [10, 40, 33, 20];
-    /// let mut iter = slice.split(|num| num % 3 == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
-    /// assert_eq!(iter.next().unwrap(), &[20]);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// If the first element is matched, an empty slice will be the first item
-    /// returned by the iterator. Similarly, if the last element in the slice
-    /// is matched, an empty slice will be the last item returned by the
-    /// iterator:
-    ///
-    /// ```
-    /// let slice = [10, 40, 33];
-    /// let mut iter = slice.split(|num| num % 3 == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
-    /// assert_eq!(iter.next().unwrap(), &[]);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// If two matched elements are directly adjacent, an empty slice will be
-    /// present between them:
-    ///
-    /// ```
-    /// let slice = [10, 6, 33, 20];
-    /// let mut iter = slice.split(|num| num % 3 == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[10]);
-    /// assert_eq!(iter.next().unwrap(), &[]);
-    /// assert_eq!(iter.next().unwrap(), &[20]);
-    /// assert!(iter.next().is_none());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split<F>(&self, pred: F) -> Split<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::split(self, pred)
-    }
-
-    /// Returns an iterator over mutable subslices separated by elements that
-    /// match `pred`. The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.split_mut(|num| *num % 3 == 0) {
-    ///     group[0] = 1;
-    /// }
-    /// assert_eq!(v, [1, 40, 30, 1, 60, 1]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::split_mut(self, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, starting at the end of the slice and working backwards.
-    /// The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(slice_rsplit)]
-    ///
-    /// let slice = [11, 22, 33, 0, 44, 55];
-    /// let mut iter = slice.rsplit(|num| *num == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[44, 55]);
-    /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
-    /// assert_eq!(iter.next(), None);
-    /// ```
-    ///
-    /// As with `split()`, if the first or last element is matched, an empty
-    /// slice will be the first (or last) item returned by the iterator.
-    ///
-    /// ```
-    /// #![feature(slice_rsplit)]
-    ///
-    /// let v = &[0, 1, 1, 2, 3, 5, 8];
-    /// let mut it = v.rsplit(|n| *n % 2 == 0);
-    /// assert_eq!(it.next().unwrap(), &[]);
-    /// assert_eq!(it.next().unwrap(), &[3, 5]);
-    /// assert_eq!(it.next().unwrap(), &[1, 1]);
-    /// assert_eq!(it.next().unwrap(), &[]);
-    /// assert_eq!(it.next(), None);
-    /// ```
-    #[unstable(feature = "slice_rsplit", issue = "41020")]
-    #[inline]
-    pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplit(self, pred)
-    }
-
-    /// Returns an iterator over mutable subslices separated by elements that
-    /// match `pred`, starting at the end of the slice and working
-    /// backwards. The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(slice_rsplit)]
-    ///
-    /// let mut v = [100, 400, 300, 200, 600, 500];
-    ///
-    /// let mut count = 0;
-    /// for group in v.rsplit_mut(|num| *num % 3 == 0) {
-    ///     count += 1;
-    ///     group[0] = count;
-    /// }
-    /// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
-    /// ```
-    ///
-    #[unstable(feature = "slice_rsplit", issue = "41020")]
-    #[inline]
-    pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplit_mut(self, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to returning at most `n` items. The matched element is
-    /// not contained in the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
-    /// `[20, 60, 50]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.splitn(2, |num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::splitn(self, n, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to returning at most `n` items. The matched element is
-    /// not contained in the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.splitn_mut(2, |num| *num % 3 == 0) {
-    ///     group[0] = 1;
-    /// }
-    /// assert_eq!(v, [1, 40, 30, 1, 60, 50]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::splitn_mut(self, n, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to returning at most `n` items. This starts at the end of
-    /// the slice and works backwards.  The matched element is not contained in
-    /// the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split once, starting from the end, by numbers divisible
-    /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplitn(self, n, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to returning at most `n` items. This starts at the end of
-    /// the slice and works backwards. The matched element is not contained in
-    /// the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut s = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
-    ///     group[0] = 1;
-    /// }
-    /// assert_eq!(s, [1, 40, 30, 20, 60, 1]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplitn_mut(self, n, pred)
-    }
-
-    /// Returns `true` if the slice contains an element with the given value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.contains(&30));
-    /// assert!(!v.contains(&50));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn contains(&self, x: &T) -> bool
-        where T: PartialEq
-    {
-        core_slice::SliceExt::contains(self, x)
-    }
-
-    /// Returns `true` if `needle` is a prefix of the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.starts_with(&[10]));
-    /// assert!(v.starts_with(&[10, 40]));
-    /// assert!(!v.starts_with(&[50]));
-    /// assert!(!v.starts_with(&[10, 50]));
-    /// ```
-    ///
-    /// Always returns `true` if `needle` is an empty slice:
-    ///
-    /// ```
-    /// let v = &[10, 40, 30];
-    /// assert!(v.starts_with(&[]));
-    /// let v: &[u8] = &[];
-    /// assert!(v.starts_with(&[]));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn starts_with(&self, needle: &[T]) -> bool
-        where T: PartialEq
-    {
-        core_slice::SliceExt::starts_with(self, needle)
-    }
-
-    /// Returns `true` if `needle` is a suffix of the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.ends_with(&[30]));
-    /// assert!(v.ends_with(&[40, 30]));
-    /// assert!(!v.ends_with(&[50]));
-    /// assert!(!v.ends_with(&[50, 30]));
-    /// ```
-    ///
-    /// Always returns `true` if `needle` is an empty slice:
-    ///
-    /// ```
-    /// let v = &[10, 40, 30];
-    /// assert!(v.ends_with(&[]));
-    /// let v: &[u8] = &[];
-    /// assert!(v.ends_with(&[]));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ends_with(&self, needle: &[T]) -> bool
-        where T: PartialEq
-    {
-        core_slice::SliceExt::ends_with(self, needle)
-    }
-
-    /// Binary searches this sorted slice for a given element.
-    ///
-    /// If the value is found then `Ok` is returned, containing the
-    /// index of the matching element; if the value is not found then
-    /// `Err` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Examples
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1, 4]`.
-    ///
-    /// ```
-    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    ///
-    /// assert_eq!(s.binary_search(&13),  Ok(9));
-    /// assert_eq!(s.binary_search(&4),   Err(7));
-    /// assert_eq!(s.binary_search(&100), Err(13));
-    /// let r = s.binary_search(&1);
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn binary_search(&self, x: &T) -> Result<usize, usize>
-        where T: Ord
-    {
-        core_slice::SliceExt::binary_search(self, x)
-    }
-
-    /// Binary searches this sorted slice with a comparator function.
-    ///
-    /// The comparator function should implement an order consistent
-    /// with the sort order of the underlying slice, returning an
-    /// order code that indicates whether its argument is `Less`,
-    /// `Equal` or `Greater` the desired target.
-    ///
-    /// If a matching value is found then returns `Ok`, containing
-    /// the index for the matched element; if no match is found then
-    /// `Err` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Examples
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1, 4]`.
-    ///
-    /// ```
-    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    ///
-    /// let seek = 13;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
-    /// let seek = 4;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
-    /// let seek = 100;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
-    /// let seek = 1;
-    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
-        where F: FnMut(&'a T) -> Ordering
-    {
-        core_slice::SliceExt::binary_search_by(self, f)
-    }
-
-    /// Binary searches this sorted slice with a key extraction function.
-    ///
-    /// Assumes that the slice is sorted by the key, for instance with
-    /// [`sort_by_key`] using the same key extraction function.
-    ///
-    /// If a matching value is found then returns `Ok`, containing the
-    /// index for the matched element; if no match is found then `Err`
-    /// is returned, containing the index where a matching element could
-    /// be inserted while maintaining sorted order.
-    ///
-    /// [`sort_by_key`]: #method.sort_by_key
-    ///
-    /// # Examples
-    ///
-    /// Looks up a series of four elements in a slice of pairs sorted by
-    /// their second elements. The first is found, with a uniquely
-    /// determined position; the second and third are not found; the
-    /// fourth could match any position in `[1, 4]`.
-    ///
-    /// ```
-    /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
-    ///          (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
-    ///          (1, 21), (2, 34), (4, 55)];
-    ///
-    /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
-    /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
-    /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
-    /// let r = s.binary_search_by_key(&1, |&(a,b)| b);
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
-    #[inline]
-    pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
-        where F: FnMut(&'a T) -> B,
-              B: Ord
-    {
-        core_slice::SliceExt::binary_search_by_key(self, b, f)
-    }
+    #[cfg(stage0)]
+    slice_core_methods!();
 
     /// Sorts the slice.
     ///
@@ -1407,351 +355,6 @@ macro_rules! sort_by_key {
         sort_by_key!(usize, self, f)
     }
 
-    /// Sorts the slice, but may not preserve the order of equal elements.
-    ///
-    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
-    /// and `O(n log n)` worst-case.
-    ///
-    /// # Current implementation
-    ///
-    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
-    /// which combines the fast average case of randomized quicksort with the fast worst case of
-    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
-    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
-    /// deterministic behavior.
-    ///
-    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
-    /// slice consists of several concatenated sorted sequences.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [-5, 4, 1, -3, 2];
-    ///
-    /// v.sort_unstable();
-    /// assert!(v == [-5, -3, 1, 2, 4]);
-    /// ```
-    ///
-    /// [pdqsort]: https://github.com/orlp/pdqsort
-    #[stable(feature = "sort_unstable", since = "1.20.0")]
-    #[inline]
-    pub fn sort_unstable(&mut self)
-        where T: Ord
-    {
-        core_slice::SliceExt::sort_unstable(self);
-    }
-
-    /// Sorts the slice with a comparator function, but may not preserve the order of equal
-    /// elements.
-    ///
-    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
-    /// and `O(n log n)` worst-case.
-    ///
-    /// # Current implementation
-    ///
-    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
-    /// which combines the fast average case of randomized quicksort with the fast worst case of
-    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
-    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
-    /// deterministic behavior.
-    ///
-    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
-    /// slice consists of several concatenated sorted sequences.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [5, 4, 1, 3, 2];
-    /// v.sort_unstable_by(|a, b| a.cmp(b));
-    /// assert!(v == [1, 2, 3, 4, 5]);
-    ///
-    /// // reverse sorting
-    /// v.sort_unstable_by(|a, b| b.cmp(a));
-    /// assert!(v == [5, 4, 3, 2, 1]);
-    /// ```
-    ///
-    /// [pdqsort]: https://github.com/orlp/pdqsort
-    #[stable(feature = "sort_unstable", since = "1.20.0")]
-    #[inline]
-    pub fn sort_unstable_by<F>(&mut self, compare: F)
-        where F: FnMut(&T, &T) -> Ordering
-    {
-        core_slice::SliceExt::sort_unstable_by(self, compare);
-    }
-
-    /// Sorts the slice with a key extraction function, but may not preserve the order of equal
-    /// elements.
-    ///
-    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
-    /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`.
-    ///
-    /// # Current implementation
-    ///
-    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
-    /// which combines the fast average case of randomized quicksort with the fast worst case of
-    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
-    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
-    /// deterministic behavior.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [-5i32, 4, 1, -3, 2];
-    ///
-    /// v.sort_unstable_by_key(|k| k.abs());
-    /// assert!(v == [1, 2, -3, 4, -5]);
-    /// ```
-    ///
-    /// [pdqsort]: https://github.com/orlp/pdqsort
-    #[stable(feature = "sort_unstable", since = "1.20.0")]
-    #[inline]
-    pub fn sort_unstable_by_key<K, F>(&mut self, f: F)
-        where F: FnMut(&T) -> K, K: Ord
-    {
-        core_slice::SliceExt::sort_unstable_by_key(self, f);
-    }
-
-    /// Rotates the slice in-place such that the first `mid` elements of the
-    /// slice move to the end while the last `self.len() - mid` elements move to
-    /// the front. After calling `rotate_left`, the element previously at index
-    /// `mid` will become the first element in the slice.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `mid` is greater than the length of the
-    /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
-    /// rotation.
-    ///
-    /// # Complexity
-    ///
-    /// Takes linear (in `self.len()`) time.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a.rotate_left(2);
-    /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
-    /// ```
-    ///
-    /// Rotating a subslice:
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a[1..5].rotate_left(1);
-    /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
-   /// ```
-    #[stable(feature = "slice_rotate", since = "1.26.0")]
-    pub fn rotate_left(&mut self, mid: usize) {
-        core_slice::SliceExt::rotate_left(self, mid);
-    }
-
-    /// Rotates the slice in-place such that the first `self.len() - k`
-    /// elements of the slice move to the end while the last `k` elements move
-    /// to the front. After calling `rotate_right`, the element previously at
-    /// index `self.len() - k` will become the first element in the slice.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `k` is greater than the length of the
-    /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
-    /// rotation.
-    ///
-    /// # Complexity
-    ///
-    /// Takes linear (in `self.len()`) time.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a.rotate_right(2);
-    /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
-    /// ```
-    ///
-    /// Rotate a subslice:
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a[1..5].rotate_right(1);
-    /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
-    /// ```
-    #[stable(feature = "slice_rotate", since = "1.26.0")]
-    pub fn rotate_right(&mut self, k: usize) {
-        core_slice::SliceExt::rotate_right(self, k);
-    }
-
-    /// Copies the elements from `src` into `self`.
-    ///
-    /// The length of `src` must be the same as `self`.
-    ///
-    /// If `src` implements `Copy`, it can be more performant to use
-    /// [`copy_from_slice`].
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Examples
-    ///
-    /// Cloning two elements from a slice into another:
-    ///
-    /// ```
-    /// let src = [1, 2, 3, 4];
-    /// let mut dst = [0, 0];
-    ///
-    /// dst.clone_from_slice(&src[2..]);
-    ///
-    /// assert_eq!(src, [1, 2, 3, 4]);
-    /// assert_eq!(dst, [3, 4]);
-    /// ```
-    ///
-    /// Rust enforces that there can only be one mutable reference with no
-    /// immutable references to a particular piece of data in a particular
-    /// scope. Because of this, attempting to use `clone_from_slice` on a
-    /// single slice will result in a compile failure:
-    ///
-    /// ```compile_fail
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// slice[..2].clone_from_slice(&slice[3..]); // compile fail!
-    /// ```
-    ///
-    /// To work around this, we can use [`split_at_mut`] to create two distinct
-    /// sub-slices from a slice:
-    ///
-    /// ```
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// {
-    ///     let (left, right) = slice.split_at_mut(2);
-    ///     left.clone_from_slice(&right[1..]);
-    /// }
-    ///
-    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
-    /// ```
-    ///
-    /// [`copy_from_slice`]: #method.copy_from_slice
-    /// [`split_at_mut`]: #method.split_at_mut
-    #[stable(feature = "clone_from_slice", since = "1.7.0")]
-    pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
-        core_slice::SliceExt::clone_from_slice(self, src)
-    }
-
-    /// Copies all elements from `src` into `self`, using a memcpy.
-    ///
-    /// The length of `src` must be the same as `self`.
-    ///
-    /// If `src` does not implement `Copy`, use [`clone_from_slice`].
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Examples
-    ///
-    /// Copying two elements from a slice into another:
-    ///
-    /// ```
-    /// let src = [1, 2, 3, 4];
-    /// let mut dst = [0, 0];
-    ///
-    /// dst.copy_from_slice(&src[2..]);
-    ///
-    /// assert_eq!(src, [1, 2, 3, 4]);
-    /// assert_eq!(dst, [3, 4]);
-    /// ```
-    ///
-    /// Rust enforces that there can only be one mutable reference with no
-    /// immutable references to a particular piece of data in a particular
-    /// scope. Because of this, attempting to use `copy_from_slice` on a
-    /// single slice will result in a compile failure:
-    ///
-    /// ```compile_fail
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// slice[..2].copy_from_slice(&slice[3..]); // compile fail!
-    /// ```
-    ///
-    /// To work around this, we can use [`split_at_mut`] to create two distinct
-    /// sub-slices from a slice:
-    ///
-    /// ```
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// {
-    ///     let (left, right) = slice.split_at_mut(2);
-    ///     left.copy_from_slice(&right[1..]);
-    /// }
-    ///
-    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
-    /// ```
-    ///
-    /// [`clone_from_slice`]: #method.clone_from_slice
-    /// [`split_at_mut`]: #method.split_at_mut
-    #[stable(feature = "copy_from_slice", since = "1.9.0")]
-    pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
-        core_slice::SliceExt::copy_from_slice(self, src)
-    }
-
-    /// Swaps all elements in `self` with those in `other`.
-    ///
-    /// The length of `other` must be the same as `self`.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Example
-    ///
-    /// Swapping two elements across slices:
-    ///
-    /// ```
-    /// #![feature(swap_with_slice)]
-    ///
-    /// let mut slice1 = [0, 0];
-    /// let mut slice2 = [1, 2, 3, 4];
-    ///
-    /// slice1.swap_with_slice(&mut slice2[2..]);
-    ///
-    /// assert_eq!(slice1, [3, 4]);
-    /// assert_eq!(slice2, [1, 2, 0, 0]);
-    /// ```
-    ///
-    /// Rust enforces that there can only be one mutable reference to a
-    /// particular piece of data in a particular scope. Because of this,
-    /// attempting to use `swap_with_slice` on a single slice will result in
-    /// a compile failure:
-    ///
-    /// ```compile_fail
-    /// #![feature(swap_with_slice)]
-    ///
-    /// let mut slice = [1, 2, 3, 4, 5];
-    /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail!
-    /// ```
-    ///
-    /// To work around this, we can use [`split_at_mut`] to create two distinct
-    /// mutable sub-slices from a slice:
-    ///
-    /// ```
-    /// #![feature(swap_with_slice)]
-    ///
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// {
-    ///     let (left, right) = slice.split_at_mut(2);
-    ///     left.swap_with_slice(&mut right[1..]);
-    /// }
-    ///
-    /// assert_eq!(slice, [4, 5, 3, 1, 2]);
-    /// ```
-    ///
-    /// [`split_at_mut`]: #method.split_at_mut
-    #[unstable(feature = "swap_with_slice", issue = "44030")]
-    pub fn swap_with_slice(&mut self, other: &mut [T]) {
-        core_slice::SliceExt::swap_with_slice(self, other)
-    }
-
     /// Copies `self` into a new `Vec`.
     ///
     /// # Examples
@@ -1793,16 +396,10 @@ pub fn into_vec(self: Box<Self>) -> Vec<T> {
     }
 }
 
-#[lang = "slice_u8"]
+#[cfg_attr(stage0, lang = "slice_u8")]
+#[cfg_attr(not(stage0), lang = "slice_u8_alloc")]
 #[cfg(not(test))]
 impl [u8] {
-    /// Checks if all bytes in this slice are within the ASCII range.
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn is_ascii(&self) -> bool {
-        self.iter().all(|b| b.is_ascii())
-    }
-
     /// Returns a vector containing a copy of this slice where each byte
     /// is mapped to its ASCII upper case equivalent.
     ///
@@ -1837,52 +434,8 @@ pub fn to_ascii_lowercase(&self) -> Vec<u8> {
         me
     }
 
-    /// Checks that two slices are an ASCII case-insensitive match.
-    ///
-    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-    /// but without allocating and copying temporaries.
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
-        self.len() == other.len() &&
-            self.iter().zip(other).all(|(a, b)| {
-                a.eq_ignore_ascii_case(b)
-            })
-    }
-
-    /// Converts this slice to its ASCII upper case equivalent in-place.
-    ///
-    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new uppercased value without modifying the existing one, use
-    /// [`to_ascii_uppercase`].
-    ///
-    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn make_ascii_uppercase(&mut self) {
-        for byte in self {
-            byte.make_ascii_uppercase();
-        }
-    }
-
-    /// Converts this slice to its ASCII lower case equivalent in-place.
-    ///
-    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new lowercased value without modifying the existing one, use
-    /// [`to_ascii_lowercase`].
-    ///
-    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn make_ascii_lowercase(&mut self) {
-        for byte in self {
-            byte.make_ascii_lowercase();
-        }
-    }
+    #[cfg(stage0)]
+    slice_u8_core_methods!();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index 6c9f3dd7ec975d9d0368d31f864ab079d34bd021..82ba2f4571193e09f9a871bc0fd569e72f7e3715 100644 (file)
@@ -40,6 +40,7 @@
 
 use core::fmt;
 use core::str as core_str;
+#[cfg(stage0)] use core::str::StrExt;
 use core::str::pattern::Pattern;
 use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 use core::mem;
 pub use core::str::SplitWhitespace;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::pattern;
-
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+pub use core::str::EncodeUtf16;
 
 #[unstable(feature = "slice_concat_ext",
            reason = "trait should not have to exist",
            issue = "27747")]
 impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
-    type Output = String;
-
-    fn concat(&self) -> String {
-        if self.is_empty() {
-            return String::new();
-        }
-
-        // `len` calculation may overflow but push_str will check boundaries
-        let len = self.iter().map(|s| s.borrow().len()).sum();
-        let mut result = String::with_capacity(len);
-
-        for s in self {
-            result.push_str(s.borrow())
-        }
-
-        result
-    }
-
-    fn join(&self, sep: &str) -> String {
-        if self.is_empty() {
-            return String::new();
-        }
-
-        // concat is faster
-        if sep.is_empty() {
-            return self.concat();
-        }
-
-        // this is wrong without the guarantee that `self` is non-empty
-        // `len` calculation may overflow but push_str but will check boundaries
-        let len = sep.len() * (self.len() - 1) +
-                  self.iter().map(|s| s.borrow().len()).sum::<usize>();
-        let mut result = String::with_capacity(len);
-        let mut first = true;
-
-        for s in self {
-            if first {
-                first = false;
-            } else {
-                result.push_str(sep);
-            }
-            result.push_str(s.borrow());
-        }
-        result
-    }
-
-    fn connect(&self, sep: &str) -> String {
-        self.join(sep)
-    }
-}
-
-/// An iterator of [`u16`] over the string encoded as UTF-16.
-///
-/// [`u16`]: ../../std/primitive.u16.html
-///
-/// This struct is created by the [`encode_utf16`] method on [`str`].
-/// See its documentation for more.
-///
-/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16
-/// [`str`]: ../../std/primitive.str.html
-#[derive(Clone)]
-#[stable(feature = "encode_utf16", since = "1.8.0")]
-pub struct EncodeUtf16<'a> {
-    chars: Chars<'a>,
-    extra: u16,
-}
-
-#[stable(feature = "collection_debug", since = "1.17.0")]
-impl<'a> fmt::Debug for EncodeUtf16<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("EncodeUtf16 { .. }")
-    }
-}
-
-#[stable(feature = "encode_utf16", since = "1.8.0")]
-impl<'a> Iterator for EncodeUtf16<'a> {
-    type Item = u16;
-
-    #[inline]
-    fn next(&mut self) -> Option<u16> {
-        if self.extra != 0 {
-            let tmp = self.extra;
-            self.extra = 0;
-            return Some(tmp);
-        }
-
-        let mut buf = [0; 2];
-        self.chars.next().map(|ch| {
-            let n = ch.encode_utf16(&mut buf).len();
-            if n == 2 {
-                self.extra = buf[1];
-            }
-            buf[0]
-        })
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (low, high) = self.chars.size_hint();
-        // every char gets either one u16 or two u16,
-        // so this iterator is between 1 or 2 times as
-        // long as the underlying iterator.
-        (low, high.and_then(|n| n.checked_mul(2)))
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<'a> FusedIterator for EncodeUtf16<'a> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Borrow<str> for String {
-    #[inline]
-    fn borrow(&self) -> &str {
-        &self[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl ToOwned for str {
-    type Owned = String;
-    fn to_owned(&self) -> String {
-        unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
-    }
-
-    fn clone_into(&self, target: &mut String) {
-        let mut b = mem::replace(target, String::new()).into_bytes();
-        self.as_bytes().clone_into(&mut b);
-        *target = unsafe { String::from_utf8_unchecked(b) }
-    }
-}
-
-/// Methods for string slices.
-#[lang = "str"]
-#[cfg(not(test))]
-impl str {
-    /// Returns the length of `self`.
-    ///
-    /// This length is in bytes, not [`char`]s or graphemes. In other words,
-    /// it may not be what a human considers the length of the string.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let len = "foo".len();
-    /// assert_eq!(3, len);
-    ///
-    /// let len = "ƒoo".len(); // fancy f!
-    /// assert_eq!(4, len);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn len(&self) -> usize {
-        core_str::StrExt::len(self)
-    }
-
-    /// Returns `true` if `self` has a length of zero bytes.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "";
-    /// assert!(s.is_empty());
-    ///
-    /// let s = "not empty";
-    /// assert!(!s.is_empty());
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool {
-        core_str::StrExt::is_empty(self)
-    }
-
-    /// Checks that `index`-th byte lies at the start and/or end of a
-    /// UTF-8 code point sequence.
-    ///
-    /// The start and end of the string (when `index == self.len()`) are
-    /// considered to be
-    /// boundaries.
-    ///
-    /// Returns `false` if `index` is greater than `self.len()`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// assert!(s.is_char_boundary(0));
-    /// // start of `老`
-    /// assert!(s.is_char_boundary(6));
-    /// assert!(s.is_char_boundary(s.len()));
-    ///
-    /// // second byte of `ö`
-    /// assert!(!s.is_char_boundary(2));
-    ///
-    /// // third byte of `老`
-    /// assert!(!s.is_char_boundary(8));
-    /// ```
-    #[stable(feature = "is_char_boundary", since = "1.9.0")]
-    #[inline]
-    pub fn is_char_boundary(&self, index: usize) -> bool {
-        core_str::StrExt::is_char_boundary(self, index)
-    }
-
-    /// Converts a string slice to a byte slice. To convert the byte slice back
-    /// into a string slice, use the [`str::from_utf8`] function.
-    ///
-    /// [`str::from_utf8`]: ./str/fn.from_utf8.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bytes = "bors".as_bytes();
-    /// assert_eq!(b"bors", bytes);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline(always)]
-    pub fn as_bytes(&self) -> &[u8] {
-        core_str::StrExt::as_bytes(self)
-    }
-
-    /// Converts a mutable string slice to a mutable byte slice. To convert the
-    /// mutable byte slice back into a mutable string slice, use the
-    /// [`str::from_utf8_mut`] function.
-    ///
-    /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = String::from("Hello");
-    /// let bytes = unsafe { s.as_bytes_mut() };
-    ///
-    /// assert_eq!(b"Hello", bytes);
-    /// ```
-    ///
-    /// Mutability:
-    ///
-    /// ```
-    /// let mut s = String::from("🗻∈🌏");
-    ///
-    /// unsafe {
-    ///     let bytes = s.as_bytes_mut();
-    ///
-    ///     bytes[0] = 0xF0;
-    ///     bytes[1] = 0x9F;
-    ///     bytes[2] = 0x8D;
-    ///     bytes[3] = 0x94;
-    /// }
-    ///
-    /// assert_eq!("🍔∈🌏", s);
-    /// ```
-    #[stable(feature = "str_mut_extras", since = "1.20.0")]
-    #[inline(always)]
-    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
-        core_str::StrExt::as_bytes_mut(self)
-    }
-
-    /// Converts a string slice to a raw pointer.
-    ///
-    /// As string slices are a slice of bytes, the raw pointer points to a
-    /// [`u8`]. This pointer will be pointing to the first byte of the string
-    /// slice.
-    ///
-    /// [`u8`]: primitive.u8.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "Hello";
-    /// let ptr = s.as_ptr();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_ptr(&self) -> *const u8 {
-        core_str::StrExt::as_ptr(self)
-    }
-
-    /// Returns a subslice of `str`.
-    ///
-    /// This is the non-panicking alternative to indexing the `str`. Returns
-    /// [`None`] whenever equivalent indexing operation would panic.
-    ///
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = String::from("🗻∈🌏");
-    ///
-    /// assert_eq!(Some("🗻"), v.get(0..4));
-    ///
-    /// // indices not on UTF-8 sequence boundaries
-    /// assert!(v.get(1..).is_none());
-    /// assert!(v.get(..8).is_none());
-    ///
-    /// // out of bounds
-    /// assert!(v.get(..42).is_none());
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
-        core_str::StrExt::get(self, i)
-    }
-
-    /// Returns a mutable subslice of `str`.
-    ///
-    /// This is the non-panicking alternative to indexing the `str`. Returns
-    /// [`None`] whenever equivalent indexing operation would panic.
-    ///
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = String::from("hello");
-    /// // correct length
-    /// assert!(v.get_mut(0..5).is_some());
-    /// // out of bounds
-    /// assert!(v.get_mut(..42).is_none());
-    /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v));
-    ///
-    /// assert_eq!("hello", v);
-    /// {
-    ///     let s = v.get_mut(0..2);
-    ///     let s = s.map(|s| {
-    ///         s.make_ascii_uppercase();
-    ///         &*s
-    ///     });
-    ///     assert_eq!(Some("HE"), s);
-    /// }
-    /// assert_eq!("HEllo", v);
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
-        core_str::StrExt::get_mut(self, i)
-    }
-
-    /// Returns a unchecked subslice of `str`.
-    ///
-    /// This is the unchecked alternative to indexing the `str`.
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that these preconditions are
-    /// satisfied:
-    ///
-    /// * The starting index must come before the ending index;
-    /// * Indexes must be within bounds of the original slice;
-    /// * Indexes must lie on UTF-8 sequence boundaries.
-    ///
-    /// Failing that, the returned string slice may reference invalid memory or
-    /// violate the invariants communicated by the `str` type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = "🗻∈🌏";
-    /// unsafe {
-    ///     assert_eq!("🗻", v.get_unchecked(0..4));
-    ///     assert_eq!("∈", v.get_unchecked(4..7));
-    ///     assert_eq!("🌏", v.get_unchecked(7..11));
-    /// }
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
-        core_str::StrExt::get_unchecked(self, i)
-    }
-
-    /// Returns a mutable, unchecked subslice of `str`.
-    ///
-    /// This is the unchecked alternative to indexing the `str`.
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that these preconditions are
-    /// satisfied:
-    ///
-    /// * The starting index must come before the ending index;
-    /// * Indexes must be within bounds of the original slice;
-    /// * Indexes must lie on UTF-8 sequence boundaries.
-    ///
-    /// Failing that, the returned string slice may reference invalid memory or
-    /// violate the invariants communicated by the `str` type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = String::from("🗻∈🌏");
-    /// unsafe {
-    ///     assert_eq!("🗻", v.get_unchecked_mut(0..4));
-    ///     assert_eq!("∈", v.get_unchecked_mut(4..7));
-    ///     assert_eq!("🌏", v.get_unchecked_mut(7..11));
-    /// }
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
-        core_str::StrExt::get_unchecked_mut(self, i)
-    }
-
-    /// Creates a string slice from another string slice, bypassing safety
-    /// checks.
-    ///
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`str`] and [`Index`].
-    ///
-    /// [`str`]: primitive.str.html
-    /// [`Index`]: ops/trait.Index.html
-    ///
-    /// This new slice goes from `begin` to `end`, including `begin` but
-    /// excluding `end`.
-    ///
-    /// To get a mutable string slice instead, see the
-    /// [`slice_mut_unchecked`] method.
-    ///
-    /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that three preconditions are
-    /// satisfied:
-    ///
-    /// * `begin` must come before `end`.
-    /// * `begin` and `end` must be byte positions within the string slice.
-    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// unsafe {
-    ///     assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21));
-    /// }
-    ///
-    /// let s = "Hello, world!";
-    ///
-    /// unsafe {
-    ///     assert_eq!("world", s.slice_unchecked(7, 12));
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
-        core_str::StrExt::slice_unchecked(self, begin, end)
-    }
-
-    /// Creates a string slice from another string slice, bypassing safety
-    /// checks.
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`str`] and [`IndexMut`].
-    ///
-    /// [`str`]: primitive.str.html
-    /// [`IndexMut`]: ops/trait.IndexMut.html
-    ///
-    /// This new slice goes from `begin` to `end`, including `begin` but
-    /// excluding `end`.
-    ///
-    /// To get an immutable string slice instead, see the
-    /// [`slice_unchecked`] method.
-    ///
-    /// [`slice_unchecked`]: #method.slice_unchecked
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that three preconditions are
-    /// satisfied:
-    ///
-    /// * `begin` must come before `end`.
-    /// * `begin` and `end` must be byte positions within the string slice.
-    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
-    #[stable(feature = "str_slice_mut", since = "1.5.0")]
-    #[inline]
-    pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
-        core_str::StrExt::slice_mut_unchecked(self, begin, end)
-    }
-
-    /// Divide one string slice into two at an index.
-    ///
-    /// The argument, `mid`, should be a byte offset from the start of the
-    /// string. It must also be on the boundary of a UTF-8 code point.
-    ///
-    /// The two slices returned go from the start of the string slice to `mid`,
-    /// and from `mid` to the end of the string slice.
-    ///
-    /// To get mutable string slices instead, see the [`split_at_mut`]
-    /// method.
-    ///
-    /// [`split_at_mut`]: #method.split_at_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "Per Martin-Löf";
-    ///
-    /// let (first, last) = s.split_at(3);
-    ///
-    /// assert_eq!("Per", first);
-    /// assert_eq!(" Martin-Löf", last);
-    /// ```
-    #[inline]
-    #[stable(feature = "str_split_at", since = "1.4.0")]
-    pub fn split_at(&self, mid: usize) -> (&str, &str) {
-        core_str::StrExt::split_at(self, mid)
-    }
-
-    /// Divide one mutable string slice into two at an index.
-    ///
-    /// The argument, `mid`, should be a byte offset from the start of the
-    /// string. It must also be on the boundary of a UTF-8 code point.
-    ///
-    /// The two slices returned go from the start of the string slice to `mid`,
-    /// and from `mid` to the end of the string slice.
-    ///
-    /// To get immutable string slices instead, see the [`split_at`] method.
-    ///
-    /// [`split_at`]: #method.split_at
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = "Per Martin-Löf".to_string();
-    /// {
-    ///     let (first, last) = s.split_at_mut(3);
-    ///     first.make_ascii_uppercase();
-    ///     assert_eq!("PER", first);
-    ///     assert_eq!(" Martin-Löf", last);
-    /// }
-    /// assert_eq!("PER Martin-Löf", s);
-    /// ```
-    #[inline]
-    #[stable(feature = "str_split_at", since = "1.4.0")]
-    pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
-        core_str::StrExt::split_at_mut(self, mid)
-    }
-
-    /// Returns an iterator over the [`char`]s of a string slice.
-    ///
-    /// As a string slice consists of valid UTF-8, we can iterate through a
-    /// string slice by [`char`]. This method returns such an iterator.
-    ///
-    /// It's important to remember that [`char`] represents a Unicode Scalar
-    /// Value, and may not match your idea of what a 'character' is. Iteration
-    /// over grapheme clusters may be what you actually want.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let word = "goodbye";
-    ///
-    /// let count = word.chars().count();
-    /// assert_eq!(7, count);
-    ///
-    /// let mut chars = word.chars();
-    ///
-    /// assert_eq!(Some('g'), chars.next());
-    /// assert_eq!(Some('o'), chars.next());
-    /// assert_eq!(Some('o'), chars.next());
-    /// assert_eq!(Some('d'), chars.next());
-    /// assert_eq!(Some('b'), chars.next());
-    /// assert_eq!(Some('y'), chars.next());
-    /// assert_eq!(Some('e'), chars.next());
-    ///
-    /// assert_eq!(None, chars.next());
-    /// ```
-    ///
-    /// Remember, [`char`]s may not match your human intuition about characters:
-    ///
-    /// ```
-    /// let y = "y̆";
-    ///
-    /// let mut chars = y.chars();
-    ///
-    /// assert_eq!(Some('y'), chars.next()); // not 'y̆'
-    /// assert_eq!(Some('\u{0306}'), chars.next());
-    ///
-    /// assert_eq!(None, chars.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn chars(&self) -> Chars {
-        core_str::StrExt::chars(self)
-    }
-    /// Returns an iterator over the [`char`]s of a string slice, and their
-    /// positions.
-    ///
-    /// As a string slice consists of valid UTF-8, we can iterate through a
-    /// string slice by [`char`]. This method returns an iterator of both
-    /// these [`char`]s, as well as their byte positions.
-    ///
-    /// The iterator yields tuples. The position is first, the [`char`] is
-    /// second.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let word = "goodbye";
-    ///
-    /// let count = word.char_indices().count();
-    /// assert_eq!(7, count);
-    ///
-    /// let mut char_indices = word.char_indices();
-    ///
-    /// assert_eq!(Some((0, 'g')), char_indices.next());
-    /// assert_eq!(Some((1, 'o')), char_indices.next());
-    /// assert_eq!(Some((2, 'o')), char_indices.next());
-    /// assert_eq!(Some((3, 'd')), char_indices.next());
-    /// assert_eq!(Some((4, 'b')), char_indices.next());
-    /// assert_eq!(Some((5, 'y')), char_indices.next());
-    /// assert_eq!(Some((6, 'e')), char_indices.next());
-    ///
-    /// assert_eq!(None, char_indices.next());
-    /// ```
-    ///
-    /// Remember, [`char`]s may not match your human intuition about characters:
-    ///
-    /// ```
-    /// let yes = "y̆es";
-    ///
-    /// let mut char_indices = yes.char_indices();
-    ///
-    /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
-    /// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
-    ///
-    /// // note the 3 here - the last character took up two bytes
-    /// assert_eq!(Some((3, 'e')), char_indices.next());
-    /// assert_eq!(Some((4, 's')), char_indices.next());
-    ///
-    /// assert_eq!(None, char_indices.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn char_indices(&self) -> CharIndices {
-        core_str::StrExt::char_indices(self)
-    }
-
-    /// An iterator over the bytes of a string slice.
-    ///
-    /// As a string slice consists of a sequence of bytes, we can iterate
-    /// through a string slice by byte. This method returns such an iterator.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut bytes = "bors".bytes();
-    ///
-    /// assert_eq!(Some(b'b'), bytes.next());
-    /// assert_eq!(Some(b'o'), bytes.next());
-    /// assert_eq!(Some(b'r'), bytes.next());
-    /// assert_eq!(Some(b's'), bytes.next());
-    ///
-    /// assert_eq!(None, bytes.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn bytes(&self) -> Bytes {
-        core_str::StrExt::bytes(self)
-    }
-
-    /// Split a string slice by whitespace.
-    ///
-    /// The iterator returned will return string slices that are sub-slices of
-    /// the original string slice, separated by any amount of whitespace.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut iter = "A few words".split_whitespace();
-    ///
-    /// assert_eq!(Some("A"), iter.next());
-    /// assert_eq!(Some("few"), iter.next());
-    /// assert_eq!(Some("words"), iter.next());
-    ///
-    /// assert_eq!(None, iter.next());
-    /// ```
-    ///
-    /// All kinds of whitespace are considered:
-    ///
-    /// ```
-    /// let mut iter = " Mary   had\ta\u{2009}little  \n\t lamb".split_whitespace();
-    /// assert_eq!(Some("Mary"), iter.next());
-    /// assert_eq!(Some("had"), iter.next());
-    /// assert_eq!(Some("a"), iter.next());
-    /// assert_eq!(Some("little"), iter.next());
-    /// assert_eq!(Some("lamb"), iter.next());
-    ///
-    /// assert_eq!(None, iter.next());
-    /// ```
-    #[stable(feature = "split_whitespace", since = "1.1.0")]
-    #[inline]
-    pub fn split_whitespace(&self) -> SplitWhitespace {
-        StrExt::split_whitespace(self)
-    }
-
-    /// An iterator over the lines of a string, as string slices.
-    ///
-    /// Lines are ended with either a newline (`\n`) or a carriage return with
-    /// a line feed (`\r\n`).
-    ///
-    /// The final line ending is optional.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let text = "foo\r\nbar\n\nbaz\n";
-    /// let mut lines = text.lines();
-    ///
-    /// assert_eq!(Some("foo"), lines.next());
-    /// assert_eq!(Some("bar"), lines.next());
-    /// assert_eq!(Some(""), lines.next());
-    /// assert_eq!(Some("baz"), lines.next());
-    ///
-    /// assert_eq!(None, lines.next());
-    /// ```
-    ///
-    /// The final line ending isn't required:
-    ///
-    /// ```
-    /// let text = "foo\nbar\n\r\nbaz";
-    /// let mut lines = text.lines();
-    ///
-    /// assert_eq!(Some("foo"), lines.next());
-    /// assert_eq!(Some("bar"), lines.next());
-    /// assert_eq!(Some(""), lines.next());
-    /// assert_eq!(Some("baz"), lines.next());
-    ///
-    /// assert_eq!(None, lines.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn lines(&self) -> Lines {
-        core_str::StrExt::lines(self)
-    }
-
-    /// An iterator over the lines of a string.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")]
-    #[inline]
-    #[allow(deprecated)]
-    pub fn lines_any(&self) -> LinesAny {
-        core_str::StrExt::lines_any(self)
-    }
-
-    /// Returns an iterator of `u16` over the string encoded as UTF-16.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let text = "Zażółć gęślą jaźń";
-    ///
-    /// let utf8_len = text.len();
-    /// let utf16_len = text.encode_utf16().count();
-    ///
-    /// assert!(utf16_len <= utf8_len);
-    /// ```
-    #[stable(feature = "encode_utf16", since = "1.8.0")]
-    pub fn encode_utf16(&self) -> EncodeUtf16 {
-        EncodeUtf16 { chars: self[..].chars(), extra: 0 }
-    }
-
-    /// Returns `true` if the given pattern matches a sub-slice of
-    /// this string slice.
-    ///
-    /// Returns `false` if it does not.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bananas = "bananas";
-    ///
-    /// assert!(bananas.contains("nana"));
-    /// assert!(!bananas.contains("apples"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::contains(self, pat)
-    }
-
-    /// Returns `true` if the given pattern matches a prefix of this
-    /// string slice.
-    ///
-    /// Returns `false` if it does not.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bananas = "bananas";
-    ///
-    /// assert!(bananas.starts_with("bana"));
-    /// assert!(!bananas.starts_with("nana"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::starts_with(self, pat)
-    }
-
-    /// Returns `true` if the given pattern matches a suffix of this
-    /// string slice.
-    ///
-    /// Returns `false` if it does not.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bananas = "bananas";
-    ///
-    /// assert!(bananas.ends_with("anas"));
-    /// assert!(!bananas.ends_with("nana"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::ends_with(self, pat)
-    }
-
-    /// Returns the byte index of the first character of this string slice that
-    /// matches the pattern.
-    ///
-    /// Returns [`None`] if the pattern doesn't match.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.find('L'), Some(0));
-    /// assert_eq!(s.find('é'), Some(14));
-    /// assert_eq!(s.find("Léopard"), Some(13));
-    /// ```
-    ///
-    /// More complex patterns using point-free style and closures:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.find(char::is_whitespace), Some(5));
-    /// assert_eq!(s.find(char::is_lowercase), Some(1));
-    /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1));
-    /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4));
-    /// ```
-    ///
-    /// Not finding the pattern:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// let x: &[_] = &['1', '2'];
-    ///
-    /// assert_eq!(s.find(x), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
-        core_str::StrExt::find(self, pat)
-    }
-
-    /// Returns the byte index of the last character of this string slice that
-    /// matches the pattern.
-    ///
-    /// Returns [`None`] if the pattern doesn't match.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.rfind('L'), Some(13));
-    /// assert_eq!(s.rfind('é'), Some(14));
-    /// ```
-    ///
-    /// More complex patterns with closures:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.rfind(char::is_whitespace), Some(12));
-    /// assert_eq!(s.rfind(char::is_lowercase), Some(20));
-    /// ```
-    ///
-    /// Not finding the pattern:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// let x: &[_] = &['1', '2'];
-    ///
-    /// assert_eq!(s.rfind(x), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rfind(self, pat)
-    }
-
-    /// An iterator over substrings of this string slice, separated by
-    /// characters matched by a pattern.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rsplit`] method can be used.
-    ///
-    /// [`char`]: primitive.char.html
-    /// [`rsplit`]: #method.rsplit
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
-    ///
-    /// let v: Vec<&str> = "".split('X').collect();
-    /// assert_eq!(v, [""]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
-    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
-    ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
-    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
-    ///
-    /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
-    /// assert_eq!(v, ["abc", "def", "ghi"]);
-    ///
-    /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
-    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["abc", "def", "ghi"]);
-    /// ```
-    ///
-    /// If a string contains multiple contiguous separators, you will end up
-    /// with empty strings in the output:
-    ///
-    /// ```
-    /// let x = "||||a||b|c".to_string();
-    /// let d: Vec<_> = x.split('|').collect();
-    ///
-    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
-    /// ```
-    ///
-    /// Contiguous separators are separated by the empty string.
-    ///
-    /// ```
-    /// let x = "(///)".to_string();
-    /// let d: Vec<_> = x.split('/').collect();
-    ///
-    /// assert_eq!(d, &["(", "", "", ")"]);
-    /// ```
-    ///
-    /// Separators at the start or end of a string are neighbored
-    /// by empty strings.
-    ///
-    /// ```
-    /// let d: Vec<_> = "010".split("0").collect();
-    /// assert_eq!(d, &["", "1", ""]);
-    /// ```
-    ///
-    /// When the empty string is used as a separator, it separates
-    /// every character in the string, along with the beginning
-    /// and end of the string.
-    ///
-    /// ```
-    /// let f: Vec<_> = "rust".split("").collect();
-    /// assert_eq!(f, &["", "r", "u", "s", "t", ""]);
-    /// ```
-    ///
-    /// Contiguous separators can lead to possibly surprising behavior
-    /// when whitespace is used as the separator. This code is correct:
-    ///
-    /// ```
-    /// let x = "    a  b c".to_string();
-    /// let d: Vec<_> = x.split(' ').collect();
-    ///
-    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
-    /// ```
-    ///
-    /// It does _not_ give you:
-    ///
-    /// ```,ignore
-    /// assert_eq!(d, &["a", "b", "c"]);
-    /// ```
-    ///
-    /// Use [`split_whitespace`] for this behavior.
-    ///
-    /// [`split_whitespace`]: #method.split_whitespace
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
-        core_str::StrExt::split(self, pat)
-    }
-
-    /// An iterator over substrings of the given string slice, separated by
-    /// characters matched by a pattern and yielded in reverse order.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// For iterating from the front, the [`split`] method can be used.
-    ///
-    /// [`split`]: #method.split
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
-    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
-    ///
-    /// let v: Vec<&str> = "".rsplit('X').collect();
-    /// assert_eq!(v, [""]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "", "lion"]);
-    ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["ghi", "def", "abc"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplit(self, pat)
-    }
-
-    /// An iterator over substrings of the given string slice, separated by
-    /// characters matched by a pattern.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// Equivalent to [`split`], except that the trailing substring
-    /// is skipped if empty.
-    ///
-    /// [`split`]: #method.split
-    ///
-    /// This method can be used for string data that is _terminated_,
-    /// rather than _separated_ by a pattern.
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    /// [`char`]: primitive.char.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rsplit_terminator`] method can be used.
-    ///
-    /// [`rsplit_terminator`]: #method.rsplit_terminator
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
-    /// assert_eq!(v, ["A", "B"]);
-    ///
-    /// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
-    /// assert_eq!(v, ["A", "", "B", ""]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
-        core_str::StrExt::split_terminator(self, pat)
-    }
-
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by a pattern and yielded in reverse order.
-    ///
-    /// The pattern can be a simple `&str`, [`char`], or a closure that
-    /// determines the split.
-    /// Additional libraries might provide more complex patterns like
-    /// regular expressions.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// Equivalent to [`split`], except that the trailing substring is
-    /// skipped if empty.
-    ///
-    /// [`split`]: #method.split
-    ///
-    /// This method can be used for string data that is _terminated_,
-    /// rather than _separated_ by a pattern.
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a
-    /// reverse search, and it will be double ended if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// For iterating from the front, the [`split_terminator`] method can be
-    /// used.
-    ///
-    /// [`split_terminator`]: #method.split_terminator
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
-    /// assert_eq!(v, ["B", "A"]);
-    ///
-    /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
-    /// assert_eq!(v, ["", "B", "", "A"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplit_terminator(self, pat)
-    }
-
-    /// An iterator over substrings of the given string slice, separated by a
-    /// pattern, restricted to returning at most `n` items.
-    ///
-    /// If `n` substrings are returned, the last substring (the `n`th substring)
-    /// will contain the remainder of the string.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will not be double ended, because it is
-    /// not efficient to support.
-    ///
-    /// If the pattern allows a reverse search, the [`rsplitn`] method can be
-    /// used.
-    ///
-    /// [`rsplitn`]: #method.rsplitn
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
-    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
-    ///
-    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
-    /// assert_eq!(v, ["abcXdef"]);
-    ///
-    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
-    /// assert_eq!(v, [""]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["abc", "defXghi"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
-        core_str::StrExt::splitn(self, n, pat)
-    }
-
-    /// An iterator over substrings of this string slice, separated by a
-    /// pattern, starting from the end of the string, restricted to returning
-    /// at most `n` items.
-    ///
-    /// If `n` substrings are returned, the last substring (the `n`th substring)
-    /// will contain the remainder of the string.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that
-    /// determines the split.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will not be double ended, because it is not
-    /// efficient to support.
-    ///
-    /// For splitting from the front, the [`splitn`] method can be used.
-    ///
-    /// [`splitn`]: #method.splitn
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
-    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
-    ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
-    /// assert_eq!(v, ["leopard", "lion::tiger"]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["ghi", "abc1def"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplitn(self, n, pat)
-    }
-
-    /// An iterator over the disjoint matches of a pattern within the given string
-    /// slice.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that
-    /// determines if a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    /// [`char`]: primitive.char.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rmatches`] method can be used.
-    ///
-    /// [`rmatches`]: #method.rmatches
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
-    /// assert_eq!(v, ["abc", "abc", "abc"]);
-    ///
-    /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
-    /// assert_eq!(v, ["1", "2", "3"]);
-    /// ```
-    #[stable(feature = "str_matches", since = "1.2.0")]
-    #[inline]
-    pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
-        core_str::StrExt::matches(self, pat)
-    }
-
-    /// An iterator over the disjoint matches of a pattern within this string slice,
-    /// yielded in reverse order.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// For iterating from the front, the [`matches`] method can be used.
-    ///
-    /// [`matches`]: #method.matches
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
-    /// assert_eq!(v, ["abc", "abc", "abc"]);
-    ///
-    /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
-    /// assert_eq!(v, ["3", "2", "1"]);
-    /// ```
-    #[stable(feature = "str_matches", since = "1.2.0")]
-    #[inline]
-    pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rmatches(self, pat)
-    }
-
-    /// An iterator over the disjoint matches of a pattern within this string
-    /// slice as well as the index that the match starts at.
-    ///
-    /// For matches of `pat` within `self` that overlap, only the indices
-    /// corresponding to the first match are returned.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines
-    /// if a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rmatch_indices`] method can be used.
-    ///
-    /// [`rmatch_indices`]: #method.rmatch_indices
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
-    /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
-    ///
-    /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
-    /// assert_eq!(v, [(1, "abc"), (4, "abc")]);
-    ///
-    /// let v: Vec<_> = "ababa".match_indices("aba").collect();
-    /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
-    /// ```
-    #[stable(feature = "str_match_indices", since = "1.5.0")]
-    #[inline]
-    pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
-        core_str::StrExt::match_indices(self, pat)
-    }
+    type Output = String;
 
-    /// An iterator over the disjoint matches of a pattern within `self`,
-    /// yielded in reverse order along with the index of the match.
-    ///
-    /// For matches of `pat` within `self` that overlap, only the indices
-    /// corresponding to the last match are returned.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if a
-    /// character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// For iterating from the front, the [`match_indices`] method can be used.
-    ///
-    /// [`match_indices`]: #method.match_indices
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
-    ///
-    /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(4, "abc"), (1, "abc")]);
-    ///
-    /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
-    /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
-    /// ```
-    #[stable(feature = "str_match_indices", since = "1.5.0")]
-    #[inline]
-    pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rmatch_indices(self, pat)
-    }
+    fn concat(&self) -> String {
+        if self.is_empty() {
+            return String::new();
+        }
 
-    /// Returns a string slice with leading and trailing whitespace removed.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = " Hello\tworld\t";
-    ///
-    /// assert_eq!("Hello\tworld", s.trim());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim(&self) -> &str {
-        StrExt::trim(self)
-    }
+        // `len` calculation may overflow but push_str will check boundaries
+        let len = self.iter().map(|s| s.borrow().len()).sum();
+        let mut result = String::with_capacity(len);
 
-    /// Returns a string slice with leading whitespace removed.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = " Hello\tworld\t";
-    ///
-    /// assert_eq!("Hello\tworld\t", s.trim_left());
-    /// ```
-    ///
-    /// Directionality:
-    ///
-    /// ```
-    /// let s = "  English";
-    /// assert!(Some('E') == s.trim_left().chars().next());
-    ///
-    /// let s = "  עברית";
-    /// assert!(Some('ע') == s.trim_left().chars().next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left(&self) -> &str {
-        StrExt::trim_left(self)
+        for s in self {
+            result.push_str(s.borrow())
+        }
+
+        result
     }
 
-    /// Returns a string slice with trailing whitespace removed.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = " Hello\tworld\t";
-    ///
-    /// assert_eq!(" Hello\tworld", s.trim_right());
-    /// ```
-    ///
-    /// Directionality:
-    ///
-    /// ```
-    /// let s = "English  ";
-    /// assert!(Some('h') == s.trim_right().chars().rev().next());
-    ///
-    /// let s = "עברית  ";
-    /// assert!(Some('ת') == s.trim_right().chars().rev().next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right(&self) -> &str {
-        StrExt::trim_right(self)
+    fn join(&self, sep: &str) -> String {
+        if self.is_empty() {
+            return String::new();
+        }
+
+        // concat is faster
+        if sep.is_empty() {
+            return self.concat();
+        }
+
+        // this is wrong without the guarantee that `self` is non-empty
+        // `len` calculation may overflow but push_str but will check boundaries
+        let len = sep.len() * (self.len() - 1) +
+                  self.iter().map(|s| s.borrow().len()).sum::<usize>();
+        let mut result = String::with_capacity(len);
+        let mut first = true;
+
+        for s in self {
+            if first {
+                first = false;
+            } else {
+                result.push_str(sep);
+            }
+            result.push_str(s.borrow());
+        }
+        result
     }
 
-    /// Returns a string slice with all prefixes and suffixes that match a
-    /// pattern repeatedly removed.
-    ///
-    /// The pattern can be a [`char`] or a closure that determines if a
-    /// character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
-    /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar");
-    ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
-        where P::Searcher: DoubleEndedSearcher<'a>
-    {
-        core_str::StrExt::trim_matches(self, pat)
+    fn connect(&self, sep: &str) -> String {
+        self.join(sep)
     }
+}
 
-    /// Returns a string slice with all prefixes that match a pattern
-    /// repeatedly removed.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
-    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
-    ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
-        core_str::StrExt::trim_left_matches(self, pat)
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Borrow<str> for String {
+    #[inline]
+    fn borrow(&self) -> &str {
+        &self[..]
     }
+}
 
-    /// Returns a string slice with all suffixes that match a pattern
-    /// repeatedly removed.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that
-    /// determines if a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
-    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
-    ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::trim_right_matches(self, pat)
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToOwned for str {
+    type Owned = String;
+    fn to_owned(&self) -> String {
+        unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
     }
 
-    /// Parses this string slice into another type.
-    ///
-    /// Because `parse` is so general, it can cause problems with type
-    /// inference. As such, `parse` is one of the few times you'll see
-    /// the syntax affectionately known as the 'turbofish': `::<>`. This
-    /// helps the inference algorithm understand specifically which type
-    /// you're trying to parse into.
-    ///
-    /// `parse` can parse any type that implements the [`FromStr`] trait.
-    ///
-    /// [`FromStr`]: str/trait.FromStr.html
-    ///
-    /// # Errors
-    ///
-    /// Will return [`Err`] if it's not possible to parse this string slice into
-    /// the desired type.
-    ///
-    /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
-    ///
-    /// # Examples
-    ///
-    /// Basic usage
-    ///
-    /// ```
-    /// let four: u32 = "4".parse().unwrap();
-    ///
-    /// assert_eq!(4, four);
-    /// ```
-    ///
-    /// Using the 'turbofish' instead of annotating `four`:
-    ///
-    /// ```
-    /// let four = "4".parse::<u32>();
-    ///
-    /// assert_eq!(Ok(4), four);
-    /// ```
-    ///
-    /// Failing to parse:
-    ///
-    /// ```
-    /// let nope = "j".parse::<u32>();
-    ///
-    /// assert!(nope.is_err());
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
-        core_str::StrExt::parse(self)
+    fn clone_into(&self, target: &mut String) {
+        let mut b = mem::replace(target, String::new()).into_bytes();
+        self.as_bytes().clone_into(&mut b);
+        *target = unsafe { String::from_utf8_unchecked(b) }
     }
+}
+
+/// Methods for string slices.
+#[cfg_attr(stage0, lang = "str")]
+#[cfg_attr(not(stage0), lang = "str_alloc")]
+#[cfg(not(test))]
+impl str {
+    #[cfg(stage0)]
+    str_core_methods!();
 
     /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
     ///
@@ -1827,6 +178,7 @@ pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
     /// assert_eq!(*boxed_bytes, *s.as_bytes());
     /// ```
     #[stable(feature = "str_box_extras", since = "1.20.0")]
+    #[inline]
     pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
         self.into()
     }
@@ -2065,6 +417,7 @@ pub fn escape_unicode(&self) -> String {
     /// assert_eq!(boxed_str.into_string(), string);
     /// ```
     #[stable(feature = "box_str", since = "1.4.0")]
+    #[inline]
     pub fn into_string(self: Box<str>) -> String {
         let slice = Box::<[u8]>::from(self);
         unsafe { String::from_utf8_unchecked(slice.into_vec()) }
@@ -2138,68 +491,6 @@ pub fn repeat(&self, n: usize) -> String {
         unsafe { String::from_utf8_unchecked(buf) }
     }
 
-    /// Returns true if this `str` is entirely whitespace, and false otherwise.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived Core
-    /// Property `White_Space`.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// assert!("    \t ".is_whitespace());
-    ///
-    /// // a non-breaking space
-    /// assert!("\u{A0}".is_whitespace());
-    ///
-    /// assert!(!"   越".is_whitespace());
-    /// ```
-    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
-    #[inline]
-    pub fn is_whitespace(&self) -> bool {
-        StrExt::is_whitespace(self)
-    }
-
-    /// Returns true if this `str` is entirely alphanumeric, and false otherwise.
-    ///
-    /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories
-    /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// assert!("٣7৬Kو藏".is_alphanumeric());
-    /// assert!(!"¾①".is_alphanumeric());
-    /// ```
-    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
-    #[inline]
-    pub fn is_alphanumeric(&self) -> bool {
-        StrExt::is_alphanumeric(self)
-    }
-
-    /// Checks if all characters in this string are within the ASCII range.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let ascii = "hello!\n";
-    /// let non_ascii = "Grüße, Jürgen ❤";
-    ///
-    /// assert!(ascii.is_ascii());
-    /// assert!(!non_ascii.is_ascii());
-    /// ```
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn is_ascii(&self) -> bool {
-        // We can treat each byte as character here: all multibyte characters
-        // start with a byte that is not in the ascii range, so we will stop
-        // there already.
-        self.bytes().all(|b| b.is_ascii())
-    }
-
     /// Returns a copy of this string where each character is mapped to its
     /// ASCII upper case equivalent.
     ///
@@ -2259,54 +550,6 @@ pub fn to_ascii_lowercase(&self) -> String {
         // make_ascii_lowercase() preserves the UTF-8 invariant.
         unsafe { String::from_utf8_unchecked(bytes) }
     }
-
-    /// Checks that two strings are an ASCII case-insensitive match.
-    ///
-    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-    /// but without allocating and copying temporaries.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
-    /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS"));
-    /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
-    /// ```
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
-        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
-    }
-
-    /// Converts this string to its ASCII upper case equivalent in-place.
-    ///
-    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new uppercased value without modifying the existing one, use
-    /// [`to_ascii_uppercase`].
-    ///
-    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    pub fn make_ascii_uppercase(&mut self) {
-        let me = unsafe { self.as_bytes_mut() };
-        me.make_ascii_uppercase()
-    }
-
-    /// Converts this string to its ASCII lower case equivalent in-place.
-    ///
-    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new lowercased value without modifying the existing one, use
-    /// [`to_ascii_lowercase`].
-    ///
-    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    pub fn make_ascii_lowercase(&mut self) {
-        let me = unsafe { self.as_bytes_mut() };
-        me.make_ascii_lowercase()
-    }
 }
 
 /// Converts a boxed slice of bytes to a boxed string slice without checking
@@ -2323,6 +566,7 @@ pub fn make_ascii_lowercase(&mut self) {
 /// assert_eq!("☺", &*smile);
 /// ```
 #[stable(feature = "str_box_extras", since = "1.20.0")]
+#[inline]
 pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
     Box::from_raw(Box::into_raw(v) as *mut str)
 }
index 0924ca2479147f4f581f0f94eaa28a74b5237903..2f84d5f7f8676877328dc57aa79155374886f6e6 100644 (file)
@@ -1521,9 +1521,6 @@ pub fn drain<R>(&mut self, range: R) -> Drain
     /// and replaces it with the given string.
     /// The given string doesn't need to be the same length as the range.
     ///
-    /// Note: Unlike [`Vec::splice`], the replacement happens eagerly, and this
-    /// method does not return the removed chars.
-    ///
     /// # Panics
     ///
     /// Panics if the starting point or end point do not lie on a [`char`]
@@ -1586,6 +1583,7 @@ pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
     /// let b = s.into_boxed_str();
     /// ```
     #[stable(feature = "box_str", since = "1.4.0")]
+    #[inline]
     pub fn into_boxed_str(self) -> Box<str> {
         let slice = self.vec.into_boxed_slice();
         unsafe { from_boxed_utf8_unchecked(slice) }
index a3f4c385fe23b731b52f329312790a1ba494253b..a03b61ec97e51c71210cc43ef10487266f3ca2e0 100644 (file)
@@ -401,6 +401,36 @@ fn test_str_get_maxinclusive() {
     }
 }
 
+#[test]
+fn test_str_slice_rangetoinclusive_ok() {
+    let s = "abcαβγ";
+    assert_eq!(&s[..=2], "abc");
+    assert_eq!(&s[..=4], "abcα");
+}
+
+#[test]
+#[should_panic]
+fn test_str_slice_rangetoinclusive_notok() {
+    let s = "abcαβγ";
+    &s[..=3];
+}
+
+#[test]
+fn test_str_slicemut_rangetoinclusive_ok() {
+    let mut s = "abcαβγ".to_owned();
+    let s: &mut str = &mut s;
+    assert_eq!(&mut s[..=2], "abc");
+    assert_eq!(&mut s[..=4], "abcα");
+}
+
+#[test]
+#[should_panic]
+fn test_str_slicemut_rangetoinclusive_notok() {
+    let mut s = "abcαβγ".to_owned();
+    let s: &mut str = &mut s;
+    &mut s[..=3];
+}
+
 #[test]
 fn test_is_char_boundary() {
     let s = "ศไทย中华Việt Nam β-release 🐱123";
index 9ae415c328bd2cc12bdef7a8ad890900be7d6a38..b184404c15bfd6c050b99252db3c15e41b2d00a2 100644 (file)
@@ -74,6 +74,7 @@
 use core::marker::PhantomData;
 use core::mem;
 #[cfg(not(test))]
+#[cfg(stage0)]
 use core::num::Float;
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{Index, IndexMut, RangeBounds};
@@ -583,7 +584,9 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionA
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
-        self.buf.shrink_to_fit(self.len);
+        if self.capacity() != self.len {
+            self.buf.shrink_to_fit(self.len);
+        }
     }
 
     /// Shrinks the capacity of the vector with a lower bound.
@@ -2521,7 +2524,7 @@ fn next_back(&mut self) -> Option<T> {
 impl<'a, T> Drop for Drain<'a, T> {
     fn drop(&mut self) {
         // exhaust self first
-        while let Some(_) = self.next() {}
+        self.for_each(drop);
 
         if self.tail_len > 0 {
             unsafe {
@@ -2590,9 +2593,7 @@ impl<'a, I: Iterator> ExactSizeIterator for Splice<'a, I> {}
 #[stable(feature = "vec_splice", since = "1.21.0")]
 impl<'a, I: Iterator> Drop for Splice<'a, I> {
     fn drop(&mut self) {
-        // exhaust drain first
-        while let Some(_) = self.drain.next() {}
-
+        self.drain.by_ref().for_each(drop);
 
         unsafe {
             if self.drain.tail_len == 0 {
@@ -2721,8 +2722,7 @@ impl<'a, T, F> Drop for DrainFilter<'a, T, F>
     where F: FnMut(&mut T) -> bool,
 {
     fn drop(&mut self) {
-        for _ in self.by_ref() { }
-
+        self.for_each(drop);
         unsafe {
             self.vec.set_len(self.old_len - self.del);
         }
index 603e38ca2ca33d16bffd674c50163910d2091718..ff82b3a469caf1afae27c39246fc7aaf3b2b4088 100644 (file)
@@ -2250,7 +2250,7 @@ unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
 #[stable(feature = "drain", since = "1.6.0")]
 impl<'a, T: 'a> Drop for Drain<'a, T> {
     fn drop(&mut self) {
-        for _ in self.by_ref() {}
+        self.for_each(drop);
 
         let source_deque = unsafe { self.deque.as_mut() };
 
index 02435170374c503c81b7111974ebfc0266e2d3a1..7986d5dd2eb54b69a12990dc83891ba320a7e838 100644 (file)
@@ -12,7 +12,6 @@ test = false
 doc = false
 
 [dependencies]
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 2b66c293f21a025b16075103a640fa36c61b7d29..4b8755877de4bf7e044d8047054f076e0e4d3984 100644 (file)
@@ -14,7 +14,7 @@
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
             issue = "27783")]
-#![feature(alloc_system)]
+#![feature(core_intrinsics)]
 #![feature(libc)]
 #![feature(linkage)]
 #![feature(staged_api)]
 #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
 #![rustc_alloc_kind = "exe"]
 
-extern crate alloc_system;
 extern crate libc;
 
 #[cfg(not(dummy_jemalloc))]
 pub use contents::*;
 #[cfg(not(dummy_jemalloc))]
 mod contents {
-    use core::alloc::GlobalAlloc;
-    use alloc_system::System;
     use libc::{c_int, c_void, size_t};
 
     // Note that the symbols here are prefixed by default on macOS and Windows (we
@@ -100,10 +97,11 @@ fn align_to_flags(align: usize, size: usize) -> c_int {
         ptr
     }
 
+    #[cfg(stage0)]
     #[no_mangle]
     #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_oom() -> ! {
-        System.oom()
+        ::core::intrinsics::abort();
     }
 
     #[no_mangle]
index fd8109e2a4aab3d72d280c6fbab55bb44d9f611a..7376ac0f15dd0fd7a61b62e2826bca468008c8e5 100644 (file)
@@ -71,11 +71,6 @@ unsafe fn realloc(&mut self,
                       new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        ::oom()
-    }
 }
 
 #[cfg(stage0)]
@@ -103,11 +98,6 @@ unsafe fn realloc(&mut self,
                       new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::realloc(*self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        ::oom()
-    }
 }
 
 #[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
@@ -366,63 +356,3 @@ unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *
         }
     }
 }
-
-#[inline]
-fn oom() -> ! {
-    write_to_stderr("fatal runtime error: memory allocation failed");
-    unsafe {
-        ::core::intrinsics::abort();
-    }
-}
-
-#[cfg(any(unix, target_os = "redox"))]
-#[inline]
-fn write_to_stderr(s: &str) {
-    extern crate libc;
-
-    unsafe {
-        libc::write(libc::STDERR_FILENO,
-                    s.as_ptr() as *const libc::c_void,
-                    s.len());
-    }
-}
-
-#[cfg(windows)]
-#[inline]
-fn write_to_stderr(s: &str) {
-    use core::ptr;
-
-    type LPVOID = *mut u8;
-    type HANDLE = LPVOID;
-    type DWORD = u32;
-    type BOOL = i32;
-    type LPDWORD = *mut DWORD;
-    type LPOVERLAPPED = *mut u8;
-
-    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
-
-    extern "system" {
-        fn WriteFile(hFile: HANDLE,
-                     lpBuffer: LPVOID,
-                     nNumberOfBytesToWrite: DWORD,
-                     lpNumberOfBytesWritten: LPDWORD,
-                     lpOverlapped: LPOVERLAPPED)
-                     -> BOOL;
-        fn GetStdHandle(which: DWORD) -> HANDLE;
-    }
-
-    unsafe {
-        // WriteFile silently fails if it is passed an invalid
-        // handle, so there is no need to check the result of
-        // GetStdHandle.
-        WriteFile(GetStdHandle(STD_ERROR_HANDLE),
-                  s.as_ptr() as LPVOID,
-                  s.len() as DWORD,
-                  ptr::null_mut(),
-                  ptr::null_mut());
-    }
-}
-
-#[cfg(not(any(windows, unix, target_os = "redox")))]
-#[inline]
-fn write_to_stderr(_: &str) {}
index b53c0a2f48bf701d2b8d0dc8f50c8c3125bc6f6f..e2af67dd9286138e61ef1196d4d7a8487a80c20c 100644 (file)
@@ -7,3 +7,6 @@ version = "0.0.0"
 name = "arena"
 path = "lib.rs"
 crate-type = ["dylib"]
+
+[dependencies]
+rustc_data_structures = { path = "../librustc_data_structures" }
\ No newline at end of file
index b319f333342c1cc11134d98d0881aca582eb7bf8..c79e0e14e3d8b4d1ab65050153537f716e37508b 100644 (file)
@@ -32,6 +32,9 @@
 #![allow(deprecated)]
 
 extern crate alloc;
+extern crate rustc_data_structures;
+
+use rustc_data_structures::sync::MTLock;
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -290,6 +293,8 @@ pub struct DroplessArena {
     chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
 }
 
+unsafe impl Send for DroplessArena {}
+
 impl DroplessArena {
     pub fn new() -> DroplessArena {
         DroplessArena {
@@ -410,6 +415,72 @@ pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
     }
 }
 
+pub struct SyncTypedArena<T> {
+    lock: MTLock<TypedArena<T>>,
+}
+
+impl<T> SyncTypedArena<T> {
+    #[inline(always)]
+    pub fn new() -> SyncTypedArena<T> {
+        SyncTypedArena {
+            lock: MTLock::new(TypedArena::new())
+        }
+    }
+
+    #[inline(always)]
+    pub fn alloc(&self, object: T) -> &mut T {
+        // Extend the lifetime of the result since it's limited to the lock guard
+        unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
+    }
+
+    #[inline(always)]
+    pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
+    where
+        T: Copy,
+    {
+        // Extend the lifetime of the result since it's limited to the lock guard
+        unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
+    }
+
+    #[inline(always)]
+    pub fn clear(&mut self) {
+        self.lock.get_mut().clear();
+    }
+}
+
+pub struct SyncDroplessArena {
+    lock: MTLock<DroplessArena>,
+}
+
+impl SyncDroplessArena {
+    #[inline(always)]
+    pub fn new() -> SyncDroplessArena {
+        SyncDroplessArena {
+            lock: MTLock::new(DroplessArena::new())
+        }
+    }
+
+    #[inline(always)]
+    pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
+        self.lock.lock().in_arena(ptr)
+    }
+
+    #[inline(always)]
+    pub fn alloc<T>(&self, object: T) -> &mut T {
+        // Extend the lifetime of the result since it's limited to the lock guard
+        unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
+    }
+
+    #[inline(always)]
+    pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
+    where
+        T: Copy,
+    {
+        // Extend the lifetime of the result since it's limited to the lock guard
+        unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate test;
index f08baa3dd71c3146ec312b325b66eff00761f6df..674c4fb57c7f03de938288d6550d632e22484355 100644 (file)
@@ -63,7 +63,7 @@ fn size_align<T>() -> (usize, usize) {
 /// requests have positive size. A caller to the `Alloc::alloc`
 /// method must either ensure that conditions like this are met, or
 /// use specific allocators with looser requirements.)
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct Layout {
     // size of the requested block of memory, measured in bytes.
     size: usize,
@@ -451,17 +451,6 @@ unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *
         }
         new_ptr
     }
-
-    /// Aborts the thread or process, optionally performing
-    /// cleanup or logging diagnostic information before panicking or
-    /// aborting.
-    ///
-    /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request, and wish to abandon
-    /// computation rather than attempt to recover locally.
-    fn oom(&self) -> ! {
-        unsafe { ::intrinsics::abort() }
-    }
 }
 
 /// An implementation of `Alloc` can allocate, reallocate, and
@@ -614,32 +603,6 @@ pub unsafe trait Alloc {
     ///   to allocate that block of memory.
     unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout);
 
-    /// Allocator-specific method for signaling an out-of-memory
-    /// condition.
-    ///
-    /// `oom` aborts the thread or process, optionally performing
-    /// cleanup or logging diagnostic information before panicking or
-    /// aborting.
-    ///
-    /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request, and wish to abandon
-    /// computation rather than attempt to recover locally.
-    ///
-    /// Implementations of the `oom` method are discouraged from
-    /// infinitely regressing in nested calls to `oom`. In
-    /// practice this means implementors should eschew allocating,
-    /// especially from `self` (directly or indirectly).
-    ///
-    /// Implementations of the allocation and reallocation methods
-    /// (e.g. `alloc`, `alloc_one`, `realloc`) are discouraged from
-    /// panicking (or aborting) in the event of memory exhaustion;
-    /// instead they should return an appropriate error from the
-    /// invoked method, and let the client decide whether to invoke
-    /// this `oom` method in response.
-    fn oom(&mut self) -> ! {
-        unsafe { ::intrinsics::abort() }
-    }
-
     // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS ==
     // usable_size
 
index 87144c27c9e11b1b71749f832c354cba97ff59f6..3d24f8902bd83827be8aee45f393f9cf9f9e33a6 100644 (file)
@@ -59,7 +59,7 @@ fn as_mut_slice(&mut self) -> &mut [T] {
 }
 
 /// The error type returned when a conversion from a slice to an array fails.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 #[derive(Debug, Copy, Clone)]
 pub struct TryFromSliceError(());
 
@@ -148,7 +148,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
                 }
             }
 
-            #[stable(feature = "try_from", since = "1.26.0")]
+            #[unstable(feature = "try_from", issue = "33417")]
             impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                 type Error = TryFromSliceError;
 
@@ -162,7 +162,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
                 }
             }
 
-            #[stable(feature = "try_from", since = "1.26.0")]
+            #[unstable(feature = "try_from", issue = "33417")]
             impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
                 type Error = TryFromSliceError;
 
index c8ee166fee3e9240383a7ff37c77a0c2e15be536..1ff187ed3f109722f397f705ce728e886494c87e 100644 (file)
@@ -256,6 +256,33 @@ impl<T:Copy> Cell<T> {
     pub fn get(&self) -> T {
         unsafe{ *self.value.get() }
     }
+
+    /// Updates the contained value using a function and returns the new value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_update)]
+    ///
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    /// let new = c.update(|x| x + 1);
+    ///
+    /// assert_eq!(new, 6);
+    /// assert_eq!(c.get(), 6);
+    /// ```
+    #[inline]
+    #[unstable(feature = "cell_update", issue = "50186")]
+    pub fn update<F>(&self, f: F) -> T
+    where
+        F: FnOnce(T) -> T,
+    {
+        let old = self.get();
+        let new = f(old);
+        self.set(new);
+        new
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 150562a4a9b290019c62835286f05573291b345c..803a924eb3a469f49b20f21ccbe55bd81176dd3c 100644 (file)
@@ -204,7 +204,7 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
 }
 
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl TryFrom<u32> for char {
     type Error = CharTryFromError;
 
@@ -219,11 +219,11 @@ fn try_from(i: u32) -> Result<Self, Self::Error> {
 }
 
 /// The error type returned when a conversion from u32 to char fails.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct CharTryFromError(());
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl fmt::Display for CharTryFromError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         "converted integer out of range for `char`".fmt(f)
index 9edc0c88756b3c74073dad9e512c512d1a096521..210eceebc51010c74879667d4018a47fc7486d18 100644 (file)
@@ -40,7 +40,7 @@
 pub use self::convert::from_u32_unchecked;
 #[stable(feature = "char_from_str", since = "1.20.0")]
 pub use self::convert::ParseCharError;
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 pub use self::convert::CharTryFromError;
 #[stable(feature = "decode_utf16", since = "1.9.0")]
 pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
index 58a8439162c118586033a21603889c32ed6bed7e..f79f73516989f1597f4a55b425bd33009daddd66 100644 (file)
@@ -179,7 +179,7 @@ fn clone(&self) -> Self {
         bool char
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Clone for ! {
         #[inline]
         fn clone(&self) -> Self {
index 3ae9b05b865386563ee9e78764e5a7a18fb61ba7..c91aa06609dd7a5bf4c019ba3d12eb1d0e7d0013 100644 (file)
@@ -881,24 +881,24 @@ fn cmp(&self, other: &bool) -> Ordering {
 
     ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl PartialEq for ! {
         fn eq(&self, _: &!) -> bool {
             *self
         }
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Eq for ! {}
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl PartialOrd for ! {
         fn partial_cmp(&self, _: &!) -> Option<Ordering> {
             *self
         }
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Ord for ! {
         fn cmp(&self, _: &!) -> Ordering {
             *self
index 637213957848c6b7c01bf35fb791a96356669a76..7324df95bc5d5691306ba78924148e593abb4ed4 100644 (file)
@@ -322,26 +322,22 @@ pub trait From<T>: Sized {
 ///
 /// [`TryFrom`]: trait.TryFrom.html
 /// [`Into`]: trait.Into.html
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 pub trait TryInto<T>: Sized {
     /// The type returned in the event of a conversion error.
-    #[stable(feature = "try_from", since = "1.26.0")]
     type Error;
 
     /// Performs the conversion.
-    #[stable(feature = "try_from", since = "1.26.0")]
     fn try_into(self) -> Result<T, Self::Error>;
 }
 
 /// Attempt to construct `Self` via a conversion.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 pub trait TryFrom<T>: Sized {
     /// The type returned in the event of a conversion error.
-    #[stable(feature = "try_from", since = "1.26.0")]
     type Error;
 
     /// Performs the conversion.
-    #[stable(feature = "try_from", since = "1.26.0")]
     fn try_from(value: T) -> Result<Self, Self::Error>;
 }
 
@@ -409,7 +405,7 @@ fn from(t: T) -> T { t }
 
 
 // TryFrom implies TryInto
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryInto<U> for T where U: TryFrom<T>
 {
     type Error = U::Error;
@@ -421,7 +417,7 @@ fn try_into(self) -> Result<U, U::Error> {
 
 // Infallible conversions are semantically equivalent to fallible conversions
 // with an uninhabited error type.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryFrom<U> for T where T: From<U> {
     type Error = !;
 
index d55219d7226e6d5fda7e7679df06994ab6a987f8..a8430f14410e6aef368198e038840f4177214371 100644 (file)
@@ -1212,7 +1212,11 @@ pub fn pad(&mut self, s: &str) -> Result {
             // truncation. However other flags like `fill`, `width` and `align`
             // must act as always.
             if let Some((i, _)) = s.char_indices().skip(max).next() {
-                &s[..i]
+                // LLVM here can't prove that `..i` won't panic `&s[..i]`, but
+                // we know that it can't panic. Use `get` + `unwrap_or` to avoid
+                // `unsafe` and otherwise don't emit any panic-related code
+                // here.
+                s.get(..i).unwrap_or(&s)
             } else {
                 &s
             }
@@ -1776,14 +1780,14 @@ fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
 
 fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
 
-#[stable(feature = "never_type", since = "1.26.0")]
+#[unstable(feature = "never_type", issue = "35121")]
 impl Debug for ! {
     fn fmt(&self, _: &mut Formatter) -> Result {
         *self
     }
 }
 
-#[stable(feature = "never_type", since = "1.26.0")]
+#[unstable(feature = "never_type", issue = "35121")]
 impl Display for ! {
     fn fmt(&self, _: &mut Formatter) -> Result {
         *self
index cb215a38e5356247808236b1286732338a53ebc9..58eef6492877a4b0d6430d614eb119498289a6ce 100644 (file)
@@ -87,3 +87,16 @@ fn $method(&mut self, other: &'a $u) {
     }
 }
 
+#[cfg(stage0)]
+macro_rules! public_in_stage0 {
+    ( { $(#[$attr:meta])* } $($Item: tt)*) => {
+        $(#[$attr])* pub $($Item)*
+    }
+}
+
+#[cfg(not(stage0))]
+macro_rules! public_in_stage0 {
+    ( { $(#[$attr:meta])* } $($Item: tt)*) => {
+        $(#[$attr])* pub(crate) $($Item)*
+    }
+}
index 4ccf446aa6346f007655b95e50ebe30e60881c1a..6a77de2c9868dd68e160682895dbdf34d73dbe07 100644 (file)
@@ -998,7 +998,7 @@ fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
     /// an extra layer of indirection. `flat_map()` will remove this extra layer
     /// on its own.
     ///
-    /// You can think of [`flat_map(f)`][flat_map] as the semantic equivalent
+    /// You can think of `flat_map(f)` as the semantic equivalent
     /// of [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`.
     ///
     /// Another way of thinking about `flat_map()`: [`map`]'s closure returns
index 1968c11d06223ba880d778fe6da49c2d6f757ecc..0e21a3327fddf471f6a486fb9e1f222f5e545981 100644 (file)
 #![feature(asm)]
 #![feature(associated_type_defaults)]
 #![feature(attr_literals)]
-#![feature(cfg_target_feature)]
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
 #![feature(const_fn)]
+#![feature(core_float)]
 #![feature(custom_attribute)]
 #![feature(doc_cfg)]
 #![feature(doc_spotlight)]
@@ -83,6 +83,7 @@
 #![feature(iterator_repeat_with)]
 #![feature(lang_items)]
 #![feature(link_llvm_intrinsics)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(macro_at_most_once_rep)]
 #![feature(no_core)]
 #![feature(rustc_attrs)]
 #![feature(rustc_const_unstable)]
 #![feature(simd_ffi)]
+#![feature(core_slice_ext)]
+#![feature(core_str_ext)]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(stmt_expr_attributes)]
-#![feature(target_feature)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
+#![feature(doc_alias)]
+
+#![cfg_attr(not(stage0), feature(mmx_target_feature))]
+#![cfg_attr(not(stage0), feature(tbm_target_feature))]
+#![cfg_attr(not(stage0), feature(sse4a_target_feature))]
+#![cfg_attr(not(stage0), feature(arm_target_feature))]
+#![cfg_attr(not(stage0), feature(powerpc_target_feature))]
+#![cfg_attr(not(stage0), feature(mips_target_feature))]
+#![cfg_attr(not(stage0), feature(aarch64_target_feature))]
+
+#![cfg_attr(stage0, feature(target_feature))]
+#![cfg_attr(stage0, feature(cfg_target_feature))]
 
 #[prelude_import]
 #[allow(unused)]
@@ -205,8 +219,22 @@ pub mod heap {
 // things like SIMD and such. Note that the actual source for all this lies in a
 // different repository, rust-lang-nursery/stdsimd. That's why the setup here is
 // a bit wonky.
+#[allow(unused_macros)]
+macro_rules! test_v16 { ($item:item) => {}; }
+#[allow(unused_macros)]
+macro_rules! test_v32 { ($item:item) => {}; }
+#[allow(unused_macros)]
+macro_rules! test_v64 { ($item:item) => {}; }
+#[allow(unused_macros)]
+macro_rules! test_v128 { ($item:item) => {}; }
+#[allow(unused_macros)]
+macro_rules! test_v256 { ($item:item) => {}; }
+#[allow(unused_macros)]
+macro_rules! test_v512 { ($item:item) => {}; }
+#[allow(unused_macros)]
+macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
 #[path = "../stdsimd/coresimd/mod.rs"]
-#[allow(missing_docs, missing_debug_implementations, dead_code)]
+#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
 #[unstable(feature = "stdsimd", issue = "48556")]
 #[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
 mod coresimd;
@@ -214,6 +242,6 @@ pub mod heap {
 #[unstable(feature = "stdsimd", issue = "48556")]
 #[cfg(not(stage0))]
 pub use coresimd::simd;
-#[unstable(feature = "stdsimd", issue = "48556")]
+#[stable(feature = "simd_arch", since = "1.27.0")]
 #[cfg(not(stage0))]
 pub use coresimd::arch;
index 1e2551e36f54442214c0d732e0ee6cc28164b985..f9371ed0575e49782f7471320d83c5b852d663a1 100644 (file)
@@ -295,6 +295,7 @@ macro_rules! debug_assert_ne {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "?")]
 macro_rules! try {
     ($expr:expr) => (match $expr {
         $crate::result::Result::Ok(val) => val,
index 885aabe08069d4e064cbebd9183819fe799084e8..feb689dbc1fe8c525282b83ea0fda8ceeef46515 100644 (file)
@@ -630,7 +630,7 @@ impl Copy for $t {}
         bool char
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Copy for ! {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
index 3586fa5442fb44a1712882cbc8864570fa5ea04a..8d5f6f601daf8a3c0eebc46cadc9124c7219700c 100644 (file)
@@ -17,9 +17,9 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use intrinsics;
 use mem;
 use num::Float;
+#[cfg(not(stage0))] use num::FpCategory;
 use num::FpCategory as Fp;
 
 /// The radix or base of the internal representation of `f32`.
@@ -188,27 +188,6 @@ fn classify(self) -> Fp {
         }
     }
 
-    /// Computes the absolute value of `self`. Returns `Float::nan()` if the
-    /// number is `Float::nan()`.
-    #[inline]
-    fn abs(self) -> f32 {
-        unsafe { intrinsics::fabsf32(self) }
-    }
-
-    /// Returns a number that represents the sign of `self`.
-    ///
-    /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
-    /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
-    /// - `Float::nan()` if the number is `Float::nan()`
-    #[inline]
-    fn signum(self) -> f32 {
-        if self.is_nan() {
-            NAN
-        } else {
-            unsafe { intrinsics::copysignf32(1.0, self) }
-        }
-    }
-
     /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
     /// positive sign bit and positive infinity.
     #[inline]
@@ -231,11 +210,6 @@ fn recip(self) -> f32 {
         1.0 / self
     }
 
-    #[inline]
-    fn powi(self, n: i32) -> f32 {
-        unsafe { intrinsics::powif32(self, n) }
-    }
-
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f32 {
@@ -292,3 +266,286 @@ fn from_bits(v: u32) -> Self {
         unsafe { mem::transmute(v) }
     }
 }
+
+// FIXME: remove (inline) this macro and the Float trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_float", issue = "32110")]
+macro_rules! f32_core_methods { () => {
+    /// Returns `true` if this value is `NaN` and false otherwise.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let nan = f32::NAN;
+    /// let f = 7.0_f32;
+    ///
+    /// assert!(nan.is_nan());
+    /// assert!(!f.is_nan());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_nan(self) -> bool { Float::is_nan(self) }
+
+    /// Returns `true` if this value is positive infinity or negative infinity and
+    /// false otherwise.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let f = 7.0f32;
+    /// let inf = f32::INFINITY;
+    /// let neg_inf = f32::NEG_INFINITY;
+    /// let nan = f32::NAN;
+    ///
+    /// assert!(!f.is_infinite());
+    /// assert!(!nan.is_infinite());
+    ///
+    /// assert!(inf.is_infinite());
+    /// assert!(neg_inf.is_infinite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
+
+    /// Returns `true` if this number is neither infinite nor `NaN`.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let f = 7.0f32;
+    /// let inf = f32::INFINITY;
+    /// let neg_inf = f32::NEG_INFINITY;
+    /// let nan = f32::NAN;
+    ///
+    /// assert!(f.is_finite());
+    ///
+    /// assert!(!nan.is_finite());
+    /// assert!(!inf.is_finite());
+    /// assert!(!neg_inf.is_finite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_finite(self) -> bool { Float::is_finite(self) }
+
+    /// Returns `true` if the number is neither zero, infinite,
+    /// [subnormal][subnormal], or `NaN`.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
+    /// let max = f32::MAX;
+    /// let lower_than_min = 1.0e-40_f32;
+    /// let zero = 0.0_f32;
+    ///
+    /// assert!(min.is_normal());
+    /// assert!(max.is_normal());
+    ///
+    /// assert!(!zero.is_normal());
+    /// assert!(!f32::NAN.is_normal());
+    /// assert!(!f32::INFINITY.is_normal());
+    /// // Values between `0` and `min` are Subnormal.
+    /// assert!(!lower_than_min.is_normal());
+    /// ```
+    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_normal(self) -> bool { Float::is_normal(self) }
+
+    /// Returns the floating point category of the number. If only one property
+    /// is going to be tested, it is generally faster to use the specific
+    /// predicate instead.
+    ///
+    /// ```
+    /// use std::num::FpCategory;
+    /// use std::f32;
+    ///
+    /// let num = 12.4_f32;
+    /// let inf = f32::INFINITY;
+    ///
+    /// assert_eq!(num.classify(), FpCategory::Normal);
+    /// assert_eq!(inf.classify(), FpCategory::Infinite);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn classify(self) -> FpCategory { Float::classify(self) }
+
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
+    ///
+    /// ```
+    /// let f = 7.0_f32;
+    /// let g = -7.0_f32;
+    ///
+    /// assert!(f.is_sign_positive());
+    /// assert!(!g.is_sign_positive());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
+
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
+    ///
+    /// ```
+    /// let f = 7.0f32;
+    /// let g = -7.0f32;
+    ///
+    /// assert!(!f.is_sign_negative());
+    /// assert!(g.is_sign_negative());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
+
+    /// Takes the reciprocal (inverse) of a number, `1/x`.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let x = 2.0_f32;
+    /// let abs_difference = (x.recip() - (1.0/x)).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn recip(self) -> f32 { Float::recip(self) }
+
+    /// Converts radians to degrees.
+    ///
+    /// ```
+    /// use std::f32::{self, consts};
+    ///
+    /// let angle = consts::PI;
+    ///
+    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
+    #[inline]
+    pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
+
+    /// Converts degrees to radians.
+    ///
+    /// ```
+    /// use std::f32::{self, consts};
+    ///
+    /// let angle = 180.0f32;
+    ///
+    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
+    #[inline]
+    pub fn to_radians(self) -> f32 { Float::to_radians(self) }
+
+    /// Returns the maximum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0f32;
+    /// let y = 2.0f32;
+    ///
+    /// assert_eq!(x.max(y), y);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn max(self, other: f32) -> f32 {
+        Float::max(self, other)
+    }
+
+    /// Returns the minimum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0f32;
+    /// let y = 2.0f32;
+    ///
+    /// assert_eq!(x.min(y), x);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn min(self, other: f32) -> f32 {
+        Float::min(self, other)
+    }
+
+    /// Raw transmutation to `u32`.
+    ///
+    /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
+    ///
+    /// See `from_bits` for some discussion of the portability of this operation
+    /// (there are almost no issues).
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
+    /// assert_eq!((12.5f32).to_bits(), 0x41480000);
+    ///
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn to_bits(self) -> u32 {
+        Float::to_bits(self)
+    }
+
+    /// Raw transmutation from `u32`.
+    ///
+    /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
+    /// It turns out this is incredibly portable, for two reasons:
+    ///
+    /// * Floats and Ints have the same endianness on all supported platforms.
+    /// * IEEE-754 very precisely specifies the bit layout of floats.
+    ///
+    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
+    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
+    /// (notably x86 and ARM) picked the interpretation that was ultimately
+    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
+    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
+    ///
+    /// Rather than trying to preserve signaling-ness cross-platform, this
+    /// implementation favours preserving the exact bits. This means that
+    /// any payloads encoded in NaNs will be preserved even if the result of
+    /// this method is sent over the network from an x86 machine to a MIPS one.
+    ///
+    /// If the results of this method are only manipulated by the same
+    /// architecture that produced them, then there is no portability concern.
+    ///
+    /// If the input isn't NaN, then there is no portability concern.
+    ///
+    /// If you don't care about signalingness (very likely), then there is no
+    /// portability concern.
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::f32;
+    /// let v = f32::from_bits(0x41480000);
+    /// let difference = (v - 12.5).abs();
+    /// assert!(difference <= 1e-5);
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn from_bits(v: u32) -> Self {
+        Float::from_bits(v)
+    }
+}}
+
+#[lang = "f32"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl f32 {
+    f32_core_methods!();
+}
index 64c0d508b388cf6b41b8a3df3e0567af55092822..08b869734d49627099a649553567dd660159b4ca 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use intrinsics;
 use mem;
-use num::FpCategory as Fp;
 use num::Float;
+#[cfg(not(stage0))] use num::FpCategory;
+use num::FpCategory as Fp;
 
 /// The radix or base of the internal representation of `f64`.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -188,27 +188,6 @@ fn classify(self) -> Fp {
         }
     }
 
-    /// Computes the absolute value of `self`. Returns `Float::nan()` if the
-    /// number is `Float::nan()`.
-    #[inline]
-    fn abs(self) -> f64 {
-        unsafe { intrinsics::fabsf64(self) }
-    }
-
-    /// Returns a number that represents the sign of `self`.
-    ///
-    /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
-    /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
-    /// - `Float::nan()` if the number is `Float::nan()`
-    #[inline]
-    fn signum(self) -> f64 {
-        if self.is_nan() {
-            NAN
-        } else {
-            unsafe { intrinsics::copysignf64(1.0, self) }
-        }
-    }
-
     /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
     /// positive sign bit and positive infinity.
     #[inline]
@@ -229,11 +208,6 @@ fn recip(self) -> f64 {
         1.0 / self
     }
 
-    #[inline]
-    fn powi(self, n: i32) -> f64 {
-        unsafe { intrinsics::powif64(self, n) }
-    }
-
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f64 {
@@ -291,3 +265,296 @@ fn from_bits(v: u64) -> Self {
         unsafe { mem::transmute(v) }
     }
 }
+
+// FIXME: remove (inline) this macro and the Float trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_float", issue = "32110")]
+macro_rules! f64_core_methods { () => {
+    /// Returns `true` if this value is `NaN` and false otherwise.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let nan = f64::NAN;
+    /// let f = 7.0_f64;
+    ///
+    /// assert!(nan.is_nan());
+    /// assert!(!f.is_nan());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_nan(self) -> bool { Float::is_nan(self) }
+
+    /// Returns `true` if this value is positive infinity or negative infinity and
+    /// false otherwise.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let f = 7.0f64;
+    /// let inf = f64::INFINITY;
+    /// let neg_inf = f64::NEG_INFINITY;
+    /// let nan = f64::NAN;
+    ///
+    /// assert!(!f.is_infinite());
+    /// assert!(!nan.is_infinite());
+    ///
+    /// assert!(inf.is_infinite());
+    /// assert!(neg_inf.is_infinite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
+
+    /// Returns `true` if this number is neither infinite nor `NaN`.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let f = 7.0f64;
+    /// let inf: f64 = f64::INFINITY;
+    /// let neg_inf: f64 = f64::NEG_INFINITY;
+    /// let nan: f64 = f64::NAN;
+    ///
+    /// assert!(f.is_finite());
+    ///
+    /// assert!(!nan.is_finite());
+    /// assert!(!inf.is_finite());
+    /// assert!(!neg_inf.is_finite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_finite(self) -> bool { Float::is_finite(self) }
+
+    /// Returns `true` if the number is neither zero, infinite,
+    /// [subnormal][subnormal], or `NaN`.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
+    /// let max = f64::MAX;
+    /// let lower_than_min = 1.0e-308_f64;
+    /// let zero = 0.0f64;
+    ///
+    /// assert!(min.is_normal());
+    /// assert!(max.is_normal());
+    ///
+    /// assert!(!zero.is_normal());
+    /// assert!(!f64::NAN.is_normal());
+    /// assert!(!f64::INFINITY.is_normal());
+    /// // Values between `0` and `min` are Subnormal.
+    /// assert!(!lower_than_min.is_normal());
+    /// ```
+    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_normal(self) -> bool { Float::is_normal(self) }
+
+    /// Returns the floating point category of the number. If only one property
+    /// is going to be tested, it is generally faster to use the specific
+    /// predicate instead.
+    ///
+    /// ```
+    /// use std::num::FpCategory;
+    /// use std::f64;
+    ///
+    /// let num = 12.4_f64;
+    /// let inf = f64::INFINITY;
+    ///
+    /// assert_eq!(num.classify(), FpCategory::Normal);
+    /// assert_eq!(inf.classify(), FpCategory::Infinite);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn classify(self) -> FpCategory { Float::classify(self) }
+
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
+    ///
+    /// ```
+    /// let f = 7.0_f64;
+    /// let g = -7.0_f64;
+    ///
+    /// assert!(f.is_sign_positive());
+    /// assert!(!g.is_sign_positive());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
+    #[inline]
+    #[doc(hidden)]
+    pub fn is_positive(self) -> bool { Float::is_sign_positive(self) }
+
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
+    ///
+    /// ```
+    /// let f = 7.0_f64;
+    /// let g = -7.0_f64;
+    ///
+    /// assert!(!f.is_sign_negative());
+    /// assert!(g.is_sign_negative());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
+    #[inline]
+    #[doc(hidden)]
+    pub fn is_negative(self) -> bool { Float::is_sign_negative(self) }
+
+    /// Takes the reciprocal (inverse) of a number, `1/x`.
+    ///
+    /// ```
+    /// let x = 2.0_f64;
+    /// let abs_difference = (x.recip() - (1.0/x)).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn recip(self) -> f64 { Float::recip(self) }
+
+    /// Converts radians to degrees.
+    ///
+    /// ```
+    /// use std::f64::consts;
+    ///
+    /// let angle = consts::PI;
+    ///
+    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
+
+    /// Converts degrees to radians.
+    ///
+    /// ```
+    /// use std::f64::consts;
+    ///
+    /// let angle = 180.0_f64;
+    ///
+    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn to_radians(self) -> f64 { Float::to_radians(self) }
+
+    /// Returns the maximum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0_f64;
+    /// let y = 2.0_f64;
+    ///
+    /// assert_eq!(x.max(y), y);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn max(self, other: f64) -> f64 {
+        Float::max(self, other)
+    }
+
+    /// Returns the minimum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0_f64;
+    /// let y = 2.0_f64;
+    ///
+    /// assert_eq!(x.min(y), x);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn min(self, other: f64) -> f64 {
+        Float::min(self, other)
+    }
+
+    /// Raw transmutation to `u64`.
+    ///
+    /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
+    ///
+    /// See `from_bits` for some discussion of the portability of this operation
+    /// (there are almost no issues).
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
+    /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
+    ///
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn to_bits(self) -> u64 {
+        Float::to_bits(self)
+    }
+
+    /// Raw transmutation from `u64`.
+    ///
+    /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
+    /// It turns out this is incredibly portable, for two reasons:
+    ///
+    /// * Floats and Ints have the same endianness on all supported platforms.
+    /// * IEEE-754 very precisely specifies the bit layout of floats.
+    ///
+    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
+    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
+    /// (notably x86 and ARM) picked the interpretation that was ultimately
+    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
+    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
+    ///
+    /// Rather than trying to preserve signaling-ness cross-platform, this
+    /// implementation favours preserving the exact bits. This means that
+    /// any payloads encoded in NaNs will be preserved even if the result of
+    /// this method is sent over the network from an x86 machine to a MIPS one.
+    ///
+    /// If the results of this method are only manipulated by the same
+    /// architecture that produced them, then there is no portability concern.
+    ///
+    /// If the input isn't NaN, then there is no portability concern.
+    ///
+    /// If you don't care about signalingness (very likely), then there is no
+    /// portability concern.
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::f64;
+    /// let v = f64::from_bits(0x4029000000000000);
+    /// let difference = (v - 12.5).abs();
+    /// assert!(difference <= 1e-5);
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn from_bits(v: u64) -> Self {
+        Float::from_bits(v)
+    }
+}}
+
+#[lang = "f64"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl f64 {
+    f64_core_methods!();
+}
index f2e8caaad1485ac00e78b0629da906ffd3df866c..aa4d4bc638b1d236d9f3752a2020e999aaa41684 100644 (file)
@@ -4098,83 +4098,58 @@ pub enum FpCategory {
     Normal,
 }
 
-/// A built-in floating point number.
+// Technically private and only exposed for coretests:
 #[doc(hidden)]
-#[unstable(feature = "core_float",
-           reason = "stable interface is via `impl f{32,64}` in later crates",
-           issue = "32110")]
+#[unstable(feature = "float_internals",
+           reason = "internal routines only exposed for testing",
+           issue = "0")]
 pub trait Float: Sized {
     /// Type used by `to_bits` and `from_bits`.
-    #[stable(feature = "core_float_bits", since = "1.25.0")]
     type Bits;
 
     /// Returns `true` if this value is NaN and false otherwise.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_nan(self) -> bool;
+
     /// Returns `true` if this value is positive infinity or negative infinity and
     /// false otherwise.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_infinite(self) -> bool;
+
     /// Returns `true` if this number is neither infinite nor NaN.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_finite(self) -> bool;
+
     /// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_normal(self) -> bool;
+
     /// Returns the category that this number falls into.
-    #[stable(feature = "core", since = "1.6.0")]
     fn classify(self) -> FpCategory;
 
-    /// Computes the absolute value of `self`. Returns `Float::nan()` if the
-    /// number is `Float::nan()`.
-    #[stable(feature = "core", since = "1.6.0")]
-    fn abs(self) -> Self;
-    /// Returns a number that represents the sign of `self`.
-    ///
-    /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
-    /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
-    /// - `Float::nan()` if the number is `Float::nan()`
-    #[stable(feature = "core", since = "1.6.0")]
-    fn signum(self) -> Self;
-
     /// Returns `true` if `self` is positive, including `+0.0` and
     /// `Float::infinity()`.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_sign_positive(self) -> bool;
+
     /// Returns `true` if `self` is negative, including `-0.0` and
     /// `Float::neg_infinity()`.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_sign_negative(self) -> bool;
 
     /// Take the reciprocal (inverse) of a number, `1/x`.
-    #[stable(feature = "core", since = "1.6.0")]
     fn recip(self) -> Self;
 
-    /// Raise a number to an integer power.
-    ///
-    /// Using this function is generally faster than using `powf`
-    #[stable(feature = "core", since = "1.6.0")]
-    fn powi(self, n: i32) -> Self;
-
     /// Convert radians to degrees.
-    #[stable(feature = "deg_rad_conversions", since="1.7.0")]
     fn to_degrees(self) -> Self;
+
     /// Convert degrees to radians.
-    #[stable(feature = "deg_rad_conversions", since="1.7.0")]
     fn to_radians(self) -> Self;
 
     /// Returns the maximum of the two numbers.
-    #[stable(feature = "core_float_min_max", since="1.20.0")]
     fn max(self, other: Self) -> Self;
+
     /// Returns the minimum of the two numbers.
-    #[stable(feature = "core_float_min_max", since="1.20.0")]
     fn min(self, other: Self) -> Self;
 
     /// Raw transmutation to integer.
-    #[stable(feature = "core_float_bits", since="1.25.0")]
     fn to_bits(self) -> Self::Bits;
+
     /// Raw transmutation from integer.
-    #[stable(feature = "core_float_bits", since="1.25.0")]
     fn from_bits(v: Self::Bits) -> Self;
 }
 
@@ -4192,7 +4167,7 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
 from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
 
 /// The error type returned when a checked integral type conversion fails.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 #[derive(Debug, Copy, Clone)]
 pub struct TryFromIntError(());
 
@@ -4207,14 +4182,14 @@ pub fn __description(&self) -> &str {
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl fmt::Display for TryFromIntError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         self.__description().fmt(fmt)
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl From<!> for TryFromIntError {
     fn from(never: !) -> TryFromIntError {
         never
@@ -4224,7 +4199,7 @@ fn from(never: !) -> TryFromIntError {
 // only negative bounds
 macro_rules! try_from_lower_bounded {
     ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.26.0")]
+        #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -4243,7 +4218,7 @@ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
 // unsigned to signed (only positive bound)
 macro_rules! try_from_upper_bounded {
     ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.26.0")]
+        #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -4262,7 +4237,7 @@ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
 // all other cases
 macro_rules! try_from_both_bounded {
     ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.26.0")]
+        #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
index 88db019b02f0789fd8175a1b6623a3c5b7b678e4..a1f6030428f1ef073b7d95d8fe4fa9ca37e01291 100644 (file)
@@ -87,6 +87,7 @@
     message="cannot add `{RHS}` to `{Self}`",
     label="no implementation for `{Self} + {RHS}`",
 )]
+#[doc(alias = "+")]
 pub trait Add<RHS=Self> {
     /// The resulting type after applying the `+` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -183,6 +184,7 @@ fn add(self, other: $t) -> $t { self + other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot subtract `{RHS}` from `{Self}`",
                          label="no implementation for `{Self} - {RHS}`")]
+#[doc(alias = "-")]
 pub trait Sub<RHS=Self> {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -301,6 +303,7 @@ fn sub(self, other: $t) -> $t { self - other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
                          label="no implementation for `{Self} * {RHS}`")]
+#[doc(alias = "*")]
 pub trait Mul<RHS=Self> {
     /// The resulting type after applying the `*` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -423,6 +426,7 @@ fn mul(self, other: $t) -> $t { self * other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
                          label="no implementation for `{Self} / {RHS}`")]
+#[doc(alias = "/")]
 pub trait Div<RHS=Self> {
     /// The resulting type after applying the `/` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -506,6 +510,7 @@ fn div(self, other: $t) -> $t { self / other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
                          label="no implementation for `{Self} % {RHS}`")]
+#[doc(alias = "%")]
 pub trait Rem<RHS=Self> {
     /// The resulting type after applying the `%` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -589,6 +594,7 @@ fn rem(self, other: $t) -> $t { self % other }
 /// ```
 #[lang = "neg"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "-")]
 pub trait Neg {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -664,6 +670,8 @@ macro_rules! neg_impl_unsigned {
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
                          label="no implementation for `{Self} += {Rhs}`")]
+#[doc(alias = "+")]
+#[doc(alias = "+=")]
 pub trait AddAssign<Rhs=Self> {
     /// Performs the `+=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -718,6 +726,8 @@ fn add_assign(&mut self, other: $t) { *self += other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`",
                          label="no implementation for `{Self} -= {Rhs}`")]
+#[doc(alias = "-")]
+#[doc(alias = "-=")]
 pub trait SubAssign<Rhs=Self> {
     /// Performs the `-=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -763,6 +773,8 @@ fn sub_assign(&mut self, other: $t) { *self -= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
                          label="no implementation for `{Self} *= {Rhs}`")]
+#[doc(alias = "*")]
+#[doc(alias = "*=")]
 pub trait MulAssign<Rhs=Self> {
     /// Performs the `*=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -808,6 +820,8 @@ fn mul_assign(&mut self, other: $t) { *self *= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
                          label="no implementation for `{Self} /= {Rhs}`")]
+#[doc(alias = "/")]
+#[doc(alias = "/=")]
 pub trait DivAssign<Rhs=Self> {
     /// Performs the `/=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -856,6 +870,8 @@ fn div_assign(&mut self, other: $t) { *self /= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
                          label="no implementation for `{Self} %= {Rhs}`")]
+#[doc(alias = "%")]
+#[doc(alias = "%=")]
 pub trait RemAssign<Rhs=Self> {
     /// Performs the `%=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
index ec1e65be774fa707031cf211011c44c2844b2506..81c4455cef4d934faa4b851e2a23c57dedd7054f 100644 (file)
@@ -375,7 +375,7 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
                          label="no implementation for `{Self} << {RHS}`")]
-pub trait Shl<RHS> {
+pub trait Shl<RHS=Self> {
     /// The resulting type after applying the `<<` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -482,7 +482,7 @@ macro_rules! shl_impl_all {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
                          label="no implementation for `{Self} >> {RHS}`")]
-pub trait Shr<RHS> {
+pub trait Shr<RHS=Self> {
     /// The resulting type after applying the `>>` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -738,7 +738,7 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
                          label="no implementation for `{Self} <<= {Rhs}`")]
-pub trait ShlAssign<Rhs> {
+pub trait ShlAssign<Rhs=Self> {
     /// Performs the `<<=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn shl_assign(&mut self, rhs: Rhs);
index d65c0aba5048103fe80c67056102347f876ee742..0a0e92a91800614a75608bd7099eb2e4fe79ab54 100644 (file)
@@ -62,6 +62,9 @@
 #[lang = "index"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "]")]
+#[doc(alias = "[")]
+#[doc(alias = "[]")]
 pub trait Index<Idx: ?Sized> {
     /// The returned type after indexing.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -146,6 +149,9 @@ pub trait Index<Idx: ?Sized> {
 #[lang = "index_mut"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
     /// Performs the mutable indexing (`container[index]`) operation.
     #[stable(feature = "rust1", since = "1.0.0")]
index 3f6674071256696e45bf74c8229a05c85993dd71..6f3e3b508853ba7c3172824222bd86a0ba6dfcb2 100644 (file)
@@ -100,17 +100,28 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
     /// ```
     /// #![feature(range_contains)]
     ///
-    /// assert!(!(3..5).contains(2));
-    /// assert!( (3..5).contains(3));
-    /// assert!( (3..5).contains(4));
-    /// assert!(!(3..5).contains(5));
+    /// use std::f32;
     ///
-    /// assert!(!(3..3).contains(3));
-    /// assert!(!(3..2).contains(3));
+    /// assert!(!(3..5).contains(&2));
+    /// assert!( (3..5).contains(&3));
+    /// assert!( (3..5).contains(&4));
+    /// assert!(!(3..5).contains(&5));
+    ///
+    /// assert!(!(3..3).contains(&3));
+    /// assert!(!(3..2).contains(&3));
+    ///
+    /// assert!( (0.0..1.0).contains(&0.5));
+    /// assert!(!(0.0..1.0).contains(&f32::NAN));
+    /// assert!(!(0.0..f32::NAN).contains(&0.5));
+    /// assert!(!(f32::NAN..1.0).contains(&0.5));
     /// ```
     #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
-    pub fn contains(&self, item: Idx) -> bool {
-        (self.start <= item) && (item < self.end)
+    pub fn contains<U>(&self, item: &U) -> bool
+    where
+        Idx: PartialOrd<U>,
+        U: ?Sized + PartialOrd<Idx>,
+    {
+        <Self as RangeBounds<Idx>>::contains(self, item)
     }
 
     /// Returns `true` if the range contains no items.
@@ -179,7 +190,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
     /// Returns `true` if `item` is contained in the range.
     ///
@@ -188,12 +198,23 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
     /// ```
     /// #![feature(range_contains)]
     ///
-    /// assert!(!(3..).contains(2));
-    /// assert!( (3..).contains(3));
-    /// assert!( (3..).contains(1_000_000_000));
+    /// use std::f32;
+    ///
+    /// assert!(!(3..).contains(&2));
+    /// assert!( (3..).contains(&3));
+    /// assert!( (3..).contains(&1_000_000_000));
+    ///
+    /// assert!( (0.0..).contains(&0.5));
+    /// assert!(!(0.0..).contains(&f32::NAN));
+    /// assert!(!(f32::NAN..).contains(&0.5));
     /// ```
-    pub fn contains(&self, item: Idx) -> bool {
-        (self.start <= item)
+    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    pub fn contains<U>(&self, item: &U) -> bool
+    where
+        Idx: PartialOrd<U>,
+        U: ?Sized + PartialOrd<Idx>,
+    {
+        <Self as RangeBounds<Idx>>::contains(self, item)
     }
 }
 
@@ -250,7 +271,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
     /// Returns `true` if `item` is contained in the range.
     ///
@@ -259,12 +279,23 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
     /// ```
     /// #![feature(range_contains)]
     ///
-    /// assert!( (..5).contains(-1_000_000_000));
-    /// assert!( (..5).contains(4));
-    /// assert!(!(..5).contains(5));
+    /// use std::f32;
+    ///
+    /// assert!( (..5).contains(&-1_000_000_000));
+    /// assert!( (..5).contains(&4));
+    /// assert!(!(..5).contains(&5));
+    ///
+    /// assert!( (..1.0).contains(&0.5));
+    /// assert!(!(..1.0).contains(&f32::NAN));
+    /// assert!(!(..f32::NAN).contains(&0.5));
     /// ```
-    pub fn contains(&self, item: Idx) -> bool {
-        (item < self.end)
+    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    pub fn contains<U>(&self, item: &U) -> bool
+    where
+        Idx: PartialOrd<U>,
+        U: ?Sized + PartialOrd<Idx>,
+    {
+        <Self as RangeBounds<Idx>>::contains(self, item)
     }
 }
 
@@ -318,18 +349,29 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
     /// ```
     /// #![feature(range_contains)]
     ///
-    /// assert!(!(3..=5).contains(2));
-    /// assert!( (3..=5).contains(3));
-    /// assert!( (3..=5).contains(4));
-    /// assert!( (3..=5).contains(5));
-    /// assert!(!(3..=5).contains(6));
+    /// use std::f32;
+    ///
+    /// assert!(!(3..=5).contains(&2));
+    /// assert!( (3..=5).contains(&3));
+    /// assert!( (3..=5).contains(&4));
+    /// assert!( (3..=5).contains(&5));
+    /// assert!(!(3..=5).contains(&6));
     ///
-    /// assert!( (3..=3).contains(3));
-    /// assert!(!(3..=2).contains(3));
+    /// assert!( (3..=3).contains(&3));
+    /// assert!(!(3..=2).contains(&3));
+    ///
+    /// assert!( (0.0..=1.0).contains(&1.0));
+    /// assert!(!(0.0..=1.0).contains(&f32::NAN));
+    /// assert!(!(0.0..=f32::NAN).contains(&0.0));
+    /// assert!(!(f32::NAN..=1.0).contains(&1.0));
     /// ```
     #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
-    pub fn contains(&self, item: Idx) -> bool {
-        self.start <= item && item <= self.end
+    pub fn contains<U>(&self, item: &U) -> bool
+    where
+        Idx: PartialOrd<U>,
+        U: ?Sized + PartialOrd<Idx>,
+    {
+        <Self as RangeBounds<Idx>>::contains(self, item)
     }
 
     /// Returns `true` if the range contains no items.
@@ -431,12 +473,23 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
     /// ```
     /// #![feature(range_contains)]
     ///
-    /// assert!( (..=5).contains(-1_000_000_000));
-    /// assert!( (..=5).contains(5));
-    /// assert!(!(..=5).contains(6));
+    /// use std::f32;
+    ///
+    /// assert!( (..=5).contains(&-1_000_000_000));
+    /// assert!( (..=5).contains(&5));
+    /// assert!(!(..=5).contains(&6));
+    ///
+    /// assert!( (..=1.0).contains(&1.0));
+    /// assert!(!(..=1.0).contains(&f32::NAN));
+    /// assert!(!(..=f32::NAN).contains(&0.5));
     /// ```
-    pub fn contains(&self, item: Idx) -> bool {
-        (item <= self.end)
+    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    pub fn contains<U>(&self, item: &U) -> bool
+    where
+        Idx: PartialOrd<U>,
+        U: ?Sized + PartialOrd<Idx>,
+    {
+        <Self as RangeBounds<Idx>>::contains(self, item)
     }
 }
 
@@ -537,6 +590,42 @@ pub trait RangeBounds<T: ?Sized> {
     /// # }
     /// ```
     fn end(&self) -> Bound<&T>;
+
+
+    /// Returns `true` if `item` is contained in the range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(range_contains)]
+    ///
+    /// use std::f32;
+    ///
+    /// assert!( (3..5).contains(&4));
+    /// assert!(!(3..5).contains(&2));
+    ///
+    /// assert!( (0.0..1.0).contains(&0.5));
+    /// assert!(!(0.0..1.0).contains(&f32::NAN));
+    /// assert!(!(0.0..f32::NAN).contains(&0.5));
+    /// assert!(!(f32::NAN..1.0).contains(&0.5));
+    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    fn contains<U>(&self, item: &U) -> bool
+    where
+        T: PartialOrd<U>,
+        U: ?Sized + PartialOrd<T>,
+    {
+        (match self.start() {
+            Included(ref start) => *start <= item,
+            Excluded(ref start) => *start < item,
+            Unbounded => true,
+        })
+        &&
+        (match self.end() {
+            Included(ref end) => item <= *end,
+            Excluded(ref end) => item < *end,
+            Unbounded => true,
+        })
+    }
 }
 
 use self::Bound::{Excluded, Included, Unbounded};
index ef6a8fb6a61c105686f26cef42068178ab4e46b1..4f2d30aa6a8a77b79fe8401f7acfed8904c38b86 100644 (file)
@@ -28,6 +28,7 @@
                that implement `{Try}`",
       label="the `?` operator cannot be applied to type `{Self}`")
 )]
+#[doc(alias = "?")]
 pub trait Try {
     /// The type of this value when viewed as successful.
     #[unstable(feature = "try_trait", issue = "42327")]
index 1720c9d8c60790a9a171f92c467fedbf86ed8dcf..27ec4aaac75dec3a9ed09cc4f268a880f97f3896 100644 (file)
@@ -49,11 +49,17 @@ impl<'a> PanicInfo<'a> {
                           and related macros",
                 issue = "0")]
     #[doc(hidden)]
-    pub fn internal_constructor(payload: &'a (Any + Send),
-                                message: Option<&'a fmt::Arguments<'a>>,
+    #[inline]
+    pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
                                 location: Location<'a>)
                                 -> Self {
-        PanicInfo { payload, location, message }
+        PanicInfo { payload: &(), location, message }
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn set_payload(&mut self, info: &'a (Any + Send)) {
+        self.payload = info;
     }
 
     /// Returns the payload associated with the panic.
@@ -251,3 +257,13 @@ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
     }
 }
+
+/// An internal trait used by libstd to pass data from libstd to `panic_unwind`
+/// and other panic runtimes. Not intended to be stabilized any time soon, do
+/// not use.
+#[unstable(feature = "std_internals", issue = "0")]
+#[doc(hidden)]
+pub unsafe trait BoxMeUp {
+    fn box_me_up(&mut self) -> *mut (Any + Send);
+    fn get(&mut self) -> &(Any + Send);
+}
index cc3ad71117a5d34d268811adec3ddb72b372019d..8212648f2d8fb308f054ea49e2f94b9c70eb9250 100644 (file)
@@ -58,7 +58,9 @@
 // Re-exported extension traits for primitive types
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
+#[cfg(stage0)]
 pub use slice::SliceExt;
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
+#[cfg(stage0)]
 pub use str::StrExt;
index 4a7d7c410eb16eebb850da3bd1cb9becb67af717..74bb264cc679cc31c310cefade5b196cbd6881b8 100644 (file)
@@ -166,8 +166,6 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// Basic usage:
 ///
 /// ```
-/// #![feature(swap_nonoverlapping)]
-///
 /// use std::ptr;
 ///
 /// let mut x = [1, 2, 3, 4];
@@ -181,7 +179,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// assert_eq!(y, [1, 2, 9]);
 /// ```
 #[inline]
-#[unstable(feature = "swap_nonoverlapping", issue = "42818")]
+#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
 pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
     let x = x as *mut u8;
     let y = y as *mut u8;
@@ -2744,7 +2742,7 @@ pub unsafe fn as_mut(&mut self) -> &mut T {
     }
 
     /// Cast to a pointer of another type
-    #[unstable(feature = "nonnull_cast", issue = "47653")]
+    #[stable(feature = "nonnull_cast", since = "1.27.0")]
     pub fn cast<U>(self) -> NonNull<U> {
         unsafe {
             NonNull::new_unchecked(self.as_ptr() as *mut U)
index 0a22028da81f4b3293015033eb8c8a535fdd497a..cc42acd77aed1c29b6ed847b4cbc53e344d15fcb 100644 (file)
@@ -68,12 +68,15 @@ struct Repr<T> {
 // Extension traits
 //
 
+public_in_stage0! {
+{
 /// Extension methods for slices.
 #[unstable(feature = "core_slice_ext",
            reason = "stable interface provided by `impl [T]` in later crates",
            issue = "32110")]
 #[allow(missing_docs)] // documented elsewhere
-pub trait SliceExt {
+}
+trait SliceExt {
     type Item;
 
     #[stable(feature = "core", since = "1.6.0")]
@@ -86,7 +89,7 @@ pub trait SliceExt {
     fn split<P>(&self, pred: P) -> Split<Self::Item, P>
         where P: FnMut(&Self::Item) -> bool;
 
-    #[unstable(feature = "slice_rsplit", issue = "41020")]
+    #[stable(feature = "slice_rsplit", since = "1.27.0")]
     fn rsplit<P>(&self, pred: P) -> RSplit<Self::Item, P>
         where P: FnMut(&Self::Item) -> bool;
 
@@ -169,7 +172,7 @@ fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
     fn split_mut<P>(&mut self, pred: P) -> SplitMut<Self::Item, P>
         where P: FnMut(&Self::Item) -> bool;
 
-    #[unstable(feature = "slice_rsplit", issue = "41020")]
+    #[stable(feature = "slice_rsplit", since = "1.27.0")]
     fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<Self::Item, P>
         where P: FnMut(&Self::Item) -> bool;
 
@@ -223,7 +226,7 @@ unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
 
-    #[unstable(feature = "swap_with_slice", issue = "44030")]
+    #[stable(feature = "swap_with_slice", since = "1.27.0")]
     fn swap_with_slice(&mut self, src: &mut [Self::Item]);
 
     #[stable(feature = "sort_unstable", since = "1.20.0")]
@@ -238,7 +241,7 @@ fn sort_unstable_by<F>(&mut self, compare: F)
     fn sort_unstable_by_key<B, F>(&mut self, f: F)
         where F: FnMut(&Self::Item) -> B,
               B: Ord;
-}
+}}
 
 // Use macros to be generic over const/mut
 macro_rules! slice_offset {
@@ -755,6 +758,1475 @@ fn sort_unstable_by_key<B, F>(&mut self, mut f: F)
     }
 }
 
+// FIXME: remove (inline) this macro and the SliceExt trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_slice_ext", issue = "32110")]
+macro_rules! slice_core_methods { () => {
+    /// Returns the number of elements in the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let a = [1, 2, 3];
+    /// assert_eq!(a.len(), 3);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn len(&self) -> usize {
+        SliceExt::len(self)
+    }
+
+    /// Returns `true` if the slice has a length of 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let a = [1, 2, 3];
+    /// assert!(!a.is_empty());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        SliceExt::is_empty(self)
+    }
+
+    /// Returns the first element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&10), v.first());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(None, w.first());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn first(&self) -> Option<&T> {
+        SliceExt::first(self)
+    }
+
+    /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(first) = x.first_mut() {
+    ///     *first = 5;
+    /// }
+    /// assert_eq!(x, &[5, 1, 2]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn first_mut(&mut self) -> Option<&mut T> {
+        SliceExt::first_mut(self)
+    }
+
+    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first() {
+    ///     assert_eq!(first, &0);
+    ///     assert_eq!(elements, &[1, 2]);
+    /// }
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_first(&self) -> Option<(&T, &[T])> {
+        SliceExt::split_first(self)
+    }
+
+    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first_mut() {
+    ///     *first = 3;
+    ///     elements[0] = 4;
+    ///     elements[1] = 5;
+    /// }
+    /// assert_eq!(x, &[3, 4, 5]);
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+        SliceExt::split_first_mut(self)
+    }
+
+    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last() {
+    ///     assert_eq!(last, &2);
+    ///     assert_eq!(elements, &[0, 1]);
+    /// }
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_last(&self) -> Option<(&T, &[T])> {
+        SliceExt::split_last(self)
+
+    }
+
+    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last_mut() {
+    ///     *last = 3;
+    ///     elements[0] = 4;
+    ///     elements[1] = 5;
+    /// }
+    /// assert_eq!(x, &[4, 5, 3]);
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+        SliceExt::split_last_mut(self)
+    }
+
+    /// Returns the last element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&30), v.last());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(None, w.last());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn last(&self) -> Option<&T> {
+        SliceExt::last(self)
+    }
+
+    /// Returns a mutable pointer to the last item in the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(last) = x.last_mut() {
+    ///     *last = 10;
+    /// }
+    /// assert_eq!(x, &[0, 1, 10]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn last_mut(&mut self) -> Option<&mut T> {
+        SliceExt::last_mut(self)
+    }
+
+    /// Returns a reference to an element or subslice depending on the type of
+    /// index.
+    ///
+    /// - If given a position, returns a reference to the element at that
+    ///   position or `None` if out of bounds.
+    /// - If given a range, returns the subslice corresponding to that range,
+    ///   or `None` if out of bounds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&40), v.get(1));
+    /// assert_eq!(Some(&[10, 40][..]), v.get(0..2));
+    /// assert_eq!(None, v.get(3));
+    /// assert_eq!(None, v.get(0..4));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn get<I>(&self, index: I) -> Option<&I::Output>
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get(self, index)
+    }
+
+    /// Returns a mutable reference to an element or subslice depending on the
+    /// type of index (see [`get`]) or `None` if the index is out of bounds.
+    ///
+    /// [`get`]: #method.get
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(elem) = x.get_mut(1) {
+    ///     *elem = 42;
+    /// }
+    /// assert_eq!(x, &[0, 42, 2]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get_mut(self, index)
+    }
+
+    /// Returns a reference to an element or subslice, without doing bounds
+    /// checking.
+    ///
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`get`].
+    ///
+    /// [`get`]: #method.get
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    ///
+    /// unsafe {
+    ///     assert_eq!(x.get_unchecked(1), &2);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get_unchecked(self, index)
+    }
+
+    /// Returns a mutable reference to an element or subslice, without doing
+    /// bounds checking.
+    ///
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`get_mut`].
+    ///
+    /// [`get_mut`]: #method.get_mut
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    ///
+    /// unsafe {
+    ///     let elem = x.get_unchecked_mut(1);
+    ///     *elem = 13;
+    /// }
+    /// assert_eq!(x, &[1, 13, 4]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get_unchecked_mut(self, index)
+    }
+
+    /// Returns a raw pointer to the slice's buffer.
+    ///
+    /// The caller must ensure that the slice outlives the pointer this
+    /// function returns, or else it will end up pointing to garbage.
+    ///
+    /// Modifying the container referenced by this slice may cause its buffer
+    /// to be reallocated, which would also make any pointers to it invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    /// let x_ptr = x.as_ptr();
+    ///
+    /// unsafe {
+    ///     for i in 0..x.len() {
+    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize));
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn as_ptr(&self) -> *const T {
+        SliceExt::as_ptr(self)
+    }
+
+    /// Returns an unsafe mutable pointer to the slice's buffer.
+    ///
+    /// The caller must ensure that the slice outlives the pointer this
+    /// function returns, or else it will end up pointing to garbage.
+    ///
+    /// Modifying the container referenced by this slice may cause its buffer
+    /// to be reallocated, which would also make any pointers to it invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    /// let x_ptr = x.as_mut_ptr();
+    ///
+    /// unsafe {
+    ///     for i in 0..x.len() {
+    ///         *x_ptr.offset(i as isize) += 2;
+    ///     }
+    /// }
+    /// assert_eq!(x, &[3, 4, 6]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn as_mut_ptr(&mut self) -> *mut T {
+        SliceExt::as_mut_ptr(self)
+    }
+
+    /// Swaps two elements in the slice.
+    ///
+    /// # Arguments
+    ///
+    /// * a - The index of the first element
+    /// * b - The index of the second element
+    ///
+    /// # Panics
+    ///
+    /// Panics if `a` or `b` are out of bounds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = ["a", "b", "c", "d"];
+    /// v.swap(1, 3);
+    /// assert!(v == ["a", "d", "c", "b"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn swap(&mut self, a: usize, b: usize) {
+        SliceExt::swap(self, a, b)
+    }
+
+    /// Reverses the order of elements in the slice, in place.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [1, 2, 3];
+    /// v.reverse();
+    /// assert!(v == [3, 2, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn reverse(&mut self) {
+        SliceExt::reverse(self)
+    }
+
+    /// Returns an iterator over the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    /// let mut iterator = x.iter();
+    ///
+    /// assert_eq!(iterator.next(), Some(&1));
+    /// assert_eq!(iterator.next(), Some(&2));
+    /// assert_eq!(iterator.next(), Some(&4));
+    /// assert_eq!(iterator.next(), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn iter(&self) -> Iter<T> {
+        SliceExt::iter(self)
+    }
+
+    /// Returns an iterator that allows modifying each value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    /// for elem in x.iter_mut() {
+    ///     *elem += 2;
+    /// }
+    /// assert_eq!(x, &[3, 4, 6]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn iter_mut(&mut self) -> IterMut<T> {
+        SliceExt::iter_mut(self)
+    }
+
+    /// Returns an iterator over all contiguous windows of length
+    /// `size`. The windows overlap. If the slice is shorter than
+    /// `size`, the iterator returns no values.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = ['r', 'u', 's', 't'];
+    /// let mut iter = slice.windows(2);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
+    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
+    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If the slice is shorter than `size`:
+    ///
+    /// ```
+    /// let slice = ['f', 'o', 'o'];
+    /// let mut iter = slice.windows(4);
+    /// assert!(iter.next().is_none());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn windows(&self, size: usize) -> Windows<T> {
+        SliceExt::windows(self, size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a
+    /// time. The chunks are slices and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last chunk will
+    /// not have length `chunk_size`.
+    ///
+    /// See [`exact_chunks`] for a variant of this iterator that returns chunks
+    /// of always exactly `chunk_size` elements.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.chunks(2);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+    /// assert_eq!(iter.next().unwrap(), &['m']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`exact_chunks`]: #method.exact_chunks
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
+        SliceExt::chunks(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a
+    /// time. The chunks are slices and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last up to `chunk_size-1`
+    /// elements will be omitted.
+    ///
+    /// Due to each chunk having exactly `chunk_size` elements, the compiler
+    /// can often optimize the resulting code better than in the case of
+    /// [`chunks`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exact_chunks)]
+    ///
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.exact_chunks(2);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`chunks`]: #method.chunks
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    #[inline]
+    pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+        SliceExt::exact_chunks(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a time.
+    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last chunk will not
+    /// have length `chunk_size`.
+    ///
+    /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
+    /// of always exactly `chunk_size` elements.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// for chunk in v.chunks_mut(2) {
+    ///     for elem in chunk.iter_mut() {
+    ///         *elem += count;
+    ///     }
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[1, 1, 2, 2, 3]);
+    /// ```
+    ///
+    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
+        SliceExt::chunks_mut(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a time.
+    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last up to `chunk_size-1`
+    /// elements will be omitted.
+    ///
+    ///
+    /// Due to each chunk having exactly `chunk_size` elements, the compiler
+    /// can often optimize the resulting code better than in the case of
+    /// [`chunks_mut`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exact_chunks)]
+    ///
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// for chunk in v.exact_chunks_mut(2) {
+    ///     for elem in chunk.iter_mut() {
+    ///         *elem += count;
+    ///     }
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
+    /// ```
+    ///
+    /// [`chunks_mut`]: #method.chunks_mut
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    #[inline]
+    pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+        SliceExt::exact_chunks_mut(self, chunk_size)
+    }
+
+    /// Divides one slice into two at an index.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [1, 2, 3, 4, 5, 6];
+    ///
+    /// {
+    ///    let (left, right) = v.split_at(0);
+    ///    assert!(left == []);
+    ///    assert!(right == [1, 2, 3, 4, 5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.split_at(2);
+    ///     assert!(left == [1, 2]);
+    ///     assert!(right == [3, 4, 5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.split_at(6);
+    ///     assert!(left == [1, 2, 3, 4, 5, 6]);
+    ///     assert!(right == []);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
+        SliceExt::split_at(self, mid)
+    }
+
+    /// Divides one mutable slice into two at an index.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [1, 0, 3, 0, 5, 6];
+    /// // scoped to restrict the lifetime of the borrows
+    /// {
+    ///     let (left, right) = v.split_at_mut(2);
+    ///     assert!(left == [1, 0]);
+    ///     assert!(right == [3, 0, 5, 6]);
+    ///     left[1] = 2;
+    ///     right[1] = 4;
+    /// }
+    /// assert!(v == [1, 2, 3, 4, 5, 6]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
+        SliceExt::split_at_mut(self, mid)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = [10, 40, 33, 20];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If the first element is matched, an empty slice will be the first item
+    /// returned by the iterator. Similarly, if the last element in the slice
+    /// is matched, an empty slice will be the last item returned by the
+    /// iterator:
+    ///
+    /// ```
+    /// let slice = [10, 40, 33];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
+    /// assert_eq!(iter.next().unwrap(), &[]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If two matched elements are directly adjacent, an empty slice will be
+    /// present between them:
+    ///
+    /// ```
+    /// let slice = [10, 6, 33, 20];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10]);
+    /// assert_eq!(iter.next().unwrap(), &[]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split<F>(&self, pred: F) -> Split<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::split(self, pred)
+    }
+
+    /// Returns an iterator over mutable subslices separated by elements that
+    /// match `pred`. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.split_mut(|num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(v, [1, 40, 30, 1, 60, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::split_mut(self, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, starting at the end of the slice and working backwards.
+    /// The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = [11, 22, 33, 0, 44, 55];
+    /// let mut iter = slice.rsplit(|num| *num == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[44, 55]);
+    /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    ///
+    /// As with `split()`, if the first or last element is matched, an empty
+    /// slice will be the first (or last) item returned by the iterator.
+    ///
+    /// ```
+    /// let v = &[0, 1, 1, 2, 3, 5, 8];
+    /// let mut it = v.rsplit(|n| *n % 2 == 0);
+    /// assert_eq!(it.next().unwrap(), &[]);
+    /// assert_eq!(it.next().unwrap(), &[3, 5]);
+    /// assert_eq!(it.next().unwrap(), &[1, 1]);
+    /// assert_eq!(it.next().unwrap(), &[]);
+    /// assert_eq!(it.next(), None);
+    /// ```
+    #[stable(feature = "slice_rsplit", since = "1.27.0")]
+    #[inline]
+    pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplit(self, pred)
+    }
+
+    /// Returns an iterator over mutable subslices separated by elements that
+    /// match `pred`, starting at the end of the slice and working
+    /// backwards. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [100, 400, 300, 200, 600, 500];
+    ///
+    /// let mut count = 0;
+    /// for group in v.rsplit_mut(|num| *num % 3 == 0) {
+    ///     count += 1;
+    ///     group[0] = count;
+    /// }
+    /// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
+    /// ```
+    ///
+    #[stable(feature = "slice_rsplit", since = "1.27.0")]
+    #[inline]
+    pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplit_mut(self, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, limited to returning at most `n` items. The matched element is
+    /// not contained in the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
+    /// `[20, 60, 50]`):
+    ///
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.splitn(2, |num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::splitn(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, limited to returning at most `n` items. The matched element is
+    /// not contained in the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.splitn_mut(2, |num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(v, [1, 40, 30, 1, 60, 50]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::splitn_mut(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred` limited to returning at most `n` items. This starts at the end of
+    /// the slice and works backwards.  The matched element is not contained in
+    /// the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// Print the slice split once, starting from the end, by numbers divisible
+    /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`):
+    ///
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplitn(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred` limited to returning at most `n` items. This starts at the end of
+    /// the slice and works backwards. The matched element is not contained in
+    /// the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut s = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(s, [1, 40, 30, 20, 60, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplitn_mut(self, n, pred)
+    }
+
+    /// Returns `true` if the slice contains an element with the given value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.contains(&30));
+    /// assert!(!v.contains(&50));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn contains(&self, x: &T) -> bool
+        where T: PartialEq
+    {
+        SliceExt::contains(self, x)
+    }
+
+    /// Returns `true` if `needle` is a prefix of the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.starts_with(&[10]));
+    /// assert!(v.starts_with(&[10, 40]));
+    /// assert!(!v.starts_with(&[50]));
+    /// assert!(!v.starts_with(&[10, 50]));
+    /// ```
+    ///
+    /// Always returns `true` if `needle` is an empty slice:
+    ///
+    /// ```
+    /// let v = &[10, 40, 30];
+    /// assert!(v.starts_with(&[]));
+    /// let v: &[u8] = &[];
+    /// assert!(v.starts_with(&[]));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn starts_with(&self, needle: &[T]) -> bool
+        where T: PartialEq
+    {
+        SliceExt::starts_with(self, needle)
+    }
+
+    /// Returns `true` if `needle` is a suffix of the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.ends_with(&[30]));
+    /// assert!(v.ends_with(&[40, 30]));
+    /// assert!(!v.ends_with(&[50]));
+    /// assert!(!v.ends_with(&[50, 30]));
+    /// ```
+    ///
+    /// Always returns `true` if `needle` is an empty slice:
+    ///
+    /// ```
+    /// let v = &[10, 40, 30];
+    /// assert!(v.ends_with(&[]));
+    /// let v: &[u8] = &[];
+    /// assert!(v.ends_with(&[]));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn ends_with(&self, needle: &[T]) -> bool
+        where T: PartialEq
+    {
+        SliceExt::ends_with(self, needle)
+    }
+
+    /// Binary searches this sorted slice for a given element.
+    ///
+    /// If the value is found then `Ok` is returned, containing the
+    /// index of the matching element; if the value is not found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    ///
+    /// assert_eq!(s.binary_search(&13),  Ok(9));
+    /// assert_eq!(s.binary_search(&4),   Err(7));
+    /// assert_eq!(s.binary_search(&100), Err(13));
+    /// let r = s.binary_search(&1);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn binary_search(&self, x: &T) -> Result<usize, usize>
+        where T: Ord
+    {
+        SliceExt::binary_search(self, x)
+    }
+
+    /// Binary searches this sorted slice with a comparator function.
+    ///
+    /// The comparator function should implement an order consistent
+    /// with the sort order of the underlying slice, returning an
+    /// order code that indicates whether its argument is `Less`,
+    /// `Equal` or `Greater` the desired target.
+    ///
+    /// If a matching value is found then returns `Ok`, containing
+    /// the index for the matched element; if no match is found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    ///
+    /// let seek = 13;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
+    /// let seek = 4;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
+    /// let seek = 100;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
+    /// let seek = 1;
+    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
+        where F: FnMut(&'a T) -> Ordering
+    {
+        SliceExt::binary_search_by(self, f)
+    }
+
+    /// Binary searches this sorted slice with a key extraction function.
+    ///
+    /// Assumes that the slice is sorted by the key, for instance with
+    /// [`sort_by_key`] using the same key extraction function.
+    ///
+    /// If a matching value is found then returns `Ok`, containing the
+    /// index for the matched element; if no match is found then `Err`
+    /// is returned, containing the index where a matching element could
+    /// be inserted while maintaining sorted order.
+    ///
+    /// [`sort_by_key`]: #method.sort_by_key
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements in a slice of pairs sorted by
+    /// their second elements. The first is found, with a uniquely
+    /// determined position; the second and third are not found; the
+    /// fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
+    ///          (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
+    ///          (1, 21), (2, 34), (4, 55)];
+    ///
+    /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
+    /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
+    /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
+    /// let r = s.binary_search_by_key(&1, |&(a,b)| b);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
+    #[inline]
+    pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
+        where F: FnMut(&'a T) -> B,
+              B: Ord
+    {
+        SliceExt::binary_search_by_key(self, b, f)
+    }
+
+    /// Sorts the slice, but may not preserve the order of equal elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
+    /// which combines the fast average case of randomized quicksort with the fast worst case of
+    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
+    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
+    /// deterministic behavior.
+    ///
+    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [-5, 4, 1, -3, 2];
+    ///
+    /// v.sort_unstable();
+    /// assert!(v == [-5, -3, 1, 2, 4]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
+    #[inline]
+    pub fn sort_unstable(&mut self)
+        where T: Ord
+    {
+        SliceExt::sort_unstable(self);
+    }
+
+    /// Sorts the slice with a comparator function, but may not preserve the order of equal
+    /// elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
+    /// which combines the fast average case of randomized quicksort with the fast worst case of
+    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
+    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
+    /// deterministic behavior.
+    ///
+    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [5, 4, 1, 3, 2];
+    /// v.sort_unstable_by(|a, b| a.cmp(b));
+    /// assert!(v == [1, 2, 3, 4, 5]);
+    ///
+    /// // reverse sorting
+    /// v.sort_unstable_by(|a, b| b.cmp(a));
+    /// assert!(v == [5, 4, 3, 2, 1]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
+    #[inline]
+    pub fn sort_unstable_by<F>(&mut self, compare: F)
+        where F: FnMut(&T, &T) -> Ordering
+    {
+        SliceExt::sort_unstable_by(self, compare);
+    }
+
+    /// Sorts the slice with a key extraction function, but may not preserve the order of equal
+    /// elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
+    /// which combines the fast average case of randomized quicksort with the fast worst case of
+    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
+    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
+    /// deterministic behavior.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [-5i32, 4, 1, -3, 2];
+    ///
+    /// v.sort_unstable_by_key(|k| k.abs());
+    /// assert!(v == [1, 2, -3, 4, -5]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
+    #[inline]
+    pub fn sort_unstable_by_key<K, F>(&mut self, f: F)
+        where F: FnMut(&T) -> K, K: Ord
+    {
+        SliceExt::sort_unstable_by_key(self, f);
+    }
+
+    /// Rotates the slice in-place such that the first `mid` elements of the
+    /// slice move to the end while the last `self.len() - mid` elements move to
+    /// the front. After calling `rotate_left`, the element previously at index
+    /// `mid` will become the first element in the slice.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `mid` is greater than the length of the
+    /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
+    /// rotation.
+    ///
+    /// # Complexity
+    ///
+    /// Takes linear (in `self.len()`) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a.rotate_left(2);
+    /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
+    /// ```
+    ///
+    /// Rotating a subslice:
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a[1..5].rotate_left(1);
+    /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
+   /// ```
+    #[stable(feature = "slice_rotate", since = "1.26.0")]
+    pub fn rotate_left(&mut self, mid: usize) {
+        SliceExt::rotate_left(self, mid);
+    }
+
+    /// Rotates the slice in-place such that the first `self.len() - k`
+    /// elements of the slice move to the end while the last `k` elements move
+    /// to the front. After calling `rotate_right`, the element previously at
+    /// index `self.len() - k` will become the first element in the slice.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `k` is greater than the length of the
+    /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
+    /// rotation.
+    ///
+    /// # Complexity
+    ///
+    /// Takes linear (in `self.len()`) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a.rotate_right(2);
+    /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
+    /// ```
+    ///
+    /// Rotate a subslice:
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a[1..5].rotate_right(1);
+    /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
+    /// ```
+    #[stable(feature = "slice_rotate", since = "1.26.0")]
+    pub fn rotate_right(&mut self, k: usize) {
+        SliceExt::rotate_right(self, k);
+    }
+
+    /// Copies the elements from `src` into `self`.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// If `src` implements `Copy`, it can be more performant to use
+    /// [`copy_from_slice`].
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Examples
+    ///
+    /// Cloning two elements from a slice into another:
+    ///
+    /// ```
+    /// let src = [1, 2, 3, 4];
+    /// let mut dst = [0, 0];
+    ///
+    /// dst.clone_from_slice(&src[2..]);
+    ///
+    /// assert_eq!(src, [1, 2, 3, 4]);
+    /// assert_eq!(dst, [3, 4]);
+    /// ```
+    ///
+    /// Rust enforces that there can only be one mutable reference with no
+    /// immutable references to a particular piece of data in a particular
+    /// scope. Because of this, attempting to use `clone_from_slice` on a
+    /// single slice will result in a compile failure:
+    ///
+    /// ```compile_fail
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// slice[..2].clone_from_slice(&slice[3..]); // compile fail!
+    /// ```
+    ///
+    /// To work around this, we can use [`split_at_mut`] to create two distinct
+    /// sub-slices from a slice:
+    ///
+    /// ```
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// {
+    ///     let (left, right) = slice.split_at_mut(2);
+    ///     left.clone_from_slice(&right[1..]);
+    /// }
+    ///
+    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
+    /// ```
+    ///
+    /// [`copy_from_slice`]: #method.copy_from_slice
+    /// [`split_at_mut`]: #method.split_at_mut
+    #[stable(feature = "clone_from_slice", since = "1.7.0")]
+    pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
+        SliceExt::clone_from_slice(self, src)
+    }
+
+    /// Copies all elements from `src` into `self`, using a memcpy.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// If `src` does not implement `Copy`, use [`clone_from_slice`].
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Examples
+    ///
+    /// Copying two elements from a slice into another:
+    ///
+    /// ```
+    /// let src = [1, 2, 3, 4];
+    /// let mut dst = [0, 0];
+    ///
+    /// dst.copy_from_slice(&src[2..]);
+    ///
+    /// assert_eq!(src, [1, 2, 3, 4]);
+    /// assert_eq!(dst, [3, 4]);
+    /// ```
+    ///
+    /// Rust enforces that there can only be one mutable reference with no
+    /// immutable references to a particular piece of data in a particular
+    /// scope. Because of this, attempting to use `copy_from_slice` on a
+    /// single slice will result in a compile failure:
+    ///
+    /// ```compile_fail
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// slice[..2].copy_from_slice(&slice[3..]); // compile fail!
+    /// ```
+    ///
+    /// To work around this, we can use [`split_at_mut`] to create two distinct
+    /// sub-slices from a slice:
+    ///
+    /// ```
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// {
+    ///     let (left, right) = slice.split_at_mut(2);
+    ///     left.copy_from_slice(&right[1..]);
+    /// }
+    ///
+    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
+    /// ```
+    ///
+    /// [`clone_from_slice`]: #method.clone_from_slice
+    /// [`split_at_mut`]: #method.split_at_mut
+    #[stable(feature = "copy_from_slice", since = "1.9.0")]
+    pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
+        SliceExt::copy_from_slice(self, src)
+    }
+
+    /// Swaps all elements in `self` with those in `other`.
+    ///
+    /// The length of `other` must be the same as `self`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Example
+    ///
+    /// Swapping two elements across slices:
+    ///
+    /// ```
+    /// let mut slice1 = [0, 0];
+    /// let mut slice2 = [1, 2, 3, 4];
+    ///
+    /// slice1.swap_with_slice(&mut slice2[2..]);
+    ///
+    /// assert_eq!(slice1, [3, 4]);
+    /// assert_eq!(slice2, [1, 2, 0, 0]);
+    /// ```
+    ///
+    /// Rust enforces that there can only be one mutable reference to a
+    /// particular piece of data in a particular scope. Because of this,
+    /// attempting to use `swap_with_slice` on a single slice will result in
+    /// a compile failure:
+    ///
+    /// ```compile_fail
+    /// let mut slice = [1, 2, 3, 4, 5];
+    /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail!
+    /// ```
+    ///
+    /// To work around this, we can use [`split_at_mut`] to create two distinct
+    /// mutable sub-slices from a slice:
+    ///
+    /// ```
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// {
+    ///     let (left, right) = slice.split_at_mut(2);
+    ///     left.swap_with_slice(&mut right[1..]);
+    /// }
+    ///
+    /// assert_eq!(slice, [4, 5, 3, 1, 2]);
+    /// ```
+    ///
+    /// [`split_at_mut`]: #method.split_at_mut
+    #[stable(feature = "swap_with_slice", since = "1.27.0")]
+    pub fn swap_with_slice(&mut self, other: &mut [T]) {
+        SliceExt::swap_with_slice(self, other)
+    }
+}}
+
+#[lang = "slice"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl<T> [T] {
+    slice_core_methods!();
+}
+
+// FIXME: remove (inline) this macro
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_slice_ext", issue = "32110")]
+macro_rules! slice_u8_core_methods { () => {
+    /// Checks if all bytes in this slice are within the ASCII range.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        self.iter().all(|b| b.is_ascii())
+    }
+
+    /// Checks that two slices are an ASCII case-insensitive match.
+    ///
+    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+    /// but without allocating and copying temporaries.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
+        self.len() == other.len() &&
+            self.iter().zip(other).all(|(a, b)| {
+                a.eq_ignore_ascii_case(b)
+            })
+    }
+
+    /// Converts this slice to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_uppercase();
+        }
+    }
+
+    /// Converts this slice to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_lowercase();
+        }
+    }
+}}
+
+#[lang = "slice_u8"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl [u8] {
+    slice_u8_core_methods!();
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::Index<I> for [T]
@@ -1840,13 +3312,13 @@ impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
 ///
 /// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
 /// [slices]: ../../std/primitive.slice.html
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 #[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
 pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool {
     inner: Split<'a, T, P>
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("RSplit")
@@ -1856,7 +3328,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
     type Item = &'a [T];
 
@@ -1871,7 +3343,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -1879,7 +3351,7 @@ fn next_back(&mut self) -> Option<&'a [T]> {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn finish(&mut self) -> Option<&'a [T]> {
@@ -1887,7 +3359,7 @@ fn finish(&mut self) -> Option<&'a [T]> {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
 
 /// An iterator over the subslices of the vector which are separated
@@ -1897,12 +3369,12 @@ impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
 ///
 /// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
 /// [slices]: ../../std/primitive.slice.html
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
     inner: SplitMut<'a, T, P>
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("RSplitMut")
@@ -1912,7 +3384,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn finish(&mut self) -> Option<&'a mut [T]> {
@@ -1920,7 +3392,7 @@ fn finish(&mut self) -> Option<&'a mut [T]> {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     type Item = &'a mut [T];
 
@@ -1935,7 +3407,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
     P: FnMut(&T) -> bool,
 {
@@ -1945,7 +3417,7 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
     }
 }
 
-#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
 impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
 
 /// An private iterator over subslices separated by elements that
index f1fe23092de93924f2c1549758bcb84462cfc08b..b39d9feb35b7e3294be2b3c50a14afe7ddf72c39 100644 (file)
@@ -2100,31 +2100,28 @@ unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
         fn index(self, slice: &str) -> &Self::Output {
             assert!(self.end != usize::max_value(),
                 "attempted to index str up to maximum usize");
-            let end = self.end + 1;
-            self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
+            (..self.end+1).index(slice)
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
             assert!(self.end != usize::max_value(),
                 "attempted to index str up to maximum usize");
-            if slice.is_char_boundary(self.end) {
-                unsafe { self.get_unchecked_mut(slice) }
-            } else {
-                super::slice_error_fail(slice, 0, self.end + 1)
-            }
+            (..self.end+1).index_mut(slice)
         }
     }
 
 }
 
-
+public_in_stage0! {
+{
 /// Methods for string slices
 #[allow(missing_docs)]
 #[doc(hidden)]
 #[unstable(feature = "core_str_ext",
            reason = "stable interface provided by `impl str` in later crates",
            issue = "32110")]
-pub trait StrExt {
+}
+trait StrExt {
     // NB there are no docs here are they're all located on the StrExt trait in
     // liballoc, not here.
 
@@ -2218,17 +2215,13 @@ fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
     fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
     #[stable(feature = "split_whitespace", since = "1.1.0")]
     fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
-    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
-    fn is_whitespace(&self) -> bool;
-    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
-    fn is_alphanumeric(&self) -> bool;
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim(&self) -> &str;
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_left(&self) -> &str;
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_right(&self) -> &str;
-}
+}}
 
 // truncate `&str` to length at most equal to `max`
 // return `true` if it were truncated, and the new str.
@@ -2554,16 +2547,6 @@ fn split_whitespace(&self) -> SplitWhitespace {
         SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
     }
 
-    #[inline]
-    fn is_whitespace(&self) -> bool {
-        self.chars().all(|c| c.is_whitespace())
-    }
-
-    #[inline]
-    fn is_alphanumeric(&self) -> bool {
-        self.chars().all(|c| c.is_alphanumeric())
-    }
-
     #[inline]
     fn trim(&self) -> &str {
         self.trim_matches(|c: char| c.is_whitespace())
@@ -2580,88 +2563,1836 @@ fn trim_right(&self) -> &str {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRef<[u8]> for str {
+// FIXME: remove (inline) this macro and the SliceExt trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_str_ext", issue = "32110")]
+macro_rules! str_core_methods { () => {
+    /// Returns the length of `self`.
+    ///
+    /// This length is in bytes, not [`char`]s or graphemes. In other words,
+    /// it may not be what a human considers the length of the string.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let len = "foo".len();
+    /// assert_eq!(3, len);
+    ///
+    /// let len = "ƒoo".len(); // fancy f!
+    /// assert_eq!(4, len);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    fn as_ref(&self) -> &[u8] {
-        self.as_bytes()
+    pub fn len(&self) -> usize {
+        StrExt::len(self)
     }
-}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Default for &'a str {
-    /// Creates an empty str
-    fn default() -> &'a str { "" }
-}
+    /// Returns `true` if `self` has a length of zero bytes.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "";
+    /// assert!(s.is_empty());
+    ///
+    /// let s = "not empty";
+    /// assert!(!s.is_empty());
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn is_empty(&self) -> bool {
+        StrExt::is_empty(self)
+    }
 
-/// An iterator over the non-whitespace substrings of a string,
-/// separated by any amount of whitespace.
-///
-/// This struct is created by the [`split_whitespace`] method on [`str`].
-/// See its documentation for more.
-///
-/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
-/// [`str`]: ../../std/primitive.str.html
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-#[derive(Clone, Debug)]
-pub struct SplitWhitespace<'a> {
-    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
-}
+    /// Checks that `index`-th byte lies at the start and/or end of a
+    /// UTF-8 code point sequence.
+    ///
+    /// The start and end of the string (when `index == self.len()`) are
+    /// considered to be
+    /// boundaries.
+    ///
+    /// Returns `false` if `index` is greater than `self.len()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert!(s.is_char_boundary(0));
+    /// // start of `老`
+    /// assert!(s.is_char_boundary(6));
+    /// assert!(s.is_char_boundary(s.len()));
+    ///
+    /// // second byte of `ö`
+    /// assert!(!s.is_char_boundary(2));
+    ///
+    /// // third byte of `老`
+    /// assert!(!s.is_char_boundary(8));
+    /// ```
+    #[stable(feature = "is_char_boundary", since = "1.9.0")]
+    #[inline]
+    pub fn is_char_boundary(&self, index: usize) -> bool {
+        StrExt::is_char_boundary(self, index)
+    }
 
-#[derive(Clone)]
-struct IsWhitespace;
+    /// Converts a string slice to a byte slice. To convert the byte slice back
+    /// into a string slice, use the [`str::from_utf8`] function.
+    ///
+    /// [`str::from_utf8`]: ./str/fn.from_utf8.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bytes = "bors".as_bytes();
+    /// assert_eq!(b"bors", bytes);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline(always)]
+    pub fn as_bytes(&self) -> &[u8] {
+        StrExt::as_bytes(self)
+    }
 
-impl FnOnce<(char, )> for IsWhitespace {
-    type Output = bool;
+    /// Converts a mutable string slice to a mutable byte slice. To convert the
+    /// mutable byte slice back into a mutable string slice, use the
+    /// [`str::from_utf8_mut`] function.
+    ///
+    /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = String::from("Hello");
+    /// let bytes = unsafe { s.as_bytes_mut() };
+    ///
+    /// assert_eq!(b"Hello", bytes);
+    /// ```
+    ///
+    /// Mutability:
+    ///
+    /// ```
+    /// let mut s = String::from("🗻∈🌏");
+    ///
+    /// unsafe {
+    ///     let bytes = s.as_bytes_mut();
+    ///
+    ///     bytes[0] = 0xF0;
+    ///     bytes[1] = 0x9F;
+    ///     bytes[2] = 0x8D;
+    ///     bytes[3] = 0x94;
+    /// }
+    ///
+    /// assert_eq!("🍔∈🌏", s);
+    /// ```
+    #[stable(feature = "str_mut_extras", since = "1.20.0")]
+    #[inline(always)]
+    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+        StrExt::as_bytes_mut(self)
+    }
 
+    /// Converts a string slice to a raw pointer.
+    ///
+    /// As string slices are a slice of bytes, the raw pointer points to a
+    /// [`u8`]. This pointer will be pointing to the first byte of the string
+    /// slice.
+    ///
+    /// [`u8`]: primitive.u8.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "Hello";
+    /// let ptr = s.as_ptr();
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
-        self.call_mut(arg)
+    pub fn as_ptr(&self) -> *const u8 {
+        StrExt::as_ptr(self)
     }
-}
 
-impl FnMut<(char, )> for IsWhitespace {
+    /// Returns a subslice of `str`.
+    ///
+    /// This is the non-panicking alternative to indexing the `str`. Returns
+    /// [`None`] whenever equivalent indexing operation would panic.
+    ///
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = String::from("🗻∈🌏");
+    ///
+    /// assert_eq!(Some("🗻"), v.get(0..4));
+    ///
+    /// // indices not on UTF-8 sequence boundaries
+    /// assert!(v.get(1..).is_none());
+    /// assert!(v.get(..8).is_none());
+    ///
+    /// // out of bounds
+    /// assert!(v.get(..42).is_none());
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
-        arg.0.is_whitespace()
+    pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
+        StrExt::get(self, i)
     }
-}
-
-#[derive(Clone)]
-struct IsNotEmpty;
 
-impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
-    type Output = bool;
+    /// Returns a mutable subslice of `str`.
+    ///
+    /// This is the non-panicking alternative to indexing the `str`. Returns
+    /// [`None`] whenever equivalent indexing operation would panic.
+    ///
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = String::from("hello");
+    /// // correct length
+    /// assert!(v.get_mut(0..5).is_some());
+    /// // out of bounds
+    /// assert!(v.get_mut(..42).is_none());
+    /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v));
+    ///
+    /// assert_eq!("hello", v);
+    /// {
+    ///     let s = v.get_mut(0..2);
+    ///     let s = s.map(|s| {
+    ///         s.make_ascii_uppercase();
+    ///         &*s
+    ///     });
+    ///     assert_eq!(Some("HE"), s);
+    /// }
+    /// assert_eq!("HEllo", v);
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
+    #[inline]
+    pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
+        StrExt::get_mut(self, i)
+    }
 
+    /// Returns a unchecked subslice of `str`.
+    ///
+    /// This is the unchecked alternative to indexing the `str`.
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that these preconditions are
+    /// satisfied:
+    ///
+    /// * The starting index must come before the ending index;
+    /// * Indexes must be within bounds of the original slice;
+    /// * Indexes must lie on UTF-8 sequence boundaries.
+    ///
+    /// Failing that, the returned string slice may reference invalid memory or
+    /// violate the invariants communicated by the `str` type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = "🗻∈🌏";
+    /// unsafe {
+    ///     assert_eq!("🗻", v.get_unchecked(0..4));
+    ///     assert_eq!("∈", v.get_unchecked(4..7));
+    ///     assert_eq!("🌏", v.get_unchecked(7..11));
+    /// }
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
-        self.call_mut(arg)
+    pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
+        StrExt::get_unchecked(self, i)
     }
-}
 
-impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
+    /// Returns a mutable, unchecked subslice of `str`.
+    ///
+    /// This is the unchecked alternative to indexing the `str`.
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that these preconditions are
+    /// satisfied:
+    ///
+    /// * The starting index must come before the ending index;
+    /// * Indexes must be within bounds of the original slice;
+    /// * Indexes must lie on UTF-8 sequence boundaries.
+    ///
+    /// Failing that, the returned string slice may reference invalid memory or
+    /// violate the invariants communicated by the `str` type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = String::from("🗻∈🌏");
+    /// unsafe {
+    ///     assert_eq!("🗻", v.get_unchecked_mut(0..4));
+    ///     assert_eq!("∈", v.get_unchecked_mut(4..7));
+    ///     assert_eq!("🌏", v.get_unchecked_mut(7..11));
+    /// }
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
-        !arg.0.is_empty()
+    pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
+        StrExt::get_unchecked_mut(self, i)
     }
-}
 
+    /// Creates a string slice from another string slice, bypassing safety
+    /// checks.
+    ///
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`str`] and [`Index`].
+    ///
+    /// [`str`]: primitive.str.html
+    /// [`Index`]: ops/trait.Index.html
+    ///
+    /// This new slice goes from `begin` to `end`, including `begin` but
+    /// excluding `end`.
+    ///
+    /// To get a mutable string slice instead, see the
+    /// [`slice_mut_unchecked`] method.
+    ///
+    /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that three preconditions are
+    /// satisfied:
+    ///
+    /// * `begin` must come before `end`.
+    /// * `begin` and `end` must be byte positions within the string slice.
+    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// unsafe {
+    ///     assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21));
+    /// }
+    ///
+    /// let s = "Hello, world!";
+    ///
+    /// unsafe {
+    ///     assert_eq!("world", s.slice_unchecked(7, 12));
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
+        StrExt::slice_unchecked(self, begin, end)
+    }
 
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-impl<'a> Iterator for SplitWhitespace<'a> {
-    type Item = &'a str;
+    /// Creates a string slice from another string slice, bypassing safety
+    /// checks.
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`str`] and [`IndexMut`].
+    ///
+    /// [`str`]: primitive.str.html
+    /// [`IndexMut`]: ops/trait.IndexMut.html
+    ///
+    /// This new slice goes from `begin` to `end`, including `begin` but
+    /// excluding `end`.
+    ///
+    /// To get an immutable string slice instead, see the
+    /// [`slice_unchecked`] method.
+    ///
+    /// [`slice_unchecked`]: #method.slice_unchecked
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that three preconditions are
+    /// satisfied:
+    ///
+    /// * `begin` must come before `end`.
+    /// * `begin` and `end` must be byte positions within the string slice.
+    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
+    #[stable(feature = "str_slice_mut", since = "1.5.0")]
+    #[inline]
+    pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
+        StrExt::slice_mut_unchecked(self, begin, end)
+    }
 
-    fn next(&mut self) -> Option<&'a str> {
-        self.inner.next()
+    /// Divide one string slice into two at an index.
+    ///
+    /// The argument, `mid`, should be a byte offset from the start of the
+    /// string. It must also be on the boundary of a UTF-8 code point.
+    ///
+    /// The two slices returned go from the start of the string slice to `mid`,
+    /// and from `mid` to the end of the string slice.
+    ///
+    /// To get mutable string slices instead, see the [`split_at_mut`]
+    /// method.
+    ///
+    /// [`split_at_mut`]: #method.split_at_mut
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
+    /// beyond the last code point of the string slice.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "Per Martin-Löf";
+    ///
+    /// let (first, last) = s.split_at(3);
+    ///
+    /// assert_eq!("Per", first);
+    /// assert_eq!(" Martin-Löf", last);
+    /// ```
+    #[inline]
+    #[stable(feature = "str_split_at", since = "1.4.0")]
+    pub fn split_at(&self, mid: usize) -> (&str, &str) {
+        StrExt::split_at(self, mid)
     }
-}
 
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
-    fn next_back(&mut self) -> Option<&'a str> {
-        self.inner.next_back()
+    /// Divide one mutable string slice into two at an index.
+    ///
+    /// The argument, `mid`, should be a byte offset from the start of the
+    /// string. It must also be on the boundary of a UTF-8 code point.
+    ///
+    /// The two slices returned go from the start of the string slice to `mid`,
+    /// and from `mid` to the end of the string slice.
+    ///
+    /// To get immutable string slices instead, see the [`split_at`] method.
+    ///
+    /// [`split_at`]: #method.split_at
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
+    /// beyond the last code point of the string slice.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = "Per Martin-Löf".to_string();
+    /// {
+    ///     let (first, last) = s.split_at_mut(3);
+    ///     first.make_ascii_uppercase();
+    ///     assert_eq!("PER", first);
+    ///     assert_eq!(" Martin-Löf", last);
+    /// }
+    /// assert_eq!("PER Martin-Löf", s);
+    /// ```
+    #[inline]
+    #[stable(feature = "str_split_at", since = "1.4.0")]
+    pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
+        StrExt::split_at_mut(self, mid)
     }
-}
 
-#[stable(feature = "fused", since = "1.26.0")]
-impl<'a> FusedIterator for SplitWhitespace<'a> {}
+    /// Returns an iterator over the [`char`]s of a string slice.
+    ///
+    /// As a string slice consists of valid UTF-8, we can iterate through a
+    /// string slice by [`char`]. This method returns such an iterator.
+    ///
+    /// It's important to remember that [`char`] represents a Unicode Scalar
+    /// Value, and may not match your idea of what a 'character' is. Iteration
+    /// over grapheme clusters may be what you actually want.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let word = "goodbye";
+    ///
+    /// let count = word.chars().count();
+    /// assert_eq!(7, count);
+    ///
+    /// let mut chars = word.chars();
+    ///
+    /// assert_eq!(Some('g'), chars.next());
+    /// assert_eq!(Some('o'), chars.next());
+    /// assert_eq!(Some('o'), chars.next());
+    /// assert_eq!(Some('d'), chars.next());
+    /// assert_eq!(Some('b'), chars.next());
+    /// assert_eq!(Some('y'), chars.next());
+    /// assert_eq!(Some('e'), chars.next());
+    ///
+    /// assert_eq!(None, chars.next());
+    /// ```
+    ///
+    /// Remember, [`char`]s may not match your human intuition about characters:
+    ///
+    /// ```
+    /// let y = "y̆";
+    ///
+    /// let mut chars = y.chars();
+    ///
+    /// assert_eq!(Some('y'), chars.next()); // not 'y̆'
+    /// assert_eq!(Some('\u{0306}'), chars.next());
+    ///
+    /// assert_eq!(None, chars.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn chars(&self) -> Chars {
+        StrExt::chars(self)
+    }
+    /// Returns an iterator over the [`char`]s of a string slice, and their
+    /// positions.
+    ///
+    /// As a string slice consists of valid UTF-8, we can iterate through a
+    /// string slice by [`char`]. This method returns an iterator of both
+    /// these [`char`]s, as well as their byte positions.
+    ///
+    /// The iterator yields tuples. The position is first, the [`char`] is
+    /// second.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let word = "goodbye";
+    ///
+    /// let count = word.char_indices().count();
+    /// assert_eq!(7, count);
+    ///
+    /// let mut char_indices = word.char_indices();
+    ///
+    /// assert_eq!(Some((0, 'g')), char_indices.next());
+    /// assert_eq!(Some((1, 'o')), char_indices.next());
+    /// assert_eq!(Some((2, 'o')), char_indices.next());
+    /// assert_eq!(Some((3, 'd')), char_indices.next());
+    /// assert_eq!(Some((4, 'b')), char_indices.next());
+    /// assert_eq!(Some((5, 'y')), char_indices.next());
+    /// assert_eq!(Some((6, 'e')), char_indices.next());
+    ///
+    /// assert_eq!(None, char_indices.next());
+    /// ```
+    ///
+    /// Remember, [`char`]s may not match your human intuition about characters:
+    ///
+    /// ```
+    /// let yes = "y̆es";
+    ///
+    /// let mut char_indices = yes.char_indices();
+    ///
+    /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
+    /// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
+    ///
+    /// // note the 3 here - the last character took up two bytes
+    /// assert_eq!(Some((3, 'e')), char_indices.next());
+    /// assert_eq!(Some((4, 's')), char_indices.next());
+    ///
+    /// assert_eq!(None, char_indices.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn char_indices(&self) -> CharIndices {
+        StrExt::char_indices(self)
+    }
+
+    /// An iterator over the bytes of a string slice.
+    ///
+    /// As a string slice consists of a sequence of bytes, we can iterate
+    /// through a string slice by byte. This method returns such an iterator.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut bytes = "bors".bytes();
+    ///
+    /// assert_eq!(Some(b'b'), bytes.next());
+    /// assert_eq!(Some(b'o'), bytes.next());
+    /// assert_eq!(Some(b'r'), bytes.next());
+    /// assert_eq!(Some(b's'), bytes.next());
+    ///
+    /// assert_eq!(None, bytes.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn bytes(&self) -> Bytes {
+        StrExt::bytes(self)
+    }
+
+    /// Split a string slice by whitespace.
+    ///
+    /// The iterator returned will return string slices that are sub-slices of
+    /// the original string slice, separated by any amount of whitespace.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut iter = "A few words".split_whitespace();
+    ///
+    /// assert_eq!(Some("A"), iter.next());
+    /// assert_eq!(Some("few"), iter.next());
+    /// assert_eq!(Some("words"), iter.next());
+    ///
+    /// assert_eq!(None, iter.next());
+    /// ```
+    ///
+    /// All kinds of whitespace are considered:
+    ///
+    /// ```
+    /// let mut iter = " Mary   had\ta\u{2009}little  \n\t lamb".split_whitespace();
+    /// assert_eq!(Some("Mary"), iter.next());
+    /// assert_eq!(Some("had"), iter.next());
+    /// assert_eq!(Some("a"), iter.next());
+    /// assert_eq!(Some("little"), iter.next());
+    /// assert_eq!(Some("lamb"), iter.next());
+    ///
+    /// assert_eq!(None, iter.next());
+    /// ```
+    #[stable(feature = "split_whitespace", since = "1.1.0")]
+    #[inline]
+    pub fn split_whitespace(&self) -> SplitWhitespace {
+        StrExt::split_whitespace(self)
+    }
+
+    /// An iterator over the lines of a string, as string slices.
+    ///
+    /// Lines are ended with either a newline (`\n`) or a carriage return with
+    /// a line feed (`\r\n`).
+    ///
+    /// The final line ending is optional.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let text = "foo\r\nbar\n\nbaz\n";
+    /// let mut lines = text.lines();
+    ///
+    /// assert_eq!(Some("foo"), lines.next());
+    /// assert_eq!(Some("bar"), lines.next());
+    /// assert_eq!(Some(""), lines.next());
+    /// assert_eq!(Some("baz"), lines.next());
+    ///
+    /// assert_eq!(None, lines.next());
+    /// ```
+    ///
+    /// The final line ending isn't required:
+    ///
+    /// ```
+    /// let text = "foo\nbar\n\r\nbaz";
+    /// let mut lines = text.lines();
+    ///
+    /// assert_eq!(Some("foo"), lines.next());
+    /// assert_eq!(Some("bar"), lines.next());
+    /// assert_eq!(Some(""), lines.next());
+    /// assert_eq!(Some("baz"), lines.next());
+    ///
+    /// assert_eq!(None, lines.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn lines(&self) -> Lines {
+        StrExt::lines(self)
+    }
+
+    /// An iterator over the lines of a string.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")]
+    #[inline]
+    #[allow(deprecated)]
+    pub fn lines_any(&self) -> LinesAny {
+        StrExt::lines_any(self)
+    }
+
+    /// Returns an iterator of `u16` over the string encoded as UTF-16.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let text = "Zażółć gęślą jaźń";
+    ///
+    /// let utf8_len = text.len();
+    /// let utf16_len = text.encode_utf16().count();
+    ///
+    /// assert!(utf16_len <= utf8_len);
+    /// ```
+    #[stable(feature = "encode_utf16", since = "1.8.0")]
+    pub fn encode_utf16(&self) -> EncodeUtf16 {
+        EncodeUtf16::new(self)
+    }
+
+    /// Returns `true` if the given pattern matches a sub-slice of
+    /// this string slice.
+    ///
+    /// Returns `false` if it does not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bananas = "bananas";
+    ///
+    /// assert!(bananas.contains("nana"));
+    /// assert!(!bananas.contains("apples"));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        StrExt::contains(self, pat)
+    }
+
+    /// Returns `true` if the given pattern matches a prefix of this
+    /// string slice.
+    ///
+    /// Returns `false` if it does not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bananas = "bananas";
+    ///
+    /// assert!(bananas.starts_with("bana"));
+    /// assert!(!bananas.starts_with("nana"));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        StrExt::starts_with(self, pat)
+    }
+
+    /// Returns `true` if the given pattern matches a suffix of this
+    /// string slice.
+    ///
+    /// Returns `false` if it does not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bananas = "bananas";
+    ///
+    /// assert!(bananas.ends_with("anas"));
+    /// assert!(!bananas.ends_with("nana"));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::ends_with(self, pat)
+    }
+
+    /// Returns the byte index of the first character of this string slice that
+    /// matches the pattern.
+    ///
+    /// Returns [`None`] if the pattern doesn't match.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.find('L'), Some(0));
+    /// assert_eq!(s.find('é'), Some(14));
+    /// assert_eq!(s.find("Léopard"), Some(13));
+    /// ```
+    ///
+    /// More complex patterns using point-free style and closures:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.find(char::is_whitespace), Some(5));
+    /// assert_eq!(s.find(char::is_lowercase), Some(1));
+    /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1));
+    /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4));
+    /// ```
+    ///
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// let x: &[_] = &['1', '2'];
+    ///
+    /// assert_eq!(s.find(x), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
+        StrExt::find(self, pat)
+    }
+
+    /// Returns the byte index of the last character of this string slice that
+    /// matches the pattern.
+    ///
+    /// Returns [`None`] if the pattern doesn't match.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.rfind('L'), Some(13));
+    /// assert_eq!(s.rfind('é'), Some(14));
+    /// ```
+    ///
+    /// More complex patterns with closures:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.rfind(char::is_whitespace), Some(12));
+    /// assert_eq!(s.rfind(char::is_lowercase), Some(20));
+    /// ```
+    ///
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// let x: &[_] = &['1', '2'];
+    ///
+    /// assert_eq!(s.rfind(x), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rfind(self, pat)
+    }
+
+    /// An iterator over substrings of this string slice, separated by
+    /// characters matched by a pattern.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rsplit`] method can be used.
+    ///
+    /// [`char`]: primitive.char.html
+    /// [`rsplit`]: #method.rsplit
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+    ///
+    /// let v: Vec<&str> = "".split('X').collect();
+    /// assert_eq!(v, [""]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
+    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
+    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
+    ///
+    /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
+    ///
+    /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
+    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
+    /// ```
+    ///
+    /// If a string contains multiple contiguous separators, you will end up
+    /// with empty strings in the output:
+    ///
+    /// ```
+    /// let x = "||||a||b|c".to_string();
+    /// let d: Vec<_> = x.split('|').collect();
+    ///
+    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+    /// ```
+    ///
+    /// Contiguous separators are separated by the empty string.
+    ///
+    /// ```
+    /// let x = "(///)".to_string();
+    /// let d: Vec<_> = x.split('/').collect();
+    ///
+    /// assert_eq!(d, &["(", "", "", ")"]);
+    /// ```
+    ///
+    /// Separators at the start or end of a string are neighbored
+    /// by empty strings.
+    ///
+    /// ```
+    /// let d: Vec<_> = "010".split("0").collect();
+    /// assert_eq!(d, &["", "1", ""]);
+    /// ```
+    ///
+    /// When the empty string is used as a separator, it separates
+    /// every character in the string, along with the beginning
+    /// and end of the string.
+    ///
+    /// ```
+    /// let f: Vec<_> = "rust".split("").collect();
+    /// assert_eq!(f, &["", "r", "u", "s", "t", ""]);
+    /// ```
+    ///
+    /// Contiguous separators can lead to possibly surprising behavior
+    /// when whitespace is used as the separator. This code is correct:
+    ///
+    /// ```
+    /// let x = "    a  b c".to_string();
+    /// let d: Vec<_> = x.split(' ').collect();
+    ///
+    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+    /// ```
+    ///
+    /// It does _not_ give you:
+    ///
+    /// ```,ignore
+    /// assert_eq!(d, &["a", "b", "c"]);
+    /// ```
+    ///
+    /// Use [`split_whitespace`] for this behavior.
+    ///
+    /// [`split_whitespace`]: #method.split_whitespace
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
+        StrExt::split(self, pat)
+    }
+
+    /// An iterator over substrings of the given string slice, separated by
+    /// characters matched by a pattern and yielded in reverse order.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// For iterating from the front, the [`split`] method can be used.
+    ///
+    /// [`split`]: #method.split
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
+    ///
+    /// let v: Vec<&str> = "".rsplit('X').collect();
+    /// assert_eq!(v, [""]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
+    /// assert_eq!(v, ["leopard", "tiger", "", "lion"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["ghi", "def", "abc"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rsplit(self, pat)
+    }
+
+    /// An iterator over substrings of the given string slice, separated by
+    /// characters matched by a pattern.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// Equivalent to [`split`], except that the trailing substring
+    /// is skipped if empty.
+    ///
+    /// [`split`]: #method.split
+    ///
+    /// This method can be used for string data that is _terminated_,
+    /// rather than _separated_ by a pattern.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    /// [`char`]: primitive.char.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rsplit_terminator`] method can be used.
+    ///
+    /// [`rsplit_terminator`]: #method.rsplit_terminator
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
+    /// assert_eq!(v, ["A", "B"]);
+    ///
+    /// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
+    /// assert_eq!(v, ["A", "", "B", ""]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
+        StrExt::split_terminator(self, pat)
+    }
+
+    /// An iterator over substrings of `self`, separated by characters
+    /// matched by a pattern and yielded in reverse order.
+    ///
+    /// The pattern can be a simple `&str`, [`char`], or a closure that
+    /// determines the split.
+    /// Additional libraries might provide more complex patterns like
+    /// regular expressions.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// Equivalent to [`split`], except that the trailing substring is
+    /// skipped if empty.
+    ///
+    /// [`split`]: #method.split
+    ///
+    /// This method can be used for string data that is _terminated_,
+    /// rather than _separated_ by a pattern.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a
+    /// reverse search, and it will be double ended if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// For iterating from the front, the [`split_terminator`] method can be
+    /// used.
+    ///
+    /// [`split_terminator`]: #method.split_terminator
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
+    /// assert_eq!(v, ["B", "A"]);
+    ///
+    /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
+    /// assert_eq!(v, ["", "B", "", "A"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rsplit_terminator(self, pat)
+    }
+
+    /// An iterator over substrings of the given string slice, separated by a
+    /// pattern, restricted to returning at most `n` items.
+    ///
+    /// If `n` substrings are returned, the last substring (the `n`th substring)
+    /// will contain the remainder of the string.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will not be double ended, because it is
+    /// not efficient to support.
+    ///
+    /// If the pattern allows a reverse search, the [`rsplitn`] method can be
+    /// used.
+    ///
+    /// [`rsplitn`]: #method.rsplitn
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
+    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
+    ///
+    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
+    /// assert_eq!(v, ["abcXdef"]);
+    ///
+    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
+    /// assert_eq!(v, [""]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["abc", "defXghi"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
+        StrExt::splitn(self, n, pat)
+    }
+
+    /// An iterator over substrings of this string slice, separated by a
+    /// pattern, starting from the end of the string, restricted to returning
+    /// at most `n` items.
+    ///
+    /// If `n` substrings are returned, the last substring (the `n`th substring)
+    /// will contain the remainder of the string.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines the split.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will not be double ended, because it is not
+    /// efficient to support.
+    ///
+    /// For splitting from the front, the [`splitn`] method can be used.
+    ///
+    /// [`splitn`]: #method.splitn
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
+    /// assert_eq!(v, ["leopard", "lion::tiger"]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["ghi", "abc1def"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rsplitn(self, n, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within the given string
+    /// slice.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    /// [`char`]: primitive.char.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rmatches`] method can be used.
+    ///
+    /// [`rmatches`]: #method.rmatches
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
+    /// assert_eq!(v, ["abc", "abc", "abc"]);
+    ///
+    /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
+    /// assert_eq!(v, ["1", "2", "3"]);
+    /// ```
+    #[stable(feature = "str_matches", since = "1.2.0")]
+    #[inline]
+    pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
+        StrExt::matches(self, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within this string slice,
+    /// yielded in reverse order.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// For iterating from the front, the [`matches`] method can be used.
+    ///
+    /// [`matches`]: #method.matches
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
+    /// assert_eq!(v, ["abc", "abc", "abc"]);
+    ///
+    /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
+    /// assert_eq!(v, ["3", "2", "1"]);
+    /// ```
+    #[stable(feature = "str_matches", since = "1.2.0")]
+    #[inline]
+    pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rmatches(self, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within this string
+    /// slice as well as the index that the match starts at.
+    ///
+    /// For matches of `pat` within `self` that overlap, only the indices
+    /// corresponding to the first match are returned.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines
+    /// if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rmatch_indices`] method can be used.
+    ///
+    /// [`rmatch_indices`]: #method.rmatch_indices
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
+    /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
+    ///
+    /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
+    /// assert_eq!(v, [(1, "abc"), (4, "abc")]);
+    ///
+    /// let v: Vec<_> = "ababa".match_indices("aba").collect();
+    /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
+    /// ```
+    #[stable(feature = "str_match_indices", since = "1.5.0")]
+    #[inline]
+    pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
+        StrExt::match_indices(self, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within `self`,
+    /// yielded in reverse order along with the index of the match.
+    ///
+    /// For matches of `pat` within `self` that overlap, only the indices
+    /// corresponding to the last match are returned.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if a
+    /// character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// For iterating from the front, the [`match_indices`] method can be used.
+    ///
+    /// [`match_indices`]: #method.match_indices
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
+    ///
+    /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(4, "abc"), (1, "abc")]);
+    ///
+    /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
+    /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
+    /// ```
+    #[stable(feature = "str_match_indices", since = "1.5.0")]
+    #[inline]
+    pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rmatch_indices(self, pat)
+    }
+
+    /// Returns a string slice with leading and trailing whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    ///
+    /// assert_eq!("Hello\tworld", s.trim());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim(&self) -> &str {
+        StrExt::trim(self)
+    }
+
+    /// Returns a string slice with leading whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    ///
+    /// assert_eq!("Hello\tworld\t", s.trim_left());
+    /// ```
+    ///
+    /// Directionality:
+    ///
+    /// ```
+    /// let s = "  English";
+    /// assert!(Some('E') == s.trim_left().chars().next());
+    ///
+    /// let s = "  עברית";
+    /// assert!(Some('ע') == s.trim_left().chars().next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_left(&self) -> &str {
+        StrExt::trim_left(self)
+    }
+
+    /// Returns a string slice with trailing whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    ///
+    /// assert_eq!(" Hello\tworld", s.trim_right());
+    /// ```
+    ///
+    /// Directionality:
+    ///
+    /// ```
+    /// let s = "English  ";
+    /// assert!(Some('h') == s.trim_right().chars().rev().next());
+    ///
+    /// let s = "עברית  ";
+    /// assert!(Some('ת') == s.trim_right().chars().rev().next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_right(&self) -> &str {
+        StrExt::trim_right(self)
+    }
+
+    /// Returns a string slice with all prefixes and suffixes that match a
+    /// pattern repeatedly removed.
+    ///
+    /// The pattern can be a [`char`] or a closure that determines if a
+    /// character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+    /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: DoubleEndedSearcher<'a>
+    {
+        StrExt::trim_matches(self, pat)
+    }
+
+    /// Returns a string slice with all prefixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
+        StrExt::trim_left_matches(self, pat)
+    }
+
+    /// Returns a string slice with all suffixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::trim_right_matches(self, pat)
+    }
+
+    /// Parses this string slice into another type.
+    ///
+    /// Because `parse` is so general, it can cause problems with type
+    /// inference. As such, `parse` is one of the few times you'll see
+    /// the syntax affectionately known as the 'turbofish': `::<>`. This
+    /// helps the inference algorithm understand specifically which type
+    /// you're trying to parse into.
+    ///
+    /// `parse` can parse any type that implements the [`FromStr`] trait.
+    ///
+    /// [`FromStr`]: str/trait.FromStr.html
+    ///
+    /// # Errors
+    ///
+    /// Will return [`Err`] if it's not possible to parse this string slice into
+    /// the desired type.
+    ///
+    /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
+    ///
+    /// # Examples
+    ///
+    /// Basic usage
+    ///
+    /// ```
+    /// let four: u32 = "4".parse().unwrap();
+    ///
+    /// assert_eq!(4, four);
+    /// ```
+    ///
+    /// Using the 'turbofish' instead of annotating `four`:
+    ///
+    /// ```
+    /// let four = "4".parse::<u32>();
+    ///
+    /// assert_eq!(Ok(4), four);
+    /// ```
+    ///
+    /// Failing to parse:
+    ///
+    /// ```
+    /// let nope = "j".parse::<u32>();
+    ///
+    /// assert!(nope.is_err());
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
+        StrExt::parse(self)
+    }
+
+    /// Checks if all characters in this string are within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = "hello!\n";
+    /// let non_ascii = "Grüße, Jürgen ❤";
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        // We can treat each byte as character here: all multibyte characters
+        // start with a byte that is not in the ascii range, so we will stop
+        // there already.
+        self.bytes().all(|b| b.is_ascii())
+    }
+
+    /// Checks that two strings are an ASCII case-insensitive match.
+    ///
+    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+    /// but without allocating and copying temporaries.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
+    /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS"));
+    /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
+        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
+    }
+
+    /// Converts this string to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    pub fn make_ascii_uppercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_uppercase()
+    }
+
+    /// Converts this string to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    pub fn make_ascii_lowercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_lowercase()
+    }
+}}
+
+#[lang = "str"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl str {
+    str_core_methods!();
+}
+
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<[u8]> for str {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.as_bytes()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> Default for &'a str {
+    /// Creates an empty str
+    fn default() -> &'a str { "" }
+}
+
+/// An iterator over the non-whitespace substrings of a string,
+/// separated by any amount of whitespace.
+///
+/// This struct is created by the [`split_whitespace`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
+/// [`str`]: ../../std/primitive.str.html
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+#[derive(Clone, Debug)]
+pub struct SplitWhitespace<'a> {
+    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
+}
+
+#[derive(Clone)]
+struct IsWhitespace;
+
+impl FnOnce<(char, )> for IsWhitespace {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl FnMut<(char, )> for IsWhitespace {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
+        arg.0.is_whitespace()
+    }
+}
+
+#[derive(Clone)]
+struct IsNotEmpty;
+
+impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
+        !arg.0.is_empty()
+    }
+}
+
+
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+impl<'a> Iterator for SplitWhitespace<'a> {
+    type Item = &'a str;
+
+    fn next(&mut self) -> Option<&'a str> {
+        self.inner.next()
+    }
+}
+
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.inner.next_back()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<'a> FusedIterator for SplitWhitespace<'a> {}
+
+/// An iterator of [`u16`] over the string encoded as UTF-16.
+///
+/// [`u16`]: ../../std/primitive.u16.html
+///
+/// This struct is created by the [`encode_utf16`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16
+/// [`str`]: ../../std/primitive.str.html
+#[derive(Clone)]
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+pub struct EncodeUtf16<'a> {
+    chars: Chars<'a>,
+    extra: u16,
+}
+
+// FIXME: remove (inline) this method
+// when updating to a bootstrap compiler that has the new lang items.
+// For grepping purpose: #[cfg(stage0)]
+impl<'a> EncodeUtf16<'a> {
+    #[unstable(feature = "core_str_ext", issue = "32110")]
+    #[doc(hidden)]
+    pub fn new(s: &'a str) -> Self {
+        EncodeUtf16 { chars: s.chars(), extra: 0 }
+    }
+}
+
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a> fmt::Debug for EncodeUtf16<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("EncodeUtf16 { .. }")
+    }
+}
+
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+impl<'a> Iterator for EncodeUtf16<'a> {
+    type Item = u16;
+
+    #[inline]
+    fn next(&mut self) -> Option<u16> {
+        if self.extra != 0 {
+            let tmp = self.extra;
+            self.extra = 0;
+            return Some(tmp);
+        }
+
+        let mut buf = [0; 2];
+        self.chars.next().map(|ch| {
+            let n = ch.encode_utf16(&mut buf).len();
+            if n == 2 {
+                self.extra = buf[1];
+            }
+            buf[0]
+        })
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (low, high) = self.chars.size_hint();
+        // every char gets either one u16 or two u16,
+        // so this iterator is between 1 or 2 times as
+        // long as the underlying iterator.
+        (low, high.and_then(|n| n.checked_mul(2)))
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<'a> FusedIterator for EncodeUtf16<'a> {}
index 95bb8f18947ec842a5a92ff107e4fb63b550f9b5..464d57a270241e7e639d9ae0a90c324bf5e50ab1 100644 (file)
@@ -258,7 +258,7 @@ pub struct CharSearcher<'a> {
 
     /// `finger` is the current byte index of the forward search.
     /// Imagine that it exists before the byte at its index, i.e.
-    /// haystack[finger] is the first byte of the slice we must inspect during
+    /// `haystack[finger]` is the first byte of the slice we must inspect during
     /// forward searching
     finger: usize,
     /// `finger_back` is the current byte index of the reverse search.
index 62e0979c5fefc077f9171c0595136fc5a297d29c..7aba8b51cff510986be81832d27b24e4b5525967 100644 (file)
@@ -990,9 +990,7 @@ fn from(v: $int_type) -> Self { Self::new(v) }
         #[$stable_debug]
         impl fmt::Debug for $atomic_type {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                f.debug_tuple(stringify!($atomic_type))
-                 .field(&self.load(Ordering::SeqCst))
-                 .finish()
+                fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
             }
         }
 
@@ -1360,8 +1358,7 @@ pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
 # Examples
 
 ```
-", $extra_feature, "#![feature(atomic_nand)]
-
+", $extra_feature, "
 use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
 
 let foo = ", stringify!($atomic_type), "::new(0x13);
@@ -1555,7 +1552,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i8", "../../../std/primitive.i8.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_min, atomic_max,
@@ -1568,7 +1565,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u8", "../../../std/primitive.u8.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_umin, atomic_umax,
@@ -1581,7 +1578,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i16", "../../../std/primitive.i16.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_min, atomic_max,
@@ -1594,7 +1591,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u16", "../../../std/primitive.u16.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_umin, atomic_umax,
@@ -1607,7 +1604,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i32", "../../../std/primitive.i32.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_min, atomic_max,
@@ -1620,7 +1617,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u32", "../../../std/primitive.u32.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_umin, atomic_umax,
@@ -1633,7 +1630,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i64", "../../../std/primitive.i64.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_min, atomic_max,
@@ -1646,7 +1643,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u64", "../../../std/primitive.u64.html",
     "#![feature(integer_atomics)]\n\n",
     atomic_umin, atomic_umax,
@@ -1659,7 +1656,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
     stable(feature = "atomic_from", since = "1.23.0"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    stable(feature = "atomic_nand", since = "1.27.0"),
     "isize", "../../../std/primitive.isize.html",
     "",
     atomic_min, atomic_max,
@@ -1672,7 +1669,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
     stable(feature = "atomic_from", since = "1.23.0"),
-    unstable(feature = "atomic_nand", issue = "13226"),
+    stable(feature = "atomic_nand", since = "1.27.0"),
     "usize", "../../../std/primitive.usize.html",
     "",
     atomic_umin, atomic_umax,
@@ -2091,7 +2088,7 @@ pub fn compiler_fence(order: Ordering) {
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl fmt::Debug for AtomicBool {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("AtomicBool").field(&self.load(Ordering::SeqCst)).finish()
+        fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
     }
 }
 
@@ -2099,7 +2096,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl<T> fmt::Debug for AtomicPtr<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish()
+        fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
     }
 }
 
index cc0ef6a6f17e04b5e7358040d0ef689cb73ea871..962fb2f0e027b3924507205b43145beccef82485 100644 (file)
@@ -26,6 +26,17 @@ fn smoketest_cell() {
     assert!(y.get() == (30, 40));
 }
 
+#[test]
+fn cell_update() {
+    let x = Cell::new(10);
+
+    assert_eq!(x.update(|x| x + 5), 15);
+    assert_eq!(x.get(), 15);
+
+    assert_eq!(x.update(|x| x / 3), 5);
+    assert_eq!(x.get(), 5);
+}
+
 #[test]
 fn cell_has_sensible_show() {
     let x = Cell::new("foo bar");
index 149269263dc8a542b34c1ff36aed75c4e4ca9075..2b69f04013d201a320a927648a011a4319baa0e2 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(ascii_ctype)]
 #![feature(box_syntax)]
+#![feature(cell_update)]
 #![feature(core_float)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
@@ -17,6 +18,7 @@
 #![feature(decode_utf8)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
+#![feature(float_internals)]
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
 #![feature(str_internals)]
 #![feature(test)]
 #![feature(trusted_len)]
+#![feature(try_from)]
 #![feature(try_trait)]
 #![feature(exact_chunks)]
-#![feature(atomic_nand)]
+#![cfg_attr(stage0, feature(atomic_nand))]
 #![feature(reverse_bits)]
 #![feature(inclusive_range_fields)]
 #![feature(iterator_find_map)]
index b8d0719b9b992b565daf45d68b161b9e68dfff87..e22fe450bb1f6562ac0e5f8c3e13fbb4211521d1 100644 (file)
@@ -137,7 +137,6 @@ pub const fn from_millis(millis: u64) -> Duration {
     /// # Examples
     ///
     /// ```
-    /// #![feature(duration_from_micros)]
     /// use std::time::Duration;
     ///
     /// let duration = Duration::from_micros(1_000_002);
@@ -145,7 +144,7 @@ pub const fn from_millis(millis: u64) -> Duration {
     /// assert_eq!(1, duration.as_secs());
     /// assert_eq!(2000, duration.subsec_nanos());
     /// ```
-    #[unstable(feature = "duration_from_micros", issue = "44400")]
+    #[stable(feature = "duration_from_micros", since = "1.27.0")]
     #[inline]
     pub const fn from_micros(micros: u64) -> Duration {
         Duration {
@@ -159,7 +158,6 @@ pub const fn from_micros(micros: u64) -> Duration {
     /// # Examples
     ///
     /// ```
-    /// #![feature(duration_extras)]
     /// use std::time::Duration;
     ///
     /// let duration = Duration::from_nanos(1_000_000_123);
@@ -167,7 +165,7 @@ pub const fn from_micros(micros: u64) -> Duration {
     /// assert_eq!(1, duration.as_secs());
     /// assert_eq!(123, duration.subsec_nanos());
     /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
+    #[stable(feature = "duration_extras", since = "1.27.0")]
     #[inline]
     pub const fn from_nanos(nanos: u64) -> Duration {
         Duration {
@@ -217,14 +215,13 @@ pub fn as_secs(&self) -> u64 { self.secs }
     /// # Examples
     ///
     /// ```
-    /// #![feature(duration_extras)]
     /// use std::time::Duration;
     ///
     /// let duration = Duration::from_millis(5432);
     /// assert_eq!(duration.as_secs(), 5);
     /// assert_eq!(duration.subsec_millis(), 432);
     /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
+    #[stable(feature = "duration_extras", since = "1.27.0")]
     #[inline]
     pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
 
@@ -237,14 +234,13 @@ pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
     /// # Examples
     ///
     /// ```
-    /// #![feature(duration_extras, duration_from_micros)]
     /// use std::time::Duration;
     ///
     /// let duration = Duration::from_micros(1_234_567);
     /// assert_eq!(duration.as_secs(), 1);
     /// assert_eq!(duration.subsec_micros(), 234_567);
     /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
+    #[stable(feature = "duration_extras", since = "1.27.0")]
     #[inline]
     pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
 
index 43c5bbbc618c2954edf7a2580102ad8932acc7ae..392bf17968fbdfc28f648b7b9f94f2c5d16e403f 100644 (file)
@@ -52,7 +52,7 @@
 // now hopefully.
 #[no_mangle]
 #[rustc_std_internal_symbol]
-pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
+pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
     abort();
 
     #[cfg(any(unix, target_os = "cloudabi"))]
index 9321d6917d1566db3ef070a9c35066c0ef8b1007..6c52c0fa10cc0b534536ed0f19ef3f602801082f 100644 (file)
@@ -29,6 +29,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 
+#![feature(allocator_api)]
 #![feature(alloc)]
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
@@ -36,6 +37,7 @@
 #![feature(panic_unwind)]
 #![feature(raw)]
 #![feature(staged_api)]
+#![feature(std_internals)]
 #![feature(unwind_attributes)]
 #![cfg_attr(target_env = "msvc", feature(raw))]
 
 #[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
 extern crate unwind;
 
+use alloc::boxed::Box;
 use core::intrinsics;
 use core::mem;
 use core::raw;
+use core::panic::BoxMeUp;
 
 // Rust runtime's startup objects depend on these symbols, so make them public.
 #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
 // implementation.
 #[no_mangle]
 #[unwind(allowed)]
-pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 {
-    imp::panic(mem::transmute(raw::TraitObject {
-        data: data as *mut (),
-        vtable: vtable as *mut (),
-    }))
+pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 {
+    let payload = payload as *mut &mut BoxMeUp;
+    imp::panic(Box::from_raw((*payload).box_me_up()))
 }
index a0ec692809499f47152482115a5ea40ccd791fc9..d1f8e75192ae178adc7d5c16b6a2898d5a1b4376 100644 (file)
@@ -163,9 +163,9 @@ fn quote(self) -> TokenStream {
     }
 }
 
-impl Quote for usize {
+impl Quote for u16 {
     fn quote(self) -> TokenStream {
-        TokenTree::from(Literal::usize_unsuffixed(self)).into()
+        TokenTree::from(Literal::u16_unsuffixed(self)).into()
     }
 }
 
@@ -197,7 +197,7 @@ macro_rules! literals {
     ($($i:ident),*; $($raw:ident),*) => {
         pub enum LiteralKind {
             $($i,)*
-            $($raw(usize),)*
+            $($raw(u16),)*
         }
 
         impl LiteralKind {
index 1b90707323850dccd75e9411dd6124a304b84771..b4f39439d5b4d4d93c4b36bee707a1775650bd6a 100644 (file)
@@ -556,7 +556,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] DefSpan(DefId),
     [] LookupStability(DefId),
     [] LookupDeprecationEntry(DefId),
-    [] ItemBodyNestedBodies(DefId),
     [] ConstIsRvaluePromotableToStatic(DefId),
     [] RvaluePromotableMap(DefId),
     [] ImplParent(DefId),
@@ -567,6 +566,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] ItemAttrs(DefId),
     [] TransFnAttrs(DefId),
     [] FnArgNames(DefId),
+    [] RenderedConst(DefId),
     [] DylibDepFormats(CrateNum),
     [] IsPanicRuntime(CrateNum),
     [] IsCompilerBuiltins(CrateNum),
@@ -615,7 +615,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] GetLangItems,
     [] DefinedLangItems(CrateNum),
     [] MissingLangItems(CrateNum),
-    [] ExternConstBody(DefId),
     [] VisibleParentMap,
     [input] MissingExternCrateItem(CrateNum),
     [input] UsedCrateSource(CrateNum),
index 1e348e3a31ce215225c4a269e5fa792e235b4439..9520ed32af9e1a4b7d9c96c88d5e0306db44157e 100644 (file)
 use hir::*;
 use hir::print::Nested;
 use hir::svh::Svh;
-use util::nodemap::{DefIdMap, FxHashMap};
+use util::nodemap::FxHashMap;
 
-use arena::TypedArena;
 use std::io;
 use ty::TyCtxt;
 
-use rustc_data_structures::sync::Lock;
-
 pub mod blocks;
 mod collector;
 mod def_collector;
@@ -219,7 +216,6 @@ fn is_body_owner(self, node_id: NodeId) -> bool {
 pub struct Forest {
     krate: Crate,
     pub dep_graph: DepGraph,
-    inlined_bodies: TypedArena<Body>
 }
 
 impl Forest {
@@ -227,7 +223,6 @@ pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest {
         Forest {
             krate,
             dep_graph: dep_graph.clone(),
-            inlined_bodies: TypedArena::new()
         }
     }
 
@@ -264,9 +259,6 @@ pub struct Map<'hir> {
 
     definitions: &'hir Definitions,
 
-    /// Bodies inlined from other crates are cached here.
-    inlined_bodies: Lock<DefIdMap<&'hir Body>>,
-
     /// The reverse mapping of `node_to_hir_id`.
     hir_to_node_id: FxHashMap<HirId, NodeId>,
 }
@@ -923,21 +915,6 @@ pub fn expect_expr(&self, id: NodeId) -> &'hir Expr {
         }
     }
 
-    pub fn get_inlined_body_untracked(&self, def_id: DefId) -> Option<&'hir Body> {
-        self.inlined_bodies.borrow().get(&def_id).cloned()
-    }
-
-    pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body {
-        let mut inlined_bodies = self.inlined_bodies.borrow_mut();
-        if let Some(&b) = inlined_bodies.get(&def_id) {
-            debug_assert_eq!(&body, b);
-            return b;
-        }
-        let body = self.forest.inlined_bodies.alloc(body);
-        inlined_bodies.insert(def_id, body);
-        body
-    }
-
     /// Returns the name associated with the given NodeId's AST.
     pub fn name(&self, id: NodeId) -> Name {
         match self.get(id) {
@@ -1195,7 +1172,6 @@ pub fn map_crate<'hir>(sess: &::session::Session,
         map,
         hir_to_node_id,
         definitions,
-        inlined_bodies: Lock::new(DefIdMap()),
     };
 
     hir_id_validator::check_crate(&map);
index e6080fad91d597f60410ffd2e989951490c1b835..f471ffb072d6700ebc937d0c25d5e9c6b8d24161 100644 (file)
@@ -2277,6 +2277,7 @@ pub struct TransFnAttrFlags: u8 {
         const NAKED                     = 0b0001_0000;
         const NO_MANGLE                 = 0b0010_0000;
         const RUSTC_STD_INTERNAL_SYMBOL = 0b0100_0000;
+        const NO_DEBUG                  = 0b1000_0000;
     }
 }
 
index d885bd43bc89dbce656a42db81c6e5aa475bf3cb..96d7cb6b041a83508866c568a7a48572a37ecf64 100644 (file)
@@ -11,8 +11,6 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::middle::cstore in no particular order.
 
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
-
 use middle;
 
 impl_stable_hash_for!(enum middle::cstore::DepKind {
     rlib,
     rmeta
 });
-
-impl<HCX> HashStable<HCX> for middle::cstore::ExternBodyNestedBodies {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut HCX,
-                                          hasher: &mut StableHasher<W>) {
-        let middle::cstore::ExternBodyNestedBodies {
-            nested_bodies: _,
-            fingerprint,
-        } = *self;
-
-        fingerprint.hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a, HCX> HashStable<HCX> for middle::cstore::ExternConstBody<'a> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut HCX,
-                                          hasher: &mut StableHasher<W>) {
-        let middle::cstore::ExternConstBody {
-            body: _,
-            fingerprint,
-        } = *self;
-
-        fingerprint.hash_stable(hcx, hasher);
-    }
-}
index c5be1b1174c432c0d2b2bb6c624a6cd8ba2aa859..70c152b40c0d25fdbc77561268c46efa6c192459 100644 (file)
@@ -1387,6 +1387,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             FromEnv(where_clause) => where_clause.hash_stable(hcx, hasher),
 
             WellFormedTy(ty) => ty.hash_stable(hcx, hasher),
+            Normalize(projection) => projection.hash_stable(hcx, hasher),
             FromEnvTy(ty) => ty.hash_stable(hcx, hasher),
             RegionOutlives(predicate) => predicate.hash_stable(hcx, hasher),
             TypeOutlives(predicate) => predicate.hash_stable(hcx, hasher),
index 8d314e251972d140e1b173b931b1b71d306b5a40..d8a2c95ab5904f1adadc5c1ad00f2a0a0808924b 100644 (file)
@@ -303,7 +303,7 @@ pub fn report_region_errors(
     ) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
-        if will_later_be_reported_by_nll && self.tcx.nll() {
+        if will_later_be_reported_by_nll && self.tcx.use_mir_borrowck() {
             // With `#![feature(nll)]`, we want to present a nice user
             // experience, so don't even mention the errors from the
             // AST checker.
@@ -311,20 +311,20 @@ pub fn report_region_errors(
                 return;
             }
 
-            // But with -Znll, it's nice to have some note for later.
+            // But with nll, it's nice to have some note for later.
             for error in errors {
                 match *error {
                     RegionResolutionError::ConcreteFailure(ref origin, ..)
                     | RegionResolutionError::GenericBoundFailure(ref origin, ..) => {
                         self.tcx
                             .sess
-                            .span_warn(origin.span(), "not reporting region error due to -Znll");
+                            .span_warn(origin.span(), "not reporting region error due to nll");
                     }
 
                     RegionResolutionError::SubSupConflict(ref rvo, ..) => {
                         self.tcx
                             .sess
-                            .span_warn(rvo.span(), "not reporting region error due to -Znll");
+                            .span_warn(rvo.span(), "not reporting region error due to nll");
                     }
                 }
             }
index 84bf9cc84e7373499419c79f7d4b9682840801aa..40cc43c3ca670d00e56b7d160f449d762cd7cf09 100644 (file)
@@ -37,7 +37,7 @@
 use syntax_pos::{self, Span};
 use syntax_pos::symbol::InternedString;
 use util::nodemap::FxHashMap;
-use arena::DroplessArena;
+use arena::SyncDroplessArena;
 
 use self::combine::CombineFields;
 use self::higher_ranked::HrMatchResult;
@@ -407,7 +407,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
 pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
-    arena: DroplessArena,
+    arena: SyncDroplessArena,
     fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
 }
 
@@ -415,7 +415,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
     pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
         InferCtxtBuilder {
             global_tcx: self,
-            arena: DroplessArena::new(),
+            arena: SyncDroplessArena::new(),
             fresh_tables: None,
 
         }
index a2cefe488c68ac53767b9ec0727a3750d1a10779..bb495049483ac3c0d2b95671655be1dd47eefc3f 100644 (file)
@@ -52,6 +52,7 @@
 #![cfg_attr(windows, feature(libc))]
 #![feature(macro_lifetime_matcher)]
 #![feature(macro_vis_matcher)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(non_exhaustive)]
 #![feature(nonzero)]
index 9f8cc2f86992f54ffa5d73f15be5cf2c5a10cab9..d5849ea22b1ef299cf4bd8aa0dee5c7ca152e255 100644 (file)
@@ -27,6 +27,7 @@
 use self::TargetLint::*;
 
 use std::slice;
+use rustc_data_structures::sync::{RwLock, ReadGuard};
 use lint::{EarlyLintPassObject, LateLintPassObject};
 use lint::{Level, Lint, LintId, LintPass, LintBuffer};
 use lint::builtin::BuiltinLintDiagnostics;
@@ -39,7 +40,6 @@
 use util::nodemap::FxHashMap;
 
 use std::default::Default as StdDefault;
-use std::cell::{Ref, RefCell};
 use syntax::ast;
 use syntax::edition;
 use syntax_pos::{MultiSpan, Span};
@@ -78,7 +78,7 @@ pub struct LintStore {
 
 pub struct LintSession<'a, PassObject> {
     /// Reference to the store of registered lints.
-    lints: Ref<'a, LintStore>,
+    lints: ReadGuard<'a, LintStore>,
 
     /// Trait objects for each lint pass.
     passes: Option<Vec<PassObject>>,
@@ -336,7 +336,7 @@ impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> {
     /// Creates a new `LintSession`, by moving out the `LintStore`'s initial
     /// lint levels and pass objects. These can be restored using the `restore`
     /// method.
-    fn new(store: &'a RefCell<LintStore>) -> LintSession<'a, PassObject> {
+    fn new(store: &'a RwLock<LintStore>) -> LintSession<'a, PassObject> {
         let mut s = store.borrow_mut();
         let passes = PassObject::take_passes(&mut *s);
         drop(s);
@@ -347,7 +347,7 @@ fn new(store: &'a RefCell<LintStore>) -> LintSession<'a, PassObject> {
     }
 
     /// Restores the levels back to the original lint store.
-    fn restore(self, store: &RefCell<LintStore>) {
+    fn restore(self, store: &RwLock<LintStore>) {
         drop(self.lints);
         let mut s = store.borrow_mut();
         PassObject::restore_passes(&mut *s, self.passes);
index 292ec184dfae5d9ada4e8fa913462ffe6fb8f5be..60e197e614aa6f7e3e98459bb47bbab59d99867f 100644 (file)
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
-use hir;
 use hir::def;
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::map as hir_map;
 use hir::map::definitions::{Definitions, DefKey, DefPathTable};
 use hir::svh::Svh;
-use ich;
 use ty::{self, TyCtxt};
 use session::{Session, CrateDisambiguator};
 use session::search_paths::PathKind;
 
 use std::any::Any;
-use std::collections::BTreeMap;
 use std::path::{Path, PathBuf};
 use syntax::ast;
 use syntax::ext::base::SyntaxExtension;
@@ -209,26 +206,6 @@ fn get_dylib_metadata(&self,
                           -> Result<MetadataRef, String>;
 }
 
-#[derive(Clone)]
-pub struct ExternConstBody<'tcx> {
-    pub body: &'tcx hir::Body,
-
-    // It would require a lot of infrastructure to enable stable-hashing Bodies
-    // from other crates, so we hash on export and just store the fingerprint
-    // with them.
-    pub fingerprint: ich::Fingerprint,
-}
-
-#[derive(Clone)]
-pub struct ExternBodyNestedBodies {
-    pub nested_bodies: Lrc<BTreeMap<hir::BodyId, hir::Body>>,
-
-    // It would require a lot of infrastructure to enable stable-hashing Bodies
-    // from other crates, so we hash on export and just store the fingerprint
-    // with them.
-    pub fingerprint: ich::Fingerprint,
-}
-
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 ///
index 3b37031cf461452978a78fa6a4760262543b4514..95e92e21b09dcdd50129bad5151257cbe62bb725 100644 (file)
@@ -214,6 +214,9 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     StrImplItem,                     "str",                     str_impl;
     SliceImplItem,                   "slice",                   slice_impl;
     SliceU8ImplItem,                 "slice_u8",                slice_u8_impl;
+    StrAllocImplItem,                "str_alloc",               str_alloc_impl;
+    SliceAllocImplItem,              "slice_alloc",             slice_alloc_impl;
+    SliceU8AllocImplItem,            "slice_u8_alloc",          slice_u8_alloc_impl;
     ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
     MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
     I8ImplItem,                      "i8",                      i8_impl;
@@ -230,6 +233,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     UsizeImplItem,                   "usize",                   usize_impl;
     F32ImplItem,                     "f32",                     f32_impl;
     F64ImplItem,                     "f64",                     f64_impl;
+    F32RuntimeImplItem,              "f32_runtime",             f32_runtime_impl;
+    F64RuntimeImplItem,              "f64_runtime",             f64_runtime_impl;
 
     SizedTraitLangItem,              "sized",                   sized_trait;
     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
@@ -298,7 +303,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
-    DropInPlaceFnLangItem,             "drop_in_place",           drop_in_place_fn;
+    DropInPlaceFnLangItem,           "drop_in_place",           drop_in_place_fn;
+    OomLangItem,                     "oom",                     oom;
 
     StartFnLangItem,                 "start",                   start_fn;
 
index e19f4483f6569f536549ef57501d9bcebe13e025..a2bceb191022165f2ff59c10760ac7bfd8474671 100644 (file)
@@ -151,4 +151,5 @@ fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
     panic_fmt,          PanicFmtLangItem,           rust_begin_unwind;
     eh_personality,     EhPersonalityLangItem,      rust_eh_personality;
     eh_unwind_resume,   EhUnwindResumeLangItem,     rust_eh_unwind_resume;
+    oom,                OomLangItem,                rust_oom;
 }
index 33f52ab09c85668b72c9d3a008345fe5394688e6..c525c4ed651f244faf93df66289f4884629441c3 100644 (file)
@@ -1991,7 +1991,7 @@ pub fn successor_within_block(&self) -> Location {
         Location { block: self.block, statement_index: self.statement_index + 1 }
     }
 
-    pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -> bool {
+    pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
         if self.block == other.block {
             self.statement_index <= other.statement_index
         } else {
index d309026212bfa1f408667cfe5a6053064553adb1..e9fe94cdb4a361c29573d316d921e76ab7bd2457 100644 (file)
@@ -16,6 +16,8 @@
 pub use self::Passes::*;
 pub use self::DebugInfoLevel::*;
 
+use std::str::FromStr;
+
 use session::{early_error, early_warn, Session};
 use session::search_paths::SearchPaths;
 
@@ -28,7 +30,7 @@
 
 use syntax::ast::{self, IntTy, UintTy};
 use syntax::codemap::{FileName, FilePathMapping};
-use syntax::edition::Edition;
+use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
 use syntax::parse::token;
 use syntax::parse;
 use syntax::symbol::Symbol;
@@ -246,6 +248,10 @@ pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf
         self.0.values()
     }
 
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
     // True if any of the output types require codegen or linking.
     pub fn should_trans(&self) -> bool {
         self.0.keys().any(|k| match *k {
@@ -406,6 +412,7 @@ pub struct Options {
 
         // Remap source path prefixes in all output (messages, object files, debug, etc)
         remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
+        edition: Edition [TRACKED],
     }
 );
 
@@ -585,6 +592,7 @@ pub fn basic_options() -> Options {
         cli_forced_codegen_units: None,
         cli_forced_thinlto_off: false,
         remap_path_prefix: Vec::new(),
+        edition: DEFAULT_EDITION,
     }
 }
 
@@ -769,8 +777,6 @@ mod $mod_desc {
             Some("`string` or `string=string`");
         pub const parse_lto: Option<&'static str> =
             Some("one of `thin`, `fat`, or omitted");
-        pub const parse_edition: Option<&'static str> =
-            Some("one of: `2015`, `2018`");
     }
 
     #[allow(dead_code)]
@@ -778,7 +784,6 @@ mod $mod_set {
         use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
         use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
-        use syntax::edition::Edition;
 
         $(
             pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -981,20 +986,6 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
             true
         }
 
-        fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
-            match v {
-                Some(s) => {
-                    let edition = s.parse();
-                    if let Ok(parsed) = edition {
-                        *slot = parsed;
-                        true
-                    } else {
-                        false
-                    }
-                }
-                _ => false,
-            }
-        }
     }
 ) }
 
@@ -1255,8 +1246,8 @@ fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
         useful for profiling / PGO."),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
         "choose which RELRO level to use"),
-    nll: bool = (false, parse_bool, [UNTRACKED],
-                 "run the non-lexical lifetimes MIR pass"),
+    nll_subminimal_causes: bool = (false, parse_bool, [UNTRACKED],
+        "when tracking region error causes, accept subminimal results for faster execution."),
     disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
         "disable user provided type assertion in NLL"),
     trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -1288,10 +1279,6 @@ fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
         `everybody_loops` (all function bodies replaced with `loop {}`),
         `hir` (the HIR), `hir,identified`, or
         `hir,typed` (HIR with types for each node)."),
-    edition: Edition = (Edition::Edition2015, parse_edition, [TRACKED],
-        "The edition to build Rust with. Newer editions may include features
-         that require breaking changes. The default edition is 2015 (the first
-         edition). Crates compiled with different editions can be linked together."),
     run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
           "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
@@ -1652,6 +1639,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
             "TYPE",
         ),
+        opt::opt_s(
+            "",
+            "edition",
+            "Specify which edition of the compiler to use when compiling code.",
+            EDITION_NAME_LIST,
+        ),
         opt::multi_s(
             "",
             "remap-path-prefix",
@@ -1711,6 +1704,34 @@ pub fn build_session_options_and_crate_config(
         ),
     };
 
+    let edition = match matches.opt_str("edition") {
+        Some(arg) => match Edition::from_str(&arg){
+            Ok(edition) => edition,
+            Err(_) => early_error(
+                ErrorOutputType::default(),
+                &format!(
+                    "argument for --edition must be one of: \
+                    {}. (instead was `{}`)",
+                    EDITION_NAME_LIST,
+                    arg
+                ),
+            ),
+        }
+        None => DEFAULT_EDITION,
+    };
+
+    if !edition.is_stable() && !nightly_options::is_nightly_build() {
+        early_error(
+                ErrorOutputType::default(),
+                &format!(
+                    "Edition {} is unstable an only\
+                    available for nightly builds of rustc.",
+                    edition,
+                )
+        )
+    }
+
+
     // We need the opts_present check because the driver will send us Matches
     // with only stable options if no unstable options are used. Since error-format
     // is unstable, it will not be present. We have to use opts_present not
@@ -2167,6 +2188,7 @@ pub fn build_session_options_and_crate_config(
             cli_forced_codegen_units: codegen_units,
             cli_forced_thinlto_off: disable_thinlto,
             remap_path_prefix,
+            edition,
         },
         cfg,
     )
@@ -2296,11 +2318,12 @@ mod dep_tracking {
     use std::hash::Hash;
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
-    use super::{CrateType, DebugInfoLevel, Edition, ErrorOutputType, Lto, OptLevel, OutputTypes,
+    use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes,
                 Passes, Sanitizer};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_back::{PanicStrategy, RelroLevel};
     use rustc_back::target::TargetTriple;
+    use syntax::edition::Edition;
 
     pub trait DepTrackingHash {
         fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
@@ -2359,8 +2382,8 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
     impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
     impl_dep_tracking_hash_via_hash!(Sanitizer);
     impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
-    impl_dep_tracking_hash_via_hash!(Edition);
     impl_dep_tracking_hash_via_hash!(TargetTriple);
+    impl_dep_tracking_hash_via_hash!(Edition);
 
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
@@ -2433,6 +2456,7 @@ mod tests {
     use super::{Externs, OutputType, OutputTypes};
     use rustc_back::{PanicStrategy, RelroLevel};
     use syntax::symbol::Symbol;
+    use syntax::edition::{Edition, DEFAULT_EDITION};
     use syntax;
 
     fn optgroups() -> getopts::Options {
@@ -3077,4 +3101,17 @@ fn test_debugging_options_tracking_hash() {
         opts.debugging_opts.relro_level = Some(RelroLevel::Full);
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
     }
+
+    #[test]
+    fn test_edition_parsing() {
+        // test default edition
+        let options = super::basic_options();
+        assert!(options.edition == DEFAULT_EDITION);
+
+        let matches = optgroups()
+            .parse(&["--edition=2018".to_string()])
+            .unwrap();
+        let (sessopts, _) = build_session_options_and_crate_config(&matches);
+        assert!(sessopts.edition == Edition::Edition2018)
+    }
 }
index 32de006459d32ca1837ad9ed54c93ae5f93b3269..5e4dee7fb60ca64bb54cde363b561a1d6431eede 100644 (file)
@@ -26,7 +26,7 @@
 use util::common::{duration_to_secs_str, ErrorReported};
 use util::common::ProfileQueriesMsg;
 
-use rustc_data_structures::sync::{Lrc, Lock, LockCell, OneThread, Once};
+use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
 
 use syntax::ast::NodeId;
 use errors::{self, DiagnosticBuilder, DiagnosticId};
@@ -83,13 +83,13 @@ pub struct Session {
 
     // FIXME: lint_store and buffered_lints are not thread-safe,
     // but are only used in a single thread
-    pub lint_store: OneThread<RefCell<lint::LintStore>>,
-    pub buffered_lints: OneThread<RefCell<Option<lint::LintBuffer>>>,
+    pub lint_store: RwLock<lint::LintStore>,
+    pub buffered_lints: Lock<Option<lint::LintBuffer>>,
 
     /// Set of (DiagnosticId, Option<Span>, message) tuples tracking
     /// (sub)diagnostics that have been set once, but should not be set again,
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
-    pub one_time_diagnostics: RefCell<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
+    pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
     pub plugin_attributes: OneThread<RefCell<Vec<(String, AttributeType)>>>,
     pub crate_types: Once<Vec<config::CrateType>>,
@@ -929,16 +929,16 @@ pub fn codegen_units(&self) -> usize {
     }
 
     pub fn teach(&self, code: &DiagnosticId) -> bool {
-        self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code)
+        self.opts.debugging_opts.teach && self.parse_sess.span_diagnostic.must_teach(code)
     }
 
     /// Are we allowed to use features from the Rust 2018 edition?
     pub fn rust_2018(&self) -> bool {
-        self.opts.debugging_opts.edition >= Edition::Edition2018
+        self.opts.edition >= Edition::Edition2018
     }
 
     pub fn edition(&self) -> Edition {
-        self.opts.debugging_opts.edition
+        self.opts.edition
     }
 }
 
@@ -983,7 +983,7 @@ pub fn build_session_with_codemap(
 
     let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
 
-    let emitter: Box<dyn Emitter> =
+    let emitter: Box<dyn Emitter + sync::Send> =
         match (sopts.error_format, emitter_dest) {
             (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
                 EmitterWriter::stderr(
@@ -1089,9 +1089,9 @@ pub fn build_session_(
         default_sysroot,
         local_crate_source_file,
         working_dir,
-        lint_store: OneThread::new(RefCell::new(lint::LintStore::new())),
-        buffered_lints: OneThread::new(RefCell::new(Some(lint::LintBuffer::new()))),
-        one_time_diagnostics: RefCell::new(FxHashSet()),
+        lint_store: RwLock::new(lint::LintStore::new()),
+        buffered_lints: Lock::new(Some(lint::LintBuffer::new())),
+        one_time_diagnostics: Lock::new(FxHashSet()),
         plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
         plugin_attributes: OneThread::new(RefCell::new(Vec::new())),
         crate_types: Once::new(),
@@ -1188,7 +1188,7 @@ pub enum IncrCompSession {
 }
 
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
-    let emitter: Box<dyn Emitter> = match output {
+    let emitter: Box<dyn Emitter + sync::Send> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
@@ -1203,7 +1203,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
 }
 
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
-    let emitter: Box<dyn Emitter> = match output {
+    let emitter: Box<dyn Emitter + sync::Send> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
index 32fd93cf20a1f7599175205ec62829c553e09b1b..8d2398d34090d8d6f8ddc327150ef42466141217 100644 (file)
@@ -266,6 +266,7 @@ pub enum DomainGoal<'tcx> {
     WellFormed(WhereClauseAtom<'tcx>),
     FromEnv(WhereClauseAtom<'tcx>),
     WellFormedTy(Ty<'tcx>),
+    Normalize(ty::ProjectionPredicate<'tcx>),
     FromEnvTy(Ty<'tcx>),
     RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
     TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
index 523cd42940e27b7ef3798476ad2f06d23fcc271a..31c5bf1bbad84fd45870dd2b302f4b283d4e72bb 100644 (file)
@@ -450,6 +450,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
             FromEnv(Implemented(trait_ref)) => write!(fmt, "FromEnv({})", trait_ref),
             FromEnv(ProjectionEq(projection)) => write!(fmt, "FromEnv({})", projection),
             WellFormedTy(ty) => write!(fmt, "WellFormed({})", ty),
+            Normalize(projection) => write!(fmt, "Normalize({})", projection),
             FromEnvTy(ty) => write!(fmt, "FromEnv({})", ty),
             RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
             TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
@@ -538,6 +539,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
         (traits::DomainGoal::WellFormed)(wc),
         (traits::DomainGoal::FromEnv)(wc),
         (traits::DomainGoal::WellFormedTy)(ty),
+        (traits::DomainGoal::Normalize)(projection),
         (traits::DomainGoal::FromEnvTy)(ty),
         (traits::DomainGoal::RegionOutlives)(predicate),
         (traits::DomainGoal::TypeOutlives)(predicate),
index ed3332f32d02fd4648a4611086b25276fd0189a9..f3a2aa519465c9933e5269b10c287c571fc09dc9 100644 (file)
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
                                            StableHasher, StableHasherResult,
                                            StableVec};
-use arena::{TypedArena, DroplessArena};
+use arena::{TypedArena, SyncDroplessArena};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::sync::{Lrc, Lock};
 use std::any::Any;
 use std::borrow::Borrow;
-use std::cell::Cell;
 use std::cmp::Ordering;
 use std::collections::hash_map::{self, Entry};
 use std::hash::{Hash, Hasher};
 
 pub struct AllArenas<'tcx> {
     pub global: GlobalArenas<'tcx>,
-    pub interner: DroplessArena,
+    pub interner: SyncDroplessArena,
 }
 
 impl<'tcx> AllArenas<'tcx> {
     pub fn new() -> Self {
         AllArenas {
             global: GlobalArenas::new(),
-            interner: DroplessArena::new(),
+            interner: SyncDroplessArena::new(),
         }
     }
 }
@@ -130,7 +129,7 @@ pub fn new() -> GlobalArenas<'tcx> {
 
 pub struct CtxtInterners<'tcx> {
     /// The arena that types, regions, etc are allocated from
-    arena: &'tcx DroplessArena,
+    arena: &'tcx SyncDroplessArena,
 
     /// Specifically use a speedy hash algorithm for these hash sets,
     /// they're accessed quite often.
@@ -147,7 +146,7 @@ pub struct CtxtInterners<'tcx> {
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
-    fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
+    fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
         CtxtInterners {
             arena,
             type_: Default::default(),
@@ -174,10 +173,10 @@ fn intern_ty(&self, st: TypeVariants<'tcx>,
                 return ty;
             }
             let global_interner = global_interners.map(|interners| {
-                interners.type_.borrow_mut()
+                (interners.type_.borrow_mut(), &interners.arena)
             });
-            if let Some(ref interner) = global_interner {
-                if let Some(&Interned(ty)) = interner.get(&st) {
+            if let Some((ref type_, _)) = global_interner {
+                if let Some(&Interned(ty)) = type_.get(&st) {
                     return ty;
                 }
             }
@@ -193,18 +192,18 @@ fn intern_ty(&self, st: TypeVariants<'tcx>,
             // determine that all contents are in the global tcx.
             // See comments on Lift for why we can't use that.
             if !flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
-                if let Some(interner) = global_interners {
+                if let Some((mut type_, arena)) = global_interner {
                     let ty_struct: TyS<'gcx> = unsafe {
                         mem::transmute(ty_struct)
                     };
-                    let ty: Ty<'gcx> = interner.arena.alloc(ty_struct);
-                    global_interner.unwrap().insert(Interned(ty));
+                    let ty: Ty<'gcx> = arena.alloc(ty_struct);
+                    type_.insert(Interned(ty));
                     return ty;
                 }
             } else {
                 // Make sure we don't end up with inference
                 // types/regions in the global tcx.
-                if global_interners.is_none() {
+                if global_interner.is_none() {
                     drop(interner);
                     bug!("Attempted to intern `{:?}` which contains \
                           inference types/regions in the global type context",
@@ -915,9 +914,6 @@ pub struct GlobalCtxt<'tcx> {
     /// Data layout specification for the current target.
     pub data_layout: TargetDataLayout,
 
-    /// Used to prevent layout from recursing too deeply.
-    pub layout_depth: Cell<usize>,
-
     stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
 
     pub interpret_interner: InterpretInterner<'tcx>,
@@ -1292,7 +1288,6 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             crate_name: Symbol::intern(crate_name),
             data_layout,
             layout_interner: Lock::new(FxHashSet()),
-            layout_depth: Cell::new(0),
             stability_interner: Lock::new(FxHashSet()),
             interpret_interner: Default::default(),
             tx_to_llvm_workers: Lock::new(tx),
@@ -1464,15 +1459,9 @@ pub fn serialize_query_result_cache<E>(self,
         self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder)
     }
 
-    /// If true, we should use NLL-style region checking instead of
-    /// lexical style.
-    pub fn nll(self) -> bool {
-        self.features().nll || self.sess.opts.debugging_opts.nll
-    }
-
     /// If true, we should use the MIR-based borrowck (we may *also* use
     /// the AST-based borrowck).
-    pub fn use_mir(self) -> bool {
+    pub fn use_mir_borrowck(self) -> bool {
         self.borrowck_mode().use_mir()
     }
 
@@ -1491,7 +1480,7 @@ pub fn borrowck_mode(&self) -> BorrowckMode {
             mode @ BorrowckMode::Compare => mode,
 
             mode @ BorrowckMode::Ast => {
-                if self.nll() {
+                if self.features().nll {
                     BorrowckMode::Mir
                 } else {
                     mode
@@ -1505,11 +1494,9 @@ pub fn borrowck_mode(&self) -> BorrowckMode {
     /// MIR borrowck, but not when NLL is used. They are also consumed
     /// by the validation stuff.
     pub fn emit_end_regions(self) -> bool {
-        // FIXME(#46875) -- we should not emit end regions when NLL is enabled,
-        // but for now we can't stop doing so because it causes false positives
         self.sess.opts.debugging_opts.emit_end_regions ||
             self.sess.opts.debugging_opts.mir_emit_validate > 0 ||
-            self.use_mir()
+            self.use_mir_borrowck()
     }
 
     #[inline]
@@ -1559,7 +1546,7 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
     /// Call the closure with a local `TyCtxt` using the given arena.
     pub fn enter_local<F, R>(
         &self,
-        arena: &'tcx DroplessArena,
+        arena: &'tcx SyncDroplessArena,
         f: F
     ) -> R
     where
@@ -1574,6 +1561,7 @@ pub fn enter_local<F, R>(
             let new_icx = ty::tls::ImplicitCtxt {
                 tcx,
                 query: icx.query.clone(),
+                layout_depth: icx.layout_depth,
             };
             ty::tls::enter_context(&new_icx, |new_icx| {
                 f(new_icx.tcx)
@@ -1768,6 +1756,9 @@ pub struct ImplicitCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
         /// The current query job, if any. This is updated by start_job in
         /// ty::maps::plumbing when executing a query
         pub query: Option<Lrc<maps::QueryJob<'gcx>>>,
+
+        /// Used to prevent layout from recursing too deeply.
+        pub layout_depth: usize,
     }
 
     // A thread local value which stores a pointer to the current ImplicitCtxt
@@ -1853,6 +1844,7 @@ pub fn enter_global<'gcx, F, R>(gcx: &GlobalCtxt<'gcx>, f: F) -> R
             let icx = ImplicitCtxt {
                 tcx,
                 query: None,
+                layout_depth: 0,
             };
             enter_context(&icx, |_| {
                 f(tcx)
@@ -2382,6 +2374,14 @@ pub fn mk_nil(self) -> Ty<'tcx> {
         self.intern_tup(&[])
     }
 
+    pub fn mk_diverging_default(self) -> Ty<'tcx> {
+        if self.features().never_type {
+            self.types.never
+        } else {
+            self.intern_tup(&[])
+        }
+    }
+
     pub fn mk_bool(self) -> Ty<'tcx> {
         self.mk_ty(TyBool)
     }
index 35ada4a7227e7d1c16a7bd44fae4ced3dbbc3c67..77e2e9447f1ed9143ee381324170506284b980cc 100644 (file)
@@ -896,21 +896,26 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
                         -> Result<&'tcx LayoutDetails, LayoutError<'tcx>>
 {
-    let (param_env, ty) = query.into_parts();
+    ty::tls::with_related_context(tcx, move |icx| {
+        let rec_limit = *tcx.sess.recursion_limit.get();
+        let (param_env, ty) = query.into_parts();
 
-    let rec_limit = *tcx.sess.recursion_limit.get();
-    let depth = tcx.layout_depth.get();
-    if depth > rec_limit {
-        tcx.sess.fatal(
-            &format!("overflow representing the type `{}`", ty));
-    }
+        if icx.layout_depth > rec_limit {
+            tcx.sess.fatal(
+                &format!("overflow representing the type `{}`", ty));
+        }
 
-    tcx.layout_depth.set(depth+1);
-    let cx = LayoutCx { tcx, param_env };
-    let layout = cx.layout_raw_uncached(ty);
-    tcx.layout_depth.set(depth);
+        // Update the ImplicitCtxt to increase the layout_depth
+        let icx = ty::tls::ImplicitCtxt {
+            layout_depth: icx.layout_depth + 1,
+            ..icx.clone()
+        };
 
-    layout
+        ty::tls::enter_context(&icx, |_| {
+            let cx = LayoutCx { tcx, param_env };
+            cx.layout_raw_uncached(ty)
+        })
+    })
 }
 
 pub fn provide(providers: &mut ty::maps::Providers) {
@@ -1700,18 +1705,19 @@ enum StructKind {
                     }
                 }
 
-                let discr = Scalar {
+                let tag_mask = !0u128 >> (128 - ity.size().bits());
+                let tag = Scalar {
                     value: Int(ity, signed),
-                    valid_range: (min as u128)..=(max as u128)
+                    valid_range: (min as u128 & tag_mask)..=(max as u128 & tag_mask),
                 };
-                let abi = if discr.value.size(dl) == size {
-                    Abi::Scalar(discr.clone())
+                let abi = if tag.value.size(dl) == size {
+                    Abi::Scalar(tag.clone())
                 } else {
                     Abi::Aggregate { sized: true }
                 };
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Tagged {
-                        discr,
+                        discr: tag,
                         variants
                     },
                     fields: FieldPlacement::Arbitrary {
index 664c84f5986608ac2e48b2952da6e788ce9ee4bc..fea7de955e0bfdc72fa713bd0c94a321010ac785 100644 (file)
@@ -283,12 +283,6 @@ fn describe(_: TyCtxt, _: DefId) -> String {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::item_body_nested_bodies<'tcx> {
-    fn describe(tcx: TyCtxt, def_id: DefId) -> String {
-        format!("nested item bodies of `{}`", tcx.item_path_str(def_id))
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("const checking if rvalue is promotable to static `{}`",
index 7d756fb16a453d0b03b4e82d1f1e82b0cef9df7d..374406158c1d51a5695dfd0ae615e4dd686d1e8c 100644 (file)
@@ -31,6 +31,7 @@ pub(super) enum QueryResult<'tcx, T> {
 /// A span and a query key
 #[derive(Clone, Debug)]
 pub struct QueryInfo<'tcx> {
+    /// The span for a reason this query was required
     pub span: Span,
     pub query: Query<'tcx>,
 }
@@ -73,13 +74,22 @@ pub(super) fn await<'lcx>(
             cycle.insert(0, job.info.clone());
 
             if &*job as *const _ == self as *const _ {
-                break;
+                // This is the end of the cycle
+                // The span entry we included was for the usage
+                // of the cycle itself, and not part of the cycle
+                // Replace it with the span which caused the cycle to form
+                cycle[0].span = span;
+                // Find out why the cycle itself was used
+                let usage = job.parent.as_ref().map(|parent| {
+                    (job.info.span, parent.info.query.clone())
+                });
+                return Err(CycleError { usage, cycle });
             }
 
             current_job = job.parent.clone();
         }
 
-        Err(CycleError { span, cycle })
+        panic!("did not find a cycle")
     }
 
     /// Signals to waiters that the query is complete.
index d317f5a494b782b2ab6d80f71f93500393b73762..0ab9f16dab481064f7b8b6330a2b5be32fb24eb1 100644 (file)
@@ -17,9 +17,8 @@
 use infer::canonical::{self, Canonical};
 use lint;
 use middle::borrowck::BorrowCheckResult;
-use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary,
-                     ExternBodyNestedBodies, ForeignModule};
-use middle::cstore::{NativeLibraryKind, DepKind, CrateSource, ExternConstBody};
+use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ForeignModule};
+use middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
 use middle::privacy::AccessLevels;
 use middle::reachable::ReachableSet;
 use middle::region;
     [] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>,
     [] fn trans_fn_attrs: trans_fn_attrs(DefId) -> TransFnAttrs,
     [] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
+    /// Gets the rendered value of the specified constant or associated constant.
+    /// Used by rustdoc.
+    [] fn rendered_const: RenderedConst(DefId) -> String,
     [] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
     [] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
-    [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
     [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
     [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>,
     [] fn is_mir_available: IsMirAvailable(DefId) -> bool,
     [] fn get_lang_items: get_lang_items_node(CrateNum) -> Lrc<LanguageItems>,
     [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Lrc<Vec<(DefId, usize)>>,
     [] fn missing_lang_items: MissingLangItems(CrateNum) -> Lrc<Vec<LangItem>>,
-    [] fn extern_const_body: ExternConstBody(DefId) -> ExternConstBody<'tcx>,
     [] fn visible_parent_map: visible_parent_map_node(CrateNum)
         -> Lrc<DefIdMap<DefId>>,
     [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool,
         substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
 
     [] fn target_features_whitelist:
-        target_features_whitelist_node(CrateNum) -> Lrc<FxHashSet<String>>,
+        target_features_whitelist_node(CrateNum) -> Lrc<FxHashMap<String, Option<String>>>,
 
     // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
     [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
index d60206ffd327cd5eace09920486608118a641b63..f88e33c708e3685027e0aade041adf1ee5243e11 100644 (file)
@@ -33,6 +33,7 @@
 use ty::maps::job::QueryResult;
 use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use ty::context::TyCtxt;
+use util::common::time;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
@@ -214,7 +215,7 @@ pub fn serialize<'a, 'tcx, E>(&self,
             // Encode query results
             let mut query_result_index = EncodedQueryResultIndex::new();
 
-            {
+            time(tcx.sess, "encode query results", || {
                 use ty::maps::queries::*;
                 let enc = &mut encoder;
                 let qri = &mut query_result_index;
@@ -258,7 +259,9 @@ pub fn serialize<'a, 'tcx, E>(&self,
                         }
                     }
                 }
-            }
+
+                Ok(())
+            })?;
 
             // Encode diagnostics
             let diagnostics_index = {
@@ -1125,6 +1128,11 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
           E: 'enc + TyEncoder,
           Q::Value: Encodable,
 {
+    let desc = &format!("encode_query_results for {}",
+        unsafe { ::std::intrinsics::type_name::<Q>() });
+
+    time(tcx.sess, desc, || {
+
     for (key, entry) in Q::get_cache_internal(tcx).map.iter() {
         if Q::cache_on_disk(key.clone()) {
             let entry = match *entry {
@@ -1143,4 +1151,5 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     Ok(())
+    })
 }
index efe7a56d8009709f8fdd460f5cdeb08fe49e0afd..8d6c7474a9f94f495569460e2938754f7651caba 100644 (file)
@@ -17,6 +17,7 @@
 use errors::Level;
 use ty::tls;
 use ty::{TyCtxt};
+use ty::maps::Query;
 use ty::maps::config::QueryDescription;
 use ty::maps::job::{QueryResult, QueryInfo};
 use ty::item_path;
@@ -63,7 +64,8 @@ fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
 
 #[derive(Clone)]
 pub(super) struct CycleError<'tcx> {
-    pub(super) span: Span,
+    /// The query and related span which uses the cycle
+    pub(super) usage: Option<(Span, Query<'tcx>)>,
     pub(super) cycle: Vec<QueryInfo<'tcx>>,
 }
 
@@ -79,33 +81,41 @@ pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub(super) fn report_cycle(self, CycleError { span, cycle: stack }: CycleError)
+    pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }: CycleError<'gcx>)
         -> DiagnosticBuilder<'a>
     {
         assert!(!stack.is_empty());
 
+        let fix_span = |span: Span, query: &Query<'gcx>| {
+            self.sess.codemap().def_span(query.default_span(self, span))
+        };
+
         // Disable naming impls with types in this path, since that
         // sometimes cycles itself, leading to extra cycle errors.
         // (And cycle errors around impls tend to occur during the
         // collect/coherence phases anyhow.)
         item_path::with_forced_impl_filename_line(|| {
-            let span = self.sess.codemap().def_span(span);
-            let mut err =
-                struct_span_err!(self.sess, span, E0391,
-                                 "cyclic dependency detected");
-            err.span_label(span, "cyclic reference");
-
-            err.span_note(self.sess.codemap().def_span(stack[0].span),
-                          &format!("the cycle begins when {}...", stack[0].query.describe(self)));
-
-            for &QueryInfo { span, ref query, .. } in &stack[1..] {
-                err.span_note(self.sess.codemap().def_span(span),
-                              &format!("...which then requires {}...", query.describe(self)));
+            let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
+            let mut err = struct_span_err!(self.sess,
+                                           span,
+                                           E0391,
+                                           "cycle detected when {}",
+                                           stack[0].query.describe(self));
+
+            for i in 1..stack.len() {
+                let query = &stack[i].query;
+                let span = fix_span(stack[(i + 1) % stack.len()].span, query);
+                err.span_note(span, &format!("...which requires {}...", query.describe(self)));
             }
 
-            err.note(&format!("...which then again requires {}, completing the cycle.",
+            err.note(&format!("...which again requires {}, completing the cycle",
                               stack[0].query.describe(self)));
 
+            if let Some((span, query)) = usage {
+                err.span_note(fix_span(span, &query),
+                              &format!("cycle used when {}", query.describe(self)));
+            }
+
             return err
         })
     }
@@ -266,6 +276,22 @@ pub fn describe(&self, tcx: TyCtxt) -> String {
                     r
                 }
             }
+
+            // FIXME(eddyb) Get more valid Span's on queries.
+            pub fn default_span(&self, tcx: TyCtxt<'_, $tcx, '_>, span: Span) -> Span {
+                if span != DUMMY_SP {
+                    return span;
+                }
+                // The def_span query is used to calculate default_span,
+                // so exit to avoid infinite recursion
+                match *self {
+                    Query::def_span(..) => return span,
+                    _ => ()
+                }
+                match *self {
+                    $(Query::$name(key) => key.default_span(tcx),)*
+                }
+            }
         }
 
         pub mod queries {
@@ -303,7 +329,7 @@ fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode {
             /// If the query already executed and panicked, this will fatal error / silently panic
             fn try_get_lock(
                 tcx: TyCtxt<'a, $tcx, 'lcx>,
-                mut span: Span,
+                span: Span,
                 key: &$K
             ) -> TryGetLock<'a, $tcx, $V, Self>
             {
@@ -329,13 +355,6 @@ fn try_get_lock(
                     };
                     mem::drop(lock);
 
-                    // This just matches the behavior of `try_get_with` so the span when
-                    // we await matches the span we would use when executing.
-                    // See the FIXME there.
-                    if span == DUMMY_SP && stringify!($name) != "def_span" {
-                        span = key.default_span(tcx);
-                    }
-
                     if let Err(cycle) = job.await(tcx, span) {
                         return TryGetLock::JobCompleted(Err(cycle));
                     }
@@ -343,7 +362,7 @@ fn try_get_lock(
             }
 
             fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                            mut span: Span,
+                            span: Span,
                             key: $K)
                             -> Result<$V, CycleError<$tcx>>
             {
@@ -377,18 +396,6 @@ macro_rules! get_lock_or_return {
 
                 let mut lock = get_lock_or_return!();
 
-                // FIXME(eddyb) Get more valid Span's on queries.
-                // def_span guard is necessary to prevent a recursive loop,
-                // default_span calls def_span query internally.
-                if span == DUMMY_SP && stringify!($name) != "def_span" {
-                    // This might deadlock if we hold the map lock since we might be
-                    // waiting for the def_span query and switch to some other fiber
-                    // So we drop the lock here and reacquire it
-                    mem::drop(lock);
-                    span = key.default_span(tcx);
-                    lock = get_lock_or_return!();
-                }
-
                 // Fast path for when incr. comp. is off. `to_dep_node` is
                 // expensive for some DepKinds.
                 if !tcx.dep_graph.is_fully_enabled() {
@@ -522,6 +529,7 @@ fn start_job<F, R>(tcx: TyCtxt<'_, $tcx, 'lcx>,
                         let icx = ty::tls::ImplicitCtxt {
                             tcx,
                             query: Some(job.clone()),
+                            layout_depth: icx.layout_depth,
                         };
 
                         // Use the ImplicitCtxt while we execute the query
@@ -1040,7 +1048,6 @@ macro_rules! force {
         DepKind::LookupDeprecationEntry => {
             force!(lookup_deprecation_entry, def_id!());
         }
-        DepKind::ItemBodyNestedBodies => { force!(item_body_nested_bodies, def_id!()); }
         DepKind::ConstIsRvaluePromotableToStatic => {
             force!(const_is_rvalue_promotable_to_static, def_id!());
         }
@@ -1055,6 +1062,7 @@ macro_rules! force {
         DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
         DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }
         DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
+        DepKind::RenderedConst => { force!(rendered_const, def_id!()); }
         DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
         DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
         DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); }
@@ -1111,7 +1119,6 @@ macro_rules! force {
         DepKind::GetLangItems => { force!(get_lang_items, LOCAL_CRATE); }
         DepKind::DefinedLangItems => { force!(defined_lang_items, krate!()); }
         DepKind::MissingLangItems => { force!(missing_lang_items, krate!()); }
-        DepKind::ExternConstBody => { force!(extern_const_body, def_id!()); }
         DepKind::VisibleParentMap => { force!(visible_parent_map, LOCAL_CRATE); }
         DepKind::MissingExternCrateItem => {
             force!(missing_extern_crate_item, krate!());
index d68393956efd1a51ece763e6e8e1314eb1cae533..310fcbcfcb374ac5cbbbc3c728ad34c5b18bfa71 100644 (file)
@@ -1550,7 +1550,7 @@ pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
         }
     }
 
-    /// Returns the type of ty[i]
+    /// Returns the type of `ty[i]`.
     pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
         match self.sty {
             TyArray(ty, _) | TySlice(ty) => Some(ty),
index 305502e7f063b562ac1d298925911ebcc325ce44..9338d000c1291aeb24dff3b95cf3e29499b66630 100644 (file)
 use rustc::middle::allocator::AllocatorKind;
 use rustc_errors;
 use syntax::abi::Abi;
-use syntax::ast::{Crate, Attribute, LitKind, StrStyle};
-use syntax::ast::{Unsafety, Constness, Generics, Mutability, Ty, Mac, Arg};
-use syntax::ast::{self, Ident, Item, ItemKind, TyKind, VisibilityKind, Expr};
+use syntax::ast::{Attribute, Crate, LitKind, StrStyle};
+use syntax::ast::{Arg, Constness, Generics, Mac, Mutability, Ty, Unsafety};
+use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind};
 use syntax::attr;
 use syntax::codemap::{dummy_spanned, respan};
-use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute};
+use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::base::Resolver;
 use syntax::ext::build::AstBuilder;
 
 use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
 
-pub fn modify(sess: &ParseSess,
-              resolver: &mut Resolver,
-              krate: Crate,
-              handler: &rustc_errors::Handler) -> ast::Crate {
+pub fn modify(
+    sess: &ParseSess,
+    resolver: &mut Resolver,
+    krate: Crate,
+    handler: &rustc_errors::Handler,
+) -> ast::Crate {
     ExpandAllocatorDirectives {
         handler,
         sess,
@@ -55,20 +57,24 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
         let name = if attr::contains_name(&item.attrs, "global_allocator") {
             "global_allocator"
         } else {
-            return fold::noop_fold_item(item, self)
+            return fold::noop_fold_item(item, self);
         };
         match item.node {
             ItemKind::Static(..) => {}
             _ => {
-                self.handler.span_err(item.span, "allocators must be statics");
-                return SmallVector::one(item)
+                self.handler
+                    .span_err(item.span, "allocators must be statics");
+                return SmallVector::one(item);
             }
         }
 
         if self.found {
-            self.handler.span_err(item.span, "cannot define more than one \
-                                              #[global_allocator]");
-            return SmallVector::one(item)
+            self.handler.span_err(
+                item.span,
+                "cannot define more than one \
+                 #[global_allocator]",
+            );
+            return SmallVector::one(item);
         }
         self.found = true;
 
@@ -80,7 +86,7 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
                 span: None,
                 allow_internal_unstable: true,
                 allow_internal_unsafe: false,
-            }
+            },
         });
         let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
         let ecfg = ExpansionConfig::default(name.to_string());
@@ -91,10 +97,7 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
             core: Ident::from_str("core"),
             cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
         };
-        let super_path = f.cx.path(f.span, vec![
-            Ident::from_str("super"),
-            f.global,
-        ]);
+        let super_path = f.cx.path(f.span, vec![Ident::from_str("super"), f.global]);
         let mut items = vec![
             f.cx.item_extern_crate(f.span, f.core),
             f.cx.item_use_simple(
@@ -114,7 +117,7 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
         let mut ret = SmallVector::new();
         ret.push(item);
         ret.push(module);
-        return ret
+        return ret;
     }
 
     fn fold_mac(&mut self, mac: Mac) -> Mac {
@@ -139,30 +142,39 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> P<Item> {
             i += 1;
             name
         };
-        let args = method.inputs.iter().map(|ty| {
-            self.arg_ty(ty, &mut abi_args, mk)
-        }).collect();
+        let args = method
+            .inputs
+            .iter()
+            .map(|ty| self.arg_ty(ty, &mut abi_args, mk))
+            .collect();
         let result = self.call_allocator(method.name, args);
         let (output_ty, output_expr) = self.ret_ty(&method.output, result);
-        let kind = ItemKind::Fn(self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
-                                Unsafety::Unsafe,
-                                dummy_spanned(Constness::NotConst),
-                                Abi::Rust,
-                                Generics::default(),
-                                self.cx.block_expr(output_expr));
-        self.cx.item(self.span,
-                     Ident::from_str(&self.kind.fn_name(method.name)),
-                     self.attrs(),
-                     kind)
+        let kind = ItemKind::Fn(
+            self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
+            Unsafety::Unsafe,
+            dummy_spanned(Constness::NotConst),
+            Abi::Rust,
+            Generics::default(),
+            self.cx.block_expr(output_expr),
+        );
+        self.cx.item(
+            self.span,
+            Ident::from_str(&self.kind.fn_name(method.name)),
+            self.attrs(),
+            kind,
+        )
     }
 
     fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
-        let method = self.cx.path(self.span, vec![
-            self.core,
-            Ident::from_str("alloc"),
-            Ident::from_str("GlobalAlloc"),
-            Ident::from_str(method),
-        ]);
+        let method = self.cx.path(
+            self.span,
+            vec![
+                self.core,
+                Ident::from_str("alloc"),
+                Ident::from_str("GlobalAlloc"),
+                Ident::from_str(method),
+            ],
+        );
         let method = self.cx.expr_path(method);
         let allocator = self.cx.path_ident(self.span, self.global);
         let allocator = self.cx.expr_path(allocator);
@@ -189,10 +201,12 @@ fn attrs(&self) -> Vec<Attribute> {
         ]
     }
 
-    fn arg_ty(&self,
-              ty: &AllocatorTy,
-              args: &mut Vec<Arg>,
-              ident: &mut FnMut() -> Ident) -> P<Expr> {
+    fn arg_ty(
+        &self,
+        ty: &AllocatorTy,
+        args: &mut Vec<Arg>,
+        ident: &mut FnMut() -> Ident,
+    ) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
                 let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
@@ -202,18 +216,19 @@ fn arg_ty(&self,
                 args.push(self.cx.arg(self.span, size, ty_usize.clone()));
                 args.push(self.cx.arg(self.span, align, ty_usize));
 
-                let layout_new = self.cx.path(self.span, vec![
-                    self.core,
-                    Ident::from_str("alloc"),
-                    Ident::from_str("Layout"),
-                    Ident::from_str("from_size_align_unchecked"),
-                ]);
+                let layout_new = self.cx.path(
+                    self.span,
+                    vec![
+                        self.core,
+                        Ident::from_str("alloc"),
+                        Ident::from_str("Layout"),
+                        Ident::from_str("from_size_align_unchecked"),
+                    ],
+                );
                 let layout_new = self.cx.expr_path(layout_new);
                 let size = self.cx.expr_ident(self.span, size);
                 let align = self.cx.expr_ident(self.span, align);
-                let layout = self.cx.expr_call(self.span,
-                                               layout_new,
-                                               vec![size, align]);
+                let layout = self.cx.expr_call(self.span, layout_new, vec![size, align]);
                 layout
             }
 
@@ -230,9 +245,7 @@ fn arg_ty(&self,
                 self.cx.expr_ident(self.span, ident)
             }
 
-            AllocatorTy::ResultPtr |
-            AllocatorTy::Bang |
-            AllocatorTy::Unit => {
+            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
                 panic!("can't convert AllocatorTy to an argument")
             }
         }
@@ -249,17 +262,9 @@ fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
                 (self.ptr_u8(), expr)
             }
 
-            AllocatorTy::Bang => {
-                (self.cx.ty(self.span, TyKind::Never), expr)
-            }
+            AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
 
-            AllocatorTy::Unit => {
-                (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr)
-            }
-
-            AllocatorTy::Layout |
-            AllocatorTy::Usize |
-            AllocatorTy::Ptr => {
+            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                 panic!("can't convert AllocatorTy to an output")
             }
         }
@@ -277,11 +282,14 @@ fn ptr_u8(&self) -> P<Ty> {
     }
 
     fn ptr_opaque(&self) -> P<Ty> {
-        let opaque = self.cx.path(self.span, vec![
-            self.core,
-            Ident::from_str("alloc"),
-            Ident::from_str("Opaque"),
-        ]);
+        let opaque = self.cx.path(
+            self.span,
+            vec![
+                self.core,
+                Ident::from_str("alloc"),
+                Ident::from_str("Opaque"),
+            ],
+        );
         let ty_opaque = self.cx.ty_path(opaque);
         self.cx.ty_ptr(self.span, ty_opaque, Mutability::Mutable)
     }
index 706eab72d44cc8af296a9fec233d3bf5babeb347..969086815ded4777c3cc6939d9e3be4fc58be6b0 100644 (file)
         inputs: &[AllocatorTy::Layout],
         output: AllocatorTy::ResultPtr,
     },
-    AllocatorMethod {
-        name: "oom",
-        inputs: &[],
-        output: AllocatorTy::Bang,
-    },
     AllocatorMethod {
         name: "dealloc",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
@@ -52,7 +47,6 @@ pub struct AllocatorMethod {
 }
 
 pub enum AllocatorTy {
-    Bang,
     Layout,
     Ptr,
     ResultPtr,
index 0f051ea5981ca4eefe254c264a179b4343640ad0..08438805a703e759f5823ab6b4a1a7b830dc616b 100644 (file)
@@ -45,6 +45,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![forbid(unsafe_code)]
 
+#![feature(try_from)]
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
index 49baa1b96cee3b4bdf61dec87801898f386f7ea1..3660bf7bea917fe7cda7b3c90ba5cc9b794fdce1 100644 (file)
@@ -20,5 +20,6 @@ pub fn opts() -> TargetOptions {
     base.is_like_android = true;
     base.position_independent_executables = true;
     base.has_elf_tls = false;
+    base.requires_uwtable = true;
     base
 }
index 592b27ac641b5204d2af6ec4a16cce4d625e938c..e46266b576e244e5a90bf089d9708735a3f063c5 100644 (file)
@@ -481,6 +481,11 @@ pub struct TargetOptions {
 
     /// Whether a .debug_gdb_scripts section will be added to the output object file
     pub emit_debug_gdb_scripts: bool,
+
+    /// Whether or not to unconditionally `uwtable` attributes on functions,
+    /// typically because the platform needs to unwind for things like stack
+    /// unwinders.
+    pub requires_uwtable: bool,
 }
 
 impl Default for TargetOptions {
@@ -554,6 +559,7 @@ fn default() -> TargetOptions {
             default_hidden_visibility: false,
             embed_bitcode: false,
             emit_debug_gdb_scripts: true,
+            requires_uwtable: false,
         }
     }
 }
@@ -804,6 +810,7 @@ macro_rules! key {
         key!(default_hidden_visibility, bool);
         key!(embed_bitcode, bool);
         key!(emit_debug_gdb_scripts, bool);
+        key!(requires_uwtable, bool);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1008,6 +1015,7 @@ macro_rules! target_option_val {
         target_option_val!(default_hidden_visibility);
         target_option_val!(embed_bitcode);
         target_option_val!(emit_debug_gdb_scripts);
+        target_option_val!(requires_uwtable);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
index 971b21e062f69415d858743eff0d3187cb86f993..4b4fb27caa839baa4d498deab92fe561c2f2b5fd 100644 (file)
@@ -103,6 +103,7 @@ pub fn opts() -> TargetOptions {
         custom_unwind_resume: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
+        requires_uwtable: true,
 
         .. Default::default()
     }
index 06e879bec3492310184cce57472dfef0e0b2e535..fee5a0284c80610993a0f7df8946ff222022b140 100644 (file)
@@ -35,6 +35,7 @@ pub fn opts() -> TargetOptions {
         crt_static_respected: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
+        requires_uwtable: true,
 
         .. Default::default()
     }
index db1cfb5c767687cf92613bb333035f980cdb2592..7b33ee40d8cdb9d8e8ca1f8f987eef86b783f7b3 100644 (file)
@@ -207,7 +207,7 @@ pub struct Iter<A: Array> {
 
 impl<A: Array> Drop for Iter<A> {
     fn drop(&mut self) {
-        for _ in self {}
+        self.for_each(drop);
     }
 }
 
@@ -251,7 +251,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 impl<'a, A: Array> Drop for Drain<'a, A> {
     fn drop(&mut self) {
         // exhaust self first
-        while let Some(_) = self.next() {}
+        self.for_each(drop);
 
         if self.tail_len > 0 {
             unsafe {
index 4071b804def6c4f77f72be1b54f3ec4d816e7187..2c781fda4ed03a38a39689e9a6794934b3bad901 100644 (file)
 use rustc::ich::Fingerprint;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_mir as mir;
-use rustc::session::{Session, CompileResult, CrateDisambiguator};
+use rustc::session::{CompileResult, CrateDisambiguator, Session};
 use rustc::session::CompileIncomplete;
 use rustc::session::config::{self, Input, OutputFilenames, OutputType};
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
-use rustc::middle::{self, stability, reachable, resolve_lifetime};
+use rustc::middle::{self, reachable, resolve_lifetime, stability};
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
-use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
+use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
 use rustc::traits;
-use rustc::util::common::{ErrorReported, time, install_panic_hook};
+use rustc::util::common::{install_panic_hook, time, ErrorReported};
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
 use rustc_incremental;
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
-use rustc_passes::{self, ast_validation, loops, rvalue_promotion, hir_stats};
+use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion};
 use super::Compilation;
 
 use serialize::json;
 
 use std::any::Any;
 use std::env;
-use std::ffi::{OsString, OsStr};
+use std::ffi::{OsStr, OsString};
 use std::fs;
 use std::io::{self, Write};
 use std::iter;
 
 use profile;
 
-pub fn compile_input(trans: Box<TransCrate>,
-                     sess: &Session,
-                     cstore: &CStore,
-                     input_path: &Option<PathBuf>,
-                     input: &Input,
-                     outdir: &Option<PathBuf>,
-                     output: &Option<PathBuf>,
-                     addl_plugins: Option<Vec<String>>,
-                     control: &CompileController) -> CompileResult {
+pub fn compile_input(
+    trans: Box<TransCrate>,
+    sess: &Session,
+    cstore: &CStore,
+    input_path: &Option<PathBuf>,
+    input: &Input,
+    outdir: &Option<PathBuf>,
+    output: &Option<PathBuf>,
+    addl_plugins: Option<Vec<String>>,
+    control: &CompileController,
+) -> CompileResult {
     macro_rules! controller_entry_point {
         ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
             let state = &mut $make_state;
@@ -106,16 +108,9 @@ macro_rules! controller_entry_point {
         };
 
         let (krate, registry) = {
-            let mut compile_state = CompileState::state_after_parse(input,
-                                                                    sess,
-                                                                    outdir,
-                                                                    output,
-                                                                    krate,
-                                                                    &cstore);
-            controller_entry_point!(after_parse,
-                                    sess,
-                                    compile_state,
-                                    Ok(()));
+            let mut compile_state =
+                CompileState::state_after_parse(input, sess, outdir, output, krate, &cstore);
+            controller_entry_point!(after_parse, sess, compile_state, Ok(()));
 
             (compile_state.krate.unwrap(), compile_state.registry)
         };
@@ -125,7 +120,13 @@ macro_rules! controller_entry_point {
             ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
         install_panic_hook();
 
-        let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
+        let ExpansionResult {
+            expanded_crate,
+            defs,
+            analysis,
+            resolutions,
+            mut hir_forest,
+        } = {
             phase_2_configure_and_expand(
                 sess,
                 &cstore,
@@ -136,11 +137,17 @@ macro_rules! controller_entry_point {
                 control.make_glob_map,
                 |expanded_crate| {
                     let mut state = CompileState::state_after_expand(
-                        input, sess, outdir, output, &cstore, expanded_crate, &crate_name,
+                        input,
+                        sess,
+                        outdir,
+                        output,
+                        &cstore,
+                        expanded_crate,
+                        &crate_name,
                     );
                     controller_entry_point!(after_expand, sess, state, Ok(()));
                     Ok(())
-                }
+                },
             )?
         };
 
@@ -152,24 +159,28 @@ macro_rules! controller_entry_point {
                 if output_contains_path(&output_paths, input_path) {
                     sess.err(&format!(
                         "the input file \"{}\" would be overwritten by the generated \
-                        executable",
-                        input_path.display()));
+                         executable",
+                        input_path.display()
+                    ));
                     return Err(CompileIncomplete::Stopped);
                 }
                 if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
                     sess.err(&format!(
                         "the generated executable for the input file \"{}\" conflicts with the \
-                        existing directory \"{}\"",
-                        input_path.display(), dir_path.display()));
+                         existing directory \"{}\"",
+                        input_path.display(),
+                        dir_path.display()
+                    ));
                     return Err(CompileIncomplete::Stopped);
                 }
             }
         }
 
         write_out_deps(sess, &outputs, &output_paths);
-        if sess.opts.output_types.contains_key(&OutputType::DepInfo) &&
-            sess.opts.output_types.keys().count() == 1 {
-            return Ok(())
+        if sess.opts.output_types.contains_key(&OutputType::DepInfo)
+            && sess.opts.output_types.len() == 1
+        {
+            return Ok(());
         }
 
         if let &Some(ref dir) = outdir {
@@ -182,28 +193,32 @@ macro_rules! controller_entry_point {
         let arenas = AllArenas::new();
 
         // Construct the HIR map
-        let hir_map = time(sess,
-                           "indexing hir",
-                           || hir_map::map_crate(sess, cstore, &mut hir_forest, &defs));
+        let hir_map = time(sess, "indexing hir", || {
+            hir_map::map_crate(sess, cstore, &mut hir_forest, &defs)
+        });
 
         {
             hir_map.dep_graph.assert_ignored();
-            controller_entry_point!(after_hir_lowering,
-                                    sess,
-                                    CompileState::state_after_hir_lowering(input,
-                                                                  sess,
-                                                                  outdir,
-                                                                  output,
-                                                                  &arenas,
-                                                                  &cstore,
-                                                                  &hir_map,
-                                                                  &analysis,
-                                                                  &resolutions,
-                                                                  &expanded_crate,
-                                                                  &hir_map.krate(),
-                                                                  &outputs,
-                                                                  &crate_name),
-                                    Ok(()));
+            controller_entry_point!(
+                after_hir_lowering,
+                sess,
+                CompileState::state_after_hir_lowering(
+                    input,
+                    sess,
+                    outdir,
+                    output,
+                    &arenas,
+                    &cstore,
+                    &hir_map,
+                    &analysis,
+                    &resolutions,
+                    &expanded_crate,
+                    &hir_map.krate(),
+                    &outputs,
+                    &crate_name
+                ),
+                Ok(())
+            );
         }
 
         let opt_crate = if control.keep_ast {
@@ -213,60 +228,64 @@ macro_rules! controller_entry_point {
             None
         };
 
-        phase_3_run_analysis_passes(&*trans,
-                                    control,
-                                    sess,
-                                    cstore,
-                                    hir_map,
-                                    analysis,
-                                    resolutions,
-                                    &arenas,
-                                    &crate_name,
-                                    &outputs,
-                                    |tcx, analysis, rx, result| {
-            {
-                // Eventually, we will want to track plugins.
-                tcx.dep_graph.with_ignore(|| {
-                    let mut state = CompileState::state_after_analysis(input,
-                                                                       sess,
-                                                                       outdir,
-                                                                       output,
-                                                                       opt_crate,
-                                                                       tcx.hir.krate(),
-                                                                       &analysis,
-                                                                       tcx,
-                                                                       &crate_name);
-                    (control.after_analysis.callback)(&mut state);
-                });
-
-                if control.after_analysis.stop == Compilation::Stop {
-                    return result.and_then(|_| Err(CompileIncomplete::Stopped));
+        phase_3_run_analysis_passes(
+            &*trans,
+            control,
+            sess,
+            cstore,
+            hir_map,
+            analysis,
+            resolutions,
+            &arenas,
+            &crate_name,
+            &outputs,
+            |tcx, analysis, rx, result| {
+                {
+                    // Eventually, we will want to track plugins.
+                    tcx.dep_graph.with_ignore(|| {
+                        let mut state = CompileState::state_after_analysis(
+                            input,
+                            sess,
+                            outdir,
+                            output,
+                            opt_crate,
+                            tcx.hir.krate(),
+                            &analysis,
+                            tcx,
+                            &crate_name,
+                        );
+                        (control.after_analysis.callback)(&mut state);
+                    });
+
+                    if control.after_analysis.stop == Compilation::Stop {
+                        return result.and_then(|_| Err(CompileIncomplete::Stopped));
+                    }
                 }
-            }
 
-            result?;
+                result?;
 
-            if log_enabled!(::log::Level::Info) {
-                println!("Pre-trans");
-                tcx.print_debug_stats();
-            }
+                if log_enabled!(::log::Level::Info) {
+                    println!("Pre-trans");
+                    tcx.print_debug_stats();
+                }
 
-            let ongoing_trans = phase_4_translate_to_llvm(&*trans, tcx, rx);
+                let ongoing_trans = phase_4_translate_to_llvm(&*trans, tcx, rx);
 
-            if log_enabled!(::log::Level::Info) {
-                println!("Post-trans");
-                tcx.print_debug_stats();
-            }
+                if log_enabled!(::log::Level::Info) {
+                    println!("Post-trans");
+                    tcx.print_debug_stats();
+                }
 
-            if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
-                if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) {
-                    sess.err(&format!("could not emit MIR: {}", e));
-                    sess.abort_if_errors();
+                if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
+                    if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) {
+                        sess.err(&format!("could not emit MIR: {}", e));
+                        sess.abort_if_errors();
+                    }
                 }
-            }
 
-            Ok((outputs.clone(), ongoing_trans, tcx.dep_graph.clone()))
-        })??
+                Ok((outputs.clone(), ongoing_trans, tcx.dep_graph.clone()))
+            },
+        )??
     };
 
     if sess.opts.debugging_opts.print_type_sizes {
@@ -391,10 +410,7 @@ pub struct CompileState<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> CompileState<'a, 'tcx> {
-    fn empty(input: &'a Input,
-             session: &'tcx Session,
-             out_dir: &'a Option<PathBuf>)
-             -> Self {
+    fn empty(input: &'a Input, session: &'tcx Session, out_dir: &'a Option<PathBuf>) -> Self {
         CompileState {
             input,
             session,
@@ -415,13 +431,14 @@ fn empty(input: &'a Input,
         }
     }
 
-    fn state_after_parse(input: &'a Input,
-                         session: &'tcx Session,
-                         out_dir: &'a Option<PathBuf>,
-                         out_file: &'a Option<PathBuf>,
-                         krate: ast::Crate,
-                         cstore: &'tcx CStore)
-                         -> Self {
+    fn state_after_parse(
+        input: &'a Input,
+        session: &'tcx Session,
+        out_dir: &'a Option<PathBuf>,
+        out_file: &'a Option<PathBuf>,
+        krate: ast::Crate,
+        cstore: &'tcx CStore,
+    ) -> Self {
         CompileState {
             // Initialize the registry before moving `krate`
             registry: Some(Registry::new(&session, krate.span)),
@@ -432,14 +449,15 @@ fn state_after_parse(input: &'a Input,
         }
     }
 
-    fn state_after_expand(input: &'a Input,
-                          session: &'tcx Session,
-                          out_dir: &'a Option<PathBuf>,
-                          out_file: &'a Option<PathBuf>,
-                          cstore: &'tcx CStore,
-                          expanded_crate: &'a ast::Crate,
-                          crate_name: &'a str)
-                          -> Self {
+    fn state_after_expand(
+        input: &'a Input,
+        session: &'tcx Session,
+        out_dir: &'a Option<PathBuf>,
+        out_file: &'a Option<PathBuf>,
+        cstore: &'tcx CStore,
+        expanded_crate: &'a ast::Crate,
+        crate_name: &'a str,
+    ) -> Self {
         CompileState {
             crate_name: Some(crate_name),
             cstore: Some(cstore),
@@ -449,20 +467,21 @@ fn state_after_expand(input: &'a Input,
         }
     }
 
-    fn state_after_hir_lowering(input: &'a Input,
-                                session: &'tcx Session,
-                                out_dir: &'a Option<PathBuf>,
-                                out_file: &'a Option<PathBuf>,
-                                arenas: &'tcx AllArenas<'tcx>,
-                                cstore: &'tcx CStore,
-                                hir_map: &'a hir_map::Map<'tcx>,
-                                analysis: &'a ty::CrateAnalysis,
-                                resolutions: &'a Resolutions,
-                                krate: &'a ast::Crate,
-                                hir_crate: &'a hir::Crate,
-                                output_filenames: &'a OutputFilenames,
-                                crate_name: &'a str)
-                                -> Self {
+    fn state_after_hir_lowering(
+        input: &'a Input,
+        session: &'tcx Session,
+        out_dir: &'a Option<PathBuf>,
+        out_file: &'a Option<PathBuf>,
+        arenas: &'tcx AllArenas<'tcx>,
+        cstore: &'tcx CStore,
+        hir_map: &'a hir_map::Map<'tcx>,
+        analysis: &'a ty::CrateAnalysis,
+        resolutions: &'a Resolutions,
+        krate: &'a ast::Crate,
+        hir_crate: &'a hir::Crate,
+        output_filenames: &'a OutputFilenames,
+        crate_name: &'a str,
+    ) -> Self {
         CompileState {
             crate_name: Some(crate_name),
             arenas: Some(arenas),
@@ -478,16 +497,17 @@ fn state_after_hir_lowering(input: &'a Input,
         }
     }
 
-    fn state_after_analysis(input: &'a Input,
-                            session: &'tcx Session,
-                            out_dir: &'a Option<PathBuf>,
-                            out_file: &'a Option<PathBuf>,
-                            krate: Option<&'a ast::Crate>,
-                            hir_crate: &'a hir::Crate,
-                            analysis: &'a ty::CrateAnalysis,
-                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            crate_name: &'a str)
-                            -> Self {
+    fn state_after_analysis(
+        input: &'a Input,
+        session: &'tcx Session,
+        out_dir: &'a Option<PathBuf>,
+        out_file: &'a Option<PathBuf>,
+        krate: Option<&'a ast::Crate>,
+        hir_crate: &'a hir::Crate,
+        analysis: &'a ty::CrateAnalysis,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        crate_name: &'a str,
+    ) -> Self {
         CompileState {
             analysis: Some(analysis),
             tcx: Some(tcx),
@@ -499,11 +519,12 @@ fn state_after_analysis(input: &'a Input,
         }
     }
 
-    fn state_when_compilation_done(input: &'a Input,
-                                   session: &'tcx Session,
-                                   out_dir: &'a Option<PathBuf>,
-                                   out_file: &'a Option<PathBuf>)
-                                   -> Self {
+    fn state_when_compilation_done(
+        input: &'a Input,
+        session: &'tcx Session,
+        out_dir: &'a Option<PathBuf>,
+        out_file: &'a Option<PathBuf>,
+    ) -> Self {
         CompileState {
             out_file: out_file.as_ref().map(|s| &**s),
             ..CompileState::empty(input, session, out_dir)
@@ -511,27 +532,24 @@ fn state_when_compilation_done(input: &'a Input,
     }
 }
 
-pub fn phase_1_parse_input<'a>(control: &CompileController,
-                               sess: &'a Session,
-                               input: &Input)
-                               -> PResult<'a, ast::Crate> {
-    sess.diagnostic().set_continue_after_error(control.continue_parse_after_error);
+pub fn phase_1_parse_input<'a>(
+    control: &CompileController,
+    sess: &'a Session,
+    input: &Input,
+) -> PResult<'a, ast::Crate> {
+    sess.diagnostic()
+        .set_continue_after_error(control.continue_parse_after_error);
 
     if sess.profile_queries() {
         profile::begin(sess);
     }
 
-    let krate = time(sess, "parsing", || {
-        match *input {
-            Input::File(ref file) => {
-                parse::parse_crate_from_file(file, &sess.parse_sess)
-            }
-            Input::Str { ref input, ref name } => {
-                parse::parse_crate_from_source_str(name.clone(),
-                                                   input.clone(),
-                                                   &sess.parse_sess)
-            }
-        }
+    let krate = time(sess, "parsing", || match *input {
+        Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
+        Input::Str {
+            ref input,
+            ref name,
+        } => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
     })?;
 
     sess.diagnostic().set_continue_after_error(true);
@@ -541,7 +559,10 @@ pub fn phase_1_parse_input<'a>(control: &CompileController,
     }
 
     if sess.opts.debugging_opts.input_stats {
-        println!("Lines of code:             {}", sess.codemap().count_lines());
+        println!(
+            "Lines of code:             {}",
+            sess.codemap().count_lines()
+        );
         println!("Pre-expansion node count:  {}", count_nodes(&krate));
     }
 
@@ -586,16 +607,19 @@ pub struct InnerExpansionResult<'a> {
 /// standard library and prelude, and name resolution.
 ///
 /// Returns `None` if we're aborting after handling -W help.
-pub fn phase_2_configure_and_expand<F>(sess: &Session,
-                                       cstore: &CStore,
-                                       krate: ast::Crate,
-                                       registry: Option<Registry>,
-                                       crate_name: &str,
-                                       addl_plugins: Option<Vec<String>>,
-                                       make_glob_map: MakeGlobMap,
-                                       after_expand: F)
-                                       -> Result<ExpansionResult, CompileIncomplete>
-    where F: FnOnce(&ast::Crate) -> CompileResult {
+pub fn phase_2_configure_and_expand<F>(
+    sess: &Session,
+    cstore: &CStore,
+    krate: ast::Crate,
+    registry: Option<Registry>,
+    crate_name: &str,
+    addl_plugins: Option<Vec<String>>,
+    make_glob_map: MakeGlobMap,
+    after_expand: F,
+) -> Result<ExpansionResult, CompileIncomplete>
+where
+    F: FnOnce(&ast::Crate) -> CompileResult,
+{
     // Currently, we ignore the name resolution data structures for the purposes of dependency
     // tracking. Instead we will run name resolution and include its output in the hash of each
     // item, much like we do for macro expansion. In other words, the hash reflects not just
@@ -603,52 +627,72 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     // this back at some point.
     let mut crate_loader = CrateLoader::new(sess, &cstore, &crate_name);
     let resolver_arenas = Resolver::arenas();
-    let result = phase_2_configure_and_expand_inner(sess, cstore, krate, registry, crate_name,
-                                                    addl_plugins, make_glob_map, &resolver_arenas,
-                                                    &mut crate_loader, after_expand);
+    let result = phase_2_configure_and_expand_inner(
+        sess,
+        cstore,
+        krate,
+        registry,
+        crate_name,
+        addl_plugins,
+        make_glob_map,
+        &resolver_arenas,
+        &mut crate_loader,
+        after_expand,
+    );
     match result {
-        Ok(InnerExpansionResult {expanded_crate, resolver, hir_forest}) => {
-            Ok(ExpansionResult {
-                expanded_crate,
-                defs: resolver.definitions,
-                hir_forest,
-                resolutions: Resolutions {
-                    freevars: resolver.freevars,
-                    export_map: resolver.export_map,
-                    trait_map: resolver.trait_map,
-                    maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
-                    maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
-                },
-
-                analysis: ty::CrateAnalysis {
-                    access_levels: Lrc::new(AccessLevels::default()),
-                    name: crate_name.to_string(),
-                    glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
+        Ok(InnerExpansionResult {
+            expanded_crate,
+            resolver,
+            hir_forest,
+        }) => Ok(ExpansionResult {
+            expanded_crate,
+            defs: resolver.definitions,
+            hir_forest,
+            resolutions: Resolutions {
+                freevars: resolver.freevars,
+                export_map: resolver.export_map,
+                trait_map: resolver.trait_map,
+                maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
+                maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
+            },
+
+            analysis: ty::CrateAnalysis {
+                access_levels: Lrc::new(AccessLevels::default()),
+                name: crate_name.to_string(),
+                glob_map: if resolver.make_glob_map {
+                    Some(resolver.glob_map)
+                } else {
+                    None
                 },
-            })
-        }
-        Err(x) => Err(x)
+            },
+        }),
+        Err(x) => Err(x),
     }
 }
 
 /// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver
 /// around
-pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
-                                       cstore: &'a CStore,
-                                       krate: ast::Crate,
-                                       registry: Option<Registry>,
-                                       crate_name: &str,
-                                       addl_plugins: Option<Vec<String>>,
-                                       make_glob_map: MakeGlobMap,
-                                       resolver_arenas: &'a ResolverArenas<'a>,
-                                       crate_loader: &'a mut CrateLoader,
-                                       after_expand: F)
-                                       -> Result<InnerExpansionResult<'a>, CompileIncomplete>
-    where F: FnOnce(&ast::Crate) -> CompileResult,
+pub fn phase_2_configure_and_expand_inner<'a, F>(
+    sess: &'a Session,
+    cstore: &'a CStore,
+    krate: ast::Crate,
+    registry: Option<Registry>,
+    crate_name: &str,
+    addl_plugins: Option<Vec<String>>,
+    make_glob_map: MakeGlobMap,
+    resolver_arenas: &'a ResolverArenas<'a>,
+    crate_loader: &'a mut CrateLoader,
+    after_expand: F,
+) -> Result<InnerExpansionResult<'a>, CompileIncomplete>
+where
+    F: FnOnce(&ast::Crate) -> CompileResult,
 {
-    let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess,
-                                                         sess.opts.test,
-                                                         sess.opts.debugging_opts.edition);
+    let (mut krate, features) = syntax::config::features(
+        krate,
+        &sess.parse_sess,
+        sess.opts.test,
+        sess.edition(),
+    );
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
 
@@ -657,17 +701,16 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
 
     let disambiguator = compute_crate_disambiguator(sess);
     sess.crate_disambiguator.set(disambiguator);
-    rustc_incremental::prepare_session_directory(
-        sess,
-        &crate_name,
-        disambiguator,
-    );
+    rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
 
     if sess.opts.incremental.is_some() {
         time(sess, "garbage collect incremental cache directory", || {
             if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
-                warn!("Error while trying to garbage collect incremental \
-                       compilation cache directory: {}", e);
+                warn!(
+                    "Error while trying to garbage collect incremental \
+                     compilation cache directory: {}",
+                    e
+                );
             }
         });
     }
@@ -690,23 +733,31 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
 
     let mut addl_plugins = Some(addl_plugins);
     let registrars = time(sess, "plugin loading", || {
-        plugin::load::load_plugins(sess,
-                                   &cstore,
-                                   &krate,
-                                   crate_name,
-                                   addl_plugins.take().unwrap())
+        plugin::load::load_plugins(
+            sess,
+            &cstore,
+            &krate,
+            crate_name,
+            addl_plugins.take().unwrap(),
+        )
     });
 
     let mut registry = registry.unwrap_or(Registry::new(sess, krate.span));
 
     time(sess, "plugin registration", || {
         if sess.features_untracked().rustc_diagnostic_macros {
-            registry.register_macro("__diagnostic_used",
-                                    diagnostics::plugin::expand_diagnostic_used);
-            registry.register_macro("__register_diagnostic",
-                                    diagnostics::plugin::expand_register_diagnostic);
-            registry.register_macro("__build_diagnostic_array",
-                                    diagnostics::plugin::expand_build_diagnostic_array);
+            registry.register_macro(
+                "__diagnostic_used",
+                diagnostics::plugin::expand_diagnostic_used,
+            );
+            registry.register_macro(
+                "__register_diagnostic",
+                diagnostics::plugin::expand_register_diagnostic,
+            );
+            registry.register_macro(
+                "__build_diagnostic_array",
+                diagnostics::plugin::expand_build_diagnostic_array,
+            );
         }
 
         for registrar in registrars {
@@ -716,8 +767,15 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
     });
 
     let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives();
-    let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
-                   llvm_passes, attributes, .. } = registry;
+    let Registry {
+        syntax_exts,
+        early_lint_passes,
+        late_lint_passes,
+        lint_groups,
+        llvm_passes,
+        attributes,
+        ..
+    } = registry;
 
     sess.track_errors(|| {
         let mut ls = sess.lint_store.borrow_mut();
@@ -742,16 +800,19 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         return Err(CompileIncomplete::Stopped);
     }
 
-    let mut resolver = Resolver::new(sess,
-                                     cstore,
-                                     &krate,
-                                     crate_name,
-                                     make_glob_map,
-                                     crate_loader,
-                                     &resolver_arenas);
+    let mut resolver = Resolver::new(
+        sess,
+        cstore,
+        &krate,
+        crate_name,
+        make_glob_map,
+        crate_loader,
+        &resolver_arenas,
+    );
     resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives;
     syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote);
 
+    // Expand all macros
     krate = time(sess, "expansion", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
         // dependencies. It's up to us to tell the system where to find all the
@@ -769,18 +830,23 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         let mut old_path = OsString::new();
         if cfg!(windows) {
             old_path = env::var_os("PATH").unwrap_or(old_path);
-            let mut new_path = sess.host_filesearch(PathKind::All)
-                                   .get_dylib_search_paths();
+            let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
             for path in env::split_paths(&old_path) {
                 if !new_path.contains(&path) {
                     new_path.push(path);
                 }
             }
-            env::set_var("PATH",
-                &env::join_paths(new_path.iter()
-                                         .filter(|p| env::join_paths(iter::once(p)).is_ok()))
-                     .unwrap());
+            env::set_var(
+                "PATH",
+                &env::join_paths(
+                    new_path
+                        .iter()
+                        .filter(|p| env::join_paths(iter::once(p)).is_ok()),
+                ).unwrap(),
+            );
         }
+
+        // Create the config for macro expansion
         let features = sess.features_untracked();
         let cfg = syntax::ext::expand::ExpansionConfig {
             features: Some(&features),
@@ -793,12 +859,23 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
         let err_count = ecx.parse_sess.span_diagnostic.err_count();
 
-        let krate = ecx.monotonic_expander().expand_crate(krate);
+        // Expand macros now!
+        let krate = time(sess, "expand crate", || {
+            ecx.monotonic_expander().expand_crate(krate)
+        });
 
-        ecx.check_unused_macros();
+        // The rest is error reporting
 
-        let mut missing_fragment_specifiers: Vec<_> =
-            ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
+        time(sess, "check unused macros", || {
+            ecx.check_unused_macros();
+        });
+
+        let mut missing_fragment_specifiers: Vec<_> = ecx.parse_sess
+            .missing_fragment_specifiers
+            .borrow()
+            .iter()
+            .cloned()
+            .collect();
         missing_fragment_specifiers.sort();
         for span in missing_fragment_specifiers {
             let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
@@ -815,12 +892,14 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
     });
 
     krate = time(sess, "maybe building test harness", || {
-        syntax::test::modify_for_testing(&sess.parse_sess,
-                                         &mut resolver,
-                                         sess.opts.test,
-                                         krate,
-                                         sess.diagnostic(),
-                                         &sess.features_untracked())
+        syntax::test::modify_for_testing(
+            &sess.parse_sess,
+            &mut resolver,
+            sess.opts.test,
+            krate,
+            sess.diagnostic(),
+            &sess.features_untracked(),
+        )
     });
 
     // If we're actually rustdoc then there's no need to actually compile
@@ -838,21 +917,20 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
             let num_crate_types = crate_types.len();
             let is_proc_macro_crate = crate_types.contains(&config::CrateTypeProcMacro);
             let is_test_crate = sess.opts.test;
-            syntax_ext::proc_macro_registrar::modify(&sess.parse_sess,
-                                                     &mut resolver,
-                                                     krate,
-                                                     is_proc_macro_crate,
-                                                     is_test_crate,
-                                                     num_crate_types,
-                                                     sess.diagnostic())
+            syntax_ext::proc_macro_registrar::modify(
+                &sess.parse_sess,
+                &mut resolver,
+                krate,
+                is_proc_macro_crate,
+                is_test_crate,
+                num_crate_types,
+                sess.diagnostic(),
+            )
         });
     }
 
     krate = time(sess, "creating allocators", || {
-        allocator::expand::modify(&sess.parse_sess,
-                                  &mut resolver,
-                                  krate,
-                                  sess.diagnostic())
+        allocator::expand::modify(&sess.parse_sess, &mut resolver, krate, sess.diagnostic())
     });
 
     after_expand(&krate)?;
@@ -869,9 +947,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         println!("{}", json::as_json(&krate));
     }
 
-    time(sess,
-         "AST validation",
-         || ast_validation::check_crate(sess, &krate));
+    time(sess, "AST validation", || {
+        ast_validation::check_crate(sess, &krate)
+    });
 
     time(sess, "name resolution", || -> CompileResult {
         resolver.resolve_crate(&krate);
@@ -881,11 +959,13 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
     // Needs to go *after* expansion to be able to check the results of macro expansion.
     time(sess, "complete gated feature checking", || {
         sess.track_errors(|| {
-            syntax::feature_gate::check_crate(&krate,
-                                              &sess.parse_sess,
-                                              &sess.features_untracked(),
-                                              &attributes,
-                                              sess.opts.unstable_features);
+            syntax::feature_gate::check_crate(
+                &krate,
+                &sess.parse_sess,
+                &sess.features_untracked(),
+                &attributes,
+                sess.opts.unstable_features,
+            );
         })
     })?;
 
@@ -901,11 +981,12 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         None => DepGraph::new_disabled(),
         Some(future) => {
             let prev_graph = time(sess, "blocked while dep-graph loading finishes", || {
-                future.open()
-                      .unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
-                          message: format!("could not decode incremental cache: {:?}", e)
-                      })
-                      .open(sess)
+                future
+                    .open()
+                    .unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
+                        message: format!("could not decode incremental cache: {:?}", e),
+                    })
+                    .open(sess)
             });
             DepGraph::new(prev_graph)
         }
@@ -920,9 +1001,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         hir_map::Forest::new(hir_crate, &dep_graph)
     });
 
-    time(sess,
-         "early lint checks",
-         || lint::check_ast_crate(sess, &krate));
+    time(sess, "early lint checks", || {
+        lint::check_ast_crate(sess, &krate)
+    });
 
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !sess.opts.debugging_opts.keep_hygiene_data {
@@ -961,39 +1042,43 @@ pub fn default_provide_extern(providers: &mut ty::maps::Providers) {
 /// Run the resolution, typechecking, region checking and other
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
-pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
-                                               control: &CompileController,
-                                               sess: &'tcx Session,
-                                               cstore: &'tcx CrateStore,
-                                               hir_map: hir_map::Map<'tcx>,
-                                               mut analysis: ty::CrateAnalysis,
-                                               resolutions: Resolutions,
-                                               arenas: &'tcx AllArenas<'tcx>,
-                                               name: &str,
-                                               output_filenames: &OutputFilenames,
-                                               f: F)
-                                               -> Result<R, CompileIncomplete>
-    where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
-                            ty::CrateAnalysis,
-                            mpsc::Receiver<Box<Any + Send>>,
-                            CompileResult) -> R
+pub fn phase_3_run_analysis_passes<'tcx, F, R>(
+    trans: &TransCrate,
+    control: &CompileController,
+    sess: &'tcx Session,
+    cstore: &'tcx CrateStore,
+    hir_map: hir_map::Map<'tcx>,
+    mut analysis: ty::CrateAnalysis,
+    resolutions: Resolutions,
+    arenas: &'tcx AllArenas<'tcx>,
+    name: &str,
+    output_filenames: &OutputFilenames,
+    f: F,
+) -> Result<R, CompileIncomplete>
+where
+    F: for<'a> FnOnce(
+        TyCtxt<'a, 'tcx, 'tcx>,
+        ty::CrateAnalysis,
+        mpsc::Receiver<Box<Any + Send>>,
+        CompileResult,
+    ) -> R,
 {
-    let query_result_on_disk_cache = time(sess,
-        "load query result cache",
-        || rustc_incremental::load_query_result_cache(sess));
+    let query_result_on_disk_cache = time(sess, "load query result cache", || {
+        rustc_incremental::load_query_result_cache(sess)
+    });
 
-    time(sess,
-         "looking for entry point",
-         || middle::entry::find_entry_point(sess, &hir_map, name));
+    time(sess, "looking for entry point", || {
+        middle::entry::find_entry_point(sess, &hir_map, name)
+    });
 
-    sess.plugin_registrar_fn.set(time(sess, "looking for plugin registrar", || {
-        plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map)
-    }));
-    sess.derive_registrar_fn.set(derive_registrar::find(&hir_map));
+    sess.plugin_registrar_fn
+        .set(time(sess, "looking for plugin registrar", || {
+            plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map)
+        }));
+    sess.derive_registrar_fn
+        .set(derive_registrar::find(&hir_map));
 
-    time(sess,
-         "loop checking",
-         || loops::check_crate(sess, &hir_map));
+    time(sess, "loop checking", || loops::check_crate(sess, &hir_map));
 
     let mut local_providers = ty::maps::Providers::default();
     default_provide(&mut local_providers);
@@ -1007,115 +1092,113 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
 
     let (tx, rx) = mpsc::channel();
 
-    TyCtxt::create_and_enter(sess,
-                             cstore,
-                             local_providers,
-                             extern_providers,
-                             arenas,
-                             resolutions,
-                             hir_map,
-                             query_result_on_disk_cache,
-                             name,
-                             tx,
-                             output_filenames,
-                             |tcx| {
-        // Do some initialization of the DepGraph that can only be done with the
-        // tcx available.
-        rustc_incremental::dep_graph_tcx_init(tcx);
-
-        time(sess, "attribute checking", || {
-            hir::check_attr::check_crate(tcx)
-        });
+    TyCtxt::create_and_enter(
+        sess,
+        cstore,
+        local_providers,
+        extern_providers,
+        arenas,
+        resolutions,
+        hir_map,
+        query_result_on_disk_cache,
+        name,
+        tx,
+        output_filenames,
+        |tcx| {
+            // Do some initialization of the DepGraph that can only be done with the
+            // tcx available.
+            rustc_incremental::dep_graph_tcx_init(tcx);
+
+            time(sess, "attribute checking", || {
+                hir::check_attr::check_crate(tcx)
+            });
 
-        time(sess,
-             "stability checking",
-             || stability::check_unstable_api_usage(tcx));
+            time(sess, "stability checking", || {
+                stability::check_unstable_api_usage(tcx)
+            });
 
-        // passes are timed inside typeck
-        match typeck::check_crate(tcx) {
-            Ok(x) => x,
-            Err(x) => {
-                f(tcx, analysis, rx, Err(x));
-                return Err(x);
+            // passes are timed inside typeck
+            match typeck::check_crate(tcx) {
+                Ok(x) => x,
+                Err(x) => {
+                    f(tcx, analysis, rx, Err(x));
+                    return Err(x);
+                }
             }
-        }
 
-        time(sess,
-             "rvalue promotion",
-             || rvalue_promotion::check_crate(tcx));
+            time(sess, "rvalue promotion", || {
+                rvalue_promotion::check_crate(tcx)
+            });
 
-        analysis.access_levels =
-            time(sess, "privacy checking", || rustc_privacy::check_crate(tcx));
+            analysis.access_levels =
+                time(sess, "privacy checking", || rustc_privacy::check_crate(tcx));
 
-        time(sess,
-             "intrinsic checking",
-             || middle::intrinsicck::check_crate(tcx));
+            time(sess, "intrinsic checking", || {
+                middle::intrinsicck::check_crate(tcx)
+            });
 
-        time(sess,
-             "match checking",
-             || mir::matchck_crate(tcx));
+            time(sess, "match checking", || mir::matchck_crate(tcx));
 
-        // this must run before MIR dump, because
-        // "not all control paths return a value" is reported here.
-        //
-        // maybe move the check to a MIR pass?
-        time(sess,
-             "liveness checking",
-             || middle::liveness::check_crate(tcx));
-
-        time(sess,
-             "borrow checking",
-             || borrowck::check_crate(tcx));
-
-        time(sess,
-             "MIR borrow checking",
-             || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id); });
-
-        time(sess,
-             "MIR effect checking",
-             || for def_id in tcx.body_owners() {
-                 mir::transform::check_unsafety::check_unsafety(tcx, def_id)
-             });
-        // Avoid overwhelming user with errors if type checking failed.
-        // I'm not sure how helpful this is, to be honest, but it avoids
-        // a
-        // lot of annoying errors in the compile-fail tests (basically,
-        // lint warnings and so on -- kindck used to do this abort, but
-        // kindck is gone now). -nmatsakis
-        if sess.err_count() > 0 {
-            return Ok(f(tcx, analysis, rx, sess.compile_status()));
-        }
+            // this must run before MIR dump, because
+            // "not all control paths return a value" is reported here.
+            //
+            // maybe move the check to a MIR pass?
+            time(sess, "liveness checking", || {
+                middle::liveness::check_crate(tcx)
+            });
 
-        time(sess, "death checking", || middle::dead::check_crate(tcx));
+            time(sess, "borrow checking", || borrowck::check_crate(tcx));
 
-        time(sess, "unused lib feature checking", || {
-            stability::check_unused_or_stable_features(tcx)
-        });
+            time(sess, "MIR borrow checking", || {
+                for def_id in tcx.body_owners() {
+                    tcx.mir_borrowck(def_id);
+                }
+            });
 
-        time(sess, "lint checking", || lint::check_crate(tcx));
+            time(sess, "MIR effect checking", || {
+                for def_id in tcx.body_owners() {
+                    mir::transform::check_unsafety::check_unsafety(tcx, def_id)
+                }
+            });
+            // Avoid overwhelming user with errors if type checking failed.
+            // I'm not sure how helpful this is, to be honest, but it avoids
+            // a
+            // lot of annoying errors in the compile-fail tests (basically,
+            // lint warnings and so on -- kindck used to do this abort, but
+            // kindck is gone now). -nmatsakis
+            if sess.err_count() > 0 {
+                return Ok(f(tcx, analysis, rx, sess.compile_status()));
+            }
 
-        time(sess,
-             "dumping chalk-like clauses",
-             || rustc_traits::lowering::dump_program_clauses(tcx));
+            time(sess, "death checking", || middle::dead::check_crate(tcx));
 
-        return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
-    })
+            time(sess, "unused lib feature checking", || {
+                stability::check_unused_or_stable_features(tcx)
+            });
+
+            time(sess, "lint checking", || lint::check_crate(tcx));
+
+            time(sess, "dumping chalk-like clauses", || {
+                rustc_traits::lowering::dump_program_clauses(tcx)
+            });
+
+            return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
+        },
+    )
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
-pub fn phase_4_translate_to_llvm<'a, 'tcx>(trans: &TransCrate,
-                                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                           rx: mpsc::Receiver<Box<Any + Send>>)
-                                           -> Box<Any> {
-    time(tcx.sess,
-         "resolving dependency formats",
-         || ::rustc::middle::dependency_format::calculate(tcx));
-
-    let translation =
-        time(tcx.sess, "translation", move || {
-            trans.trans_crate(tcx, rx)
-        });
+pub fn phase_4_translate_to_llvm<'a, 'tcx>(
+    trans: &TransCrate,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    rx: mpsc::Receiver<Box<Any + Send>>,
+) -> Box<Any> {
+    time(tcx.sess, "resolving dependency formats", || {
+        ::rustc::middle::dependency_format::calculate(tcx)
+    });
+
+    let translation = time(tcx.sess, "translation", move || trans.trans_crate(tcx, rx));
     if tcx.sess.profile_queries() {
         profile::dump(&tcx.sess, "profile_queries".to_string())
     }
@@ -1130,27 +1213,27 @@ fn escape_dep_filename(filename: &FileName) -> String {
 }
 
 // Returns all the paths that correspond to generated files.
-fn generated_output_paths(sess: &Session,
-                          outputs: &OutputFilenames,
-                          exact_name: bool,
-                          crate_name: &str) -> Vec<PathBuf> {
+fn generated_output_paths(
+    sess: &Session,
+    outputs: &OutputFilenames,
+    exact_name: bool,
+    crate_name: &str,
+) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
         let file = outputs.path(*output_type);
         match *output_type {
             // If the filename has been overridden using `-o`, it will not be modified
             // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
-            OutputType::Exe if !exact_name => {
-                for crate_type in sess.crate_types.borrow().iter() {
-                    let p = ::rustc_trans_utils::link::filename_for_input(
-                        sess,
-                        *crate_type,
-                        crate_name,
-                        outputs
-                    );
-                    out_filenames.push(p);
-                }
-            }
+            OutputType::Exe if !exact_name => for crate_type in sess.crate_types.borrow().iter() {
+                let p = ::rustc_trans_utils::link::filename_for_input(
+                    sess,
+                    *crate_type,
+                    crate_name,
+                    outputs,
+                );
+                out_filenames.push(p);
+            },
             OutputType::DepInfo if sess.opts.debugging_opts.dep_info_omit_d_target => {
                 // Don't add the dep-info output when omitting it from dep-info targets
             }
@@ -1165,24 +1248,28 @@ fn generated_output_paths(sess: &Session,
 // Runs `f` on every output file path and returns the first non-None result, or None if `f`
 // returns None for every file path.
 fn check_output<F, T>(output_paths: &Vec<PathBuf>, f: F) -> Option<T>
-        where F: Fn(&PathBuf) -> Option<T> {
-            for output_path in output_paths {
-                if let Some(result) = f(output_path) {
-                    return Some(result);
-                }
-            }
-            None
+where
+    F: Fn(&PathBuf) -> Option<T>,
+{
+    for output_path in output_paths {
+        if let Some(result) = f(output_path) {
+            return Some(result);
+        }
+    }
+    None
 }
 
 pub fn output_contains_path(output_paths: &Vec<PathBuf>, input_path: &PathBuf) -> bool {
     let input_path = input_path.canonicalize().ok();
     if input_path.is_none() {
-        return false
+        return false;
     }
     let check = |output_path: &PathBuf| {
         if output_path.canonicalize().ok() == input_path {
             Some(())
-        } else { None }
+        } else {
+            None
+        }
     };
     check_output(output_paths, check).is_some()
 }
@@ -1191,100 +1278,92 @@ pub fn output_conflicts_with_dir(output_paths: &Vec<PathBuf>) -> Option<PathBuf>
     let check = |output_path: &PathBuf| {
         if output_path.is_dir() {
             Some(output_path.clone())
-        } else { None }
+        } else {
+            None
+        }
     };
     check_output(output_paths, check)
 }
 
-fn write_out_deps(sess: &Session,
-                  outputs: &OutputFilenames,
-                  out_filenames: &Vec<PathBuf>) {
+fn write_out_deps(sess: &Session, outputs: &OutputFilenames, out_filenames: &Vec<PathBuf>) {
     // Write out dependency rules to the dep-info file if requested
     if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
         return;
     }
     let deps_filename = outputs.path(OutputType::DepInfo);
 
-    let result =
-        (|| -> io::Result<()> {
-            // Build a list of files used to compile the output and
-            // write Makefile-compatible dependency rules
-            let files: Vec<String> = sess.codemap()
-                                         .files()
-                                         .iter()
-                                         .filter(|fmap| fmap.is_real_file())
-                                         .filter(|fmap| !fmap.is_imported())
-                                         .map(|fmap| escape_dep_filename(&fmap.name))
-                                         .collect();
-            let mut file = fs::File::create(&deps_filename)?;
-            for path in out_filenames {
-                write!(file, "{}: {}\n\n", path.display(), files.join(" "))?;
-            }
+    let result = (|| -> io::Result<()> {
+        // Build a list of files used to compile the output and
+        // write Makefile-compatible dependency rules
+        let files: Vec<String> = sess.codemap()
+            .files()
+            .iter()
+            .filter(|fmap| fmap.is_real_file())
+            .filter(|fmap| !fmap.is_imported())
+            .map(|fmap| escape_dep_filename(&fmap.name))
+            .collect();
+        let mut file = fs::File::create(&deps_filename)?;
+        for path in out_filenames {
+            write!(file, "{}: {}\n\n", path.display(), files.join(" "))?;
+        }
 
-            // Emit a fake target for each input file to the compilation. This
-            // prevents `make` from spitting out an error if a file is later
-            // deleted. For more info see #28735
-            for path in files {
-                writeln!(file, "{}:", path)?;
-            }
-            Ok(())
-        })();
+        // Emit a fake target for each input file to the compilation. This
+        // prevents `make` from spitting out an error if a file is later
+        // deleted. For more info see #28735
+        for path in files {
+            writeln!(file, "{}:", path)?;
+        }
+        Ok(())
+    })();
 
     match result {
         Ok(()) => {}
         Err(e) => {
-            sess.fatal(&format!("error writing dependencies to `{}`: {}",
-                                deps_filename.display(),
-                                e));
+            sess.fatal(&format!(
+                "error writing dependencies to `{}`: {}",
+                deps_filename.display(),
+                e
+            ));
         }
     }
 }
 
 pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
     // Unconditionally collect crate types from attributes to make them used
-    let attr_types: Vec<config::CrateType> =
-        attrs.iter()
-             .filter_map(|a| {
-                 if a.check_name("crate_type") {
-                     match a.value_str() {
-                         Some(ref n) if *n == "rlib" => {
-                             Some(config::CrateTypeRlib)
-                         }
-                         Some(ref n) if *n == "dylib" => {
-                             Some(config::CrateTypeDylib)
-                         }
-                         Some(ref n) if *n == "cdylib" => {
-                             Some(config::CrateTypeCdylib)
-                         }
-                         Some(ref n) if *n == "lib" => {
-                             Some(config::default_lib_output())
-                         }
-                         Some(ref n) if *n == "staticlib" => {
-                             Some(config::CrateTypeStaticlib)
-                         }
-                         Some(ref n) if *n == "proc-macro" => {
-                             Some(config::CrateTypeProcMacro)
-                         }
-                         Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable),
-                         Some(_) => {
-                             session.buffer_lint(lint::builtin::UNKNOWN_CRATE_TYPES,
-                                                 ast::CRATE_NODE_ID,
-                                                 a.span,
-                                                 "invalid `crate_type` value");
-                             None
-                         }
-                         _ => {
-                             session.struct_span_err(a.span, "`crate_type` requires a value")
-                                 .note("for example: `#![crate_type=\"lib\"]`")
-                                 .emit();
-                             None
-                         }
-                     }
-                 } else {
-                     None
-                 }
-             })
-             .collect();
+    let attr_types: Vec<config::CrateType> = attrs
+        .iter()
+        .filter_map(|a| {
+            if a.check_name("crate_type") {
+                match a.value_str() {
+                    Some(ref n) if *n == "rlib" => Some(config::CrateTypeRlib),
+                    Some(ref n) if *n == "dylib" => Some(config::CrateTypeDylib),
+                    Some(ref n) if *n == "cdylib" => Some(config::CrateTypeCdylib),
+                    Some(ref n) if *n == "lib" => Some(config::default_lib_output()),
+                    Some(ref n) if *n == "staticlib" => Some(config::CrateTypeStaticlib),
+                    Some(ref n) if *n == "proc-macro" => Some(config::CrateTypeProcMacro),
+                    Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable),
+                    Some(_) => {
+                        session.buffer_lint(
+                            lint::builtin::UNKNOWN_CRATE_TYPES,
+                            ast::CRATE_NODE_ID,
+                            a.span,
+                            "invalid `crate_type` value",
+                        );
+                        None
+                    }
+                    _ => {
+                        session
+                            .struct_span_err(a.span, "`crate_type` requires a value")
+                            .note("for example: `#![crate_type=\"lib\"]`")
+                            .emit();
+                        None
+                    }
+                }
+            } else {
+                None
+            }
+        })
+        .collect();
 
     // If we're generating a test executable, then ignore all other output
     // styles at all other locations
@@ -1299,7 +1378,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
     if base.is_empty() {
         base.extend(attr_types);
         if base.is_empty() {
-            base.push(::rustc_trans_utils::link::default_output_for_target(session));
+            base.push(::rustc_trans_utils::link::default_output_for_target(
+                session,
+            ));
         }
         base.sort();
         base.dedup();
@@ -1310,9 +1391,10 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
             let res = !::rustc_trans_utils::link::invalid_output_for_target(session, *crate_type);
 
             if !res {
-                session.warn(&format!("dropping unsupported crate type `{}` for target `{}`",
-                                      *crate_type,
-                                      session.opts.target_triple));
+                session.warn(&format!(
+                    "dropping unsupported crate type `{}` for target `{}`",
+                    *crate_type, session.opts.target_triple
+                ));
             }
 
             res
@@ -1347,19 +1429,22 @@ pub fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
 
     // Also incorporate crate type, so that we don't get symbol conflicts when
     // linking against a library of the same name, if this is an executable.
-    let is_exe = session.crate_types.borrow().contains(&config::CrateTypeExecutable);
+    let is_exe = session
+        .crate_types
+        .borrow()
+        .contains(&config::CrateTypeExecutable);
     hasher.write(if is_exe { b"exe" } else { b"lib" });
 
     CrateDisambiguator::from(hasher.finish())
-
 }
 
-pub fn build_output_filenames(input: &Input,
-                              odir: &Option<PathBuf>,
-                              ofile: &Option<PathBuf>,
-                              attrs: &[ast::Attribute],
-                              sess: &Session)
-                              -> OutputFilenames {
+pub fn build_output_filenames(
+    input: &Input,
+    odir: &Option<PathBuf>,
+    ofile: &Option<PathBuf>,
+    attrs: &[ast::Attribute],
+    sess: &Session,
+) -> OutputFilenames {
     match *ofile {
         None => {
             // "-" as input file will cause the parser to read from stdin so we
@@ -1372,10 +1457,10 @@ pub fn build_output_filenames(input: &Input,
 
             // If a crate name is present, we use it as the link name
             let stem = sess.opts
-                           .crate_name
-                           .clone()
-                           .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
-                           .unwrap_or(input.filestem());
+                .crate_name
+                .clone()
+                .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
+                .unwrap_or(input.filestem());
 
             OutputFilenames {
                 out_directory: dirpath,
@@ -1388,13 +1473,15 @@ pub fn build_output_filenames(input: &Input,
 
         Some(ref out_file) => {
             let unnamed_output_types = sess.opts
-                                           .output_types
-                                           .values()
-                                           .filter(|a| a.is_none())
-                                           .count();
+                .output_types
+                .values()
+                .filter(|a| a.is_none())
+                .count();
             let ofile = if unnamed_output_types > 1 {
-                sess.warn("due to multiple output types requested, the explicitly specified \
-                           output file name will be adapted for each output type");
+                sess.warn(
+                    "due to multiple output types requested, the explicitly specified \
+                     output file name will be adapted for each output type",
+                );
                 None
             } else {
                 Some(out_file.clone())
@@ -1410,11 +1497,12 @@ pub fn build_output_filenames(input: &Input,
 
             OutputFilenames {
                 out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(),
-                out_filestem: out_file.file_stem()
-                                      .unwrap_or(OsStr::new(""))
-                                      .to_str()
-                                      .unwrap()
-                                      .to_string(),
+                out_filestem: out_file
+                    .file_stem()
+                    .unwrap_or(OsStr::new(""))
+                    .to_str()
+                    .unwrap()
+                    .to_string(),
                 single_output_file: ofile,
                 extra: sess.opts.cg.extra_filename.clone(),
                 outputs: sess.opts.output_types.clone(),
index 3dec84d174dd8d922badd5cd17625b8a14987639..fb333ec38fb60ada847ed1afba1723a1b4a60e1e 100644 (file)
@@ -25,6 +25,7 @@
 #![feature(slice_sort_by_cached_key)]
 #![feature(set_stdio)]
 #![feature(rustc_stack_internals)]
+#![feature(no_debug)]
 
 extern crate arena;
 extern crate getopts;
@@ -230,6 +231,9 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<TransCrate> {
 
 pub fn get_trans(sess: &Session) -> Box<TransCrate> {
     static INIT: Once = ONCE_INIT;
+
+    #[allow(deprecated)]
+    #[no_debug]
     static mut LOAD: fn() -> Box<TransCrate> = || unreachable!();
 
     INIT.call_once(|| {
@@ -547,6 +551,18 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
     (result, Some(sess))
 }
 
+#[cfg(unix)]
+pub fn set_sigpipe_handler() {
+    unsafe {
+        // Set the SIGPIPE signal handler, so that an EPIPE
+        // will cause rustc to terminate, as expected.
+        assert!(libc::signal(libc::SIGPIPE, libc::SIG_DFL) != libc::SIG_ERR);
+    }
+}
+
+#[cfg(windows)]
+pub fn set_sigpipe_handler() {}
+
 // Extract output directory and file from matches.
 fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
     let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
index 5aae895ccc4d5e1bfe0b8c61459b1d12060293a3..04f6503d92dd89bc38e7ef3d6461617fb3d748a1 100644 (file)
@@ -28,7 +28,7 @@
 use rustc::hir::map as hir_map;
 use rustc::session::{self, config};
 use rustc::session::config::{OutputFilenames, OutputTypes};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use syntax;
 use syntax::ast;
 use syntax::abi::Abi;
@@ -88,13 +88,13 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
     }
 }
 
-fn errors(msgs: &[&str]) -> (Box<Emitter + Send>, usize) {
+fn errors(msgs: &[&str]) -> (Box<Emitter + sync::Send>, usize) {
     let v = msgs.iter().map(|m| m.to_string()).collect();
-    (box ExpectErrorEmitter { messages: v } as Box<Emitter + Send>, msgs.len())
+    (box ExpectErrorEmitter { messages: v } as Box<Emitter + sync::Send>, msgs.len())
 }
 
 fn test_env<F>(source_string: &str,
-               args: (Box<Emitter + Send>, usize),
+               args: (Box<Emitter + sync::Send>, usize),
                body: F)
     where F: FnOnce(Env)
 {
@@ -104,7 +104,7 @@ fn test_env<F>(source_string: &str,
 }
 
 fn test_env_impl<F>(source_string: &str,
-                    (emitter, expected_err_count): (Box<Emitter + Send>, usize),
+                    (emitter, expected_err_count): (Box<Emitter + sync::Send>, usize),
                     body: F)
     where F: FnOnce(Env)
 {
index ca5d3f55a0fea4988d75505405c1a32d05917145..91075ddcfa422ab40d532178204b806371749145 100644 (file)
@@ -1389,8 +1389,8 @@ fn num_overlap(a_start: usize, a_end: usize, b_start: usize, b_end:usize, inclus
     } else {
         0
     };
-    (b_start..b_end + extra).contains(a_start) ||
-    (a_start..a_end + extra).contains(b_start)
+    (b_start..b_end + extra).contains(&a_start) ||
+    (a_start..a_end + extra).contains(&b_start)
 }
 fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
     num_overlap(a1.start_col, a1.end_col + padding, a2.start_col, a2.end_col, false)
index 8d5f9ac93f0b48e3d5b92f7233715e3f2c1cf7e9..ce3efef08cc4234f992590284732635140f8302c 100644 (file)
 
 use emitter::{Emitter, EmitterWriter};
 
-use rustc_data_structures::sync::{self, Lrc};
+use rustc_data_structures::sync::{self, Lrc, Lock, LockCell};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stable_hasher::StableHasher;
 
 use std::borrow::Cow;
-use std::cell::{RefCell, Cell};
+use std::cell::Cell;
 use std::{error, fmt};
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::SeqCst;
@@ -262,19 +262,22 @@ pub struct Handler {
     pub flags: HandlerFlags,
 
     err_count: AtomicUsize,
-    emitter: RefCell<Box<Emitter>>,
-    continue_after_error: Cell<bool>,
-    delayed_span_bug: RefCell<Option<Diagnostic>>,
+    emitter: Lock<Box<Emitter + sync::Send>>,
+    continue_after_error: LockCell<bool>,
+    delayed_span_bug: Lock<Option<Diagnostic>>,
 
     // This set contains the `DiagnosticId` of all emitted diagnostics to avoid
     // emitting the same diagnostic with extended help (`--teach`) twice, which
     // would be uneccessary repetition.
-    tracked_diagnostic_codes: RefCell<FxHashSet<DiagnosticId>>,
+    taught_diagnostics: Lock<FxHashSet<DiagnosticId>>,
+
+    /// Used to suggest rustc --explain <error code>
+    emitted_diagnostic_codes: Lock<FxHashSet<DiagnosticId>>,
 
     // This set contains a hash of every diagnostic that has been emitted by
     // this handler. These hashes is used to avoid emitting the same error
     // twice.
-    emitted_diagnostics: RefCell<FxHashSet<u128>>,
+    emitted_diagnostics: Lock<FxHashSet<u128>>,
 }
 
 fn default_track_diagnostic(_: &Diagnostic) {}
@@ -315,7 +318,7 @@ pub fn with_tty_emitter_and_flags(color_config: ColorConfig,
 
     pub fn with_emitter(can_emit_warnings: bool,
                         treat_err_as_bug: bool,
-                        e: Box<Emitter>)
+                        e: Box<Emitter + sync::Send>)
                         -> Handler {
         Handler::with_emitter_and_flags(
             e,
@@ -326,15 +329,16 @@ pub fn with_emitter(can_emit_warnings: bool,
             })
     }
 
-    pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> Handler {
+    pub fn with_emitter_and_flags(e: Box<Emitter + sync::Send>, flags: HandlerFlags) -> Handler {
         Handler {
             flags,
             err_count: AtomicUsize::new(0),
-            emitter: RefCell::new(e),
-            continue_after_error: Cell::new(true),
-            delayed_span_bug: RefCell::new(None),
-            tracked_diagnostic_codes: RefCell::new(FxHashSet()),
-            emitted_diagnostics: RefCell::new(FxHashSet()),
+            emitter: Lock::new(e),
+            continue_after_error: LockCell::new(true),
+            delayed_span_bug: Lock::new(None),
+            taught_diagnostics: Lock::new(FxHashSet()),
+            emitted_diagnostic_codes: Lock::new(FxHashSet()),
+            emitted_diagnostics: Lock::new(FxHashSet()),
         }
     }
 
@@ -348,7 +352,7 @@ pub fn set_continue_after_error(&self, continue_after_error: bool) {
     /// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
     /// the overall count of emitted error diagnostics.
     pub fn reset_err_count(&self) {
-        self.emitted_diagnostics.replace(FxHashSet());
+        *self.emitted_diagnostics.borrow_mut() = FxHashSet();
         self.err_count.store(0, SeqCst);
     }
 
@@ -568,10 +572,10 @@ pub fn print_error_count(&self) {
         let _ = self.fatal(&s);
 
         let can_show_explain = self.emitter.borrow().should_show_explain();
-        let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty();
+        let are_there_diagnostics = !self.emitted_diagnostic_codes.borrow().is_empty();
         if can_show_explain && are_there_diagnostics {
             let mut error_codes =
-                self.tracked_diagnostic_codes.borrow()
+                self.emitted_diagnostic_codes.borrow()
                                              .clone()
                                              .into_iter()
                                              .filter_map(|x| match x {
@@ -630,12 +634,13 @@ pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl
         }
     }
 
-    /// `true` if a diagnostic with this code has already been emitted in this handler.
+    /// `true` if we haven't taught a diagnostic with this code already.
+    /// The caller must then teach the user about such a diagnostic.
     ///
     /// Used to suppress emitting the same error multiple times with extended explanation when
     /// calling `-Zteach`.
-    pub fn code_emitted(&self, code: &DiagnosticId) -> bool {
-        self.tracked_diagnostic_codes.borrow().contains(code)
+    pub fn must_teach(&self, code: &DiagnosticId) -> bool {
+        self.taught_diagnostics.borrow_mut().insert(code.clone())
     }
 
     pub fn force_print_db(&self, mut db: DiagnosticBuilder) {
@@ -651,7 +656,7 @@ fn emit_db(&self, db: &DiagnosticBuilder) {
         });
 
         if let Some(ref code) = diagnostic.code {
-            self.tracked_diagnostic_codes.borrow_mut().insert(code.clone());
+            self.emitted_diagnostic_codes.borrow_mut().insert(code.clone());
         }
 
         let diagnostic_hash = {
index a5bc1106ba0b00fc24264b5378cd5711274e69ea..e524fcecf9094a3edce0a932d97ee83f2878272c 100644 (file)
@@ -43,7 +43,11 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
             time(sess, "persist dep-graph", || {
                 save_in(sess,
                         dep_graph_path(sess),
-                        |e| encode_dep_graph(tcx, e));
+                        |e| {
+                            time(sess, "encode dep-graph", || {
+                                encode_dep_graph(tcx, e)
+                            })
+                        });
             });
         }
 
@@ -145,7 +149,9 @@ fn encode_dep_graph(tcx: TyCtxt,
     tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
 
     // Encode the graph data.
-    let serialized_graph = tcx.dep_graph.serialize();
+    let serialized_graph = time(tcx.sess, "getting serialized graph", || {
+        tcx.dep_graph.serialize()
+    });
 
     if tcx.sess.opts.debugging_opts.incremental_info {
         #[derive(Clone)]
@@ -221,7 +227,9 @@ struct Stat {
         println!("[incremental]");
     }
 
-    serialized_graph.encode(encoder)?;
+    time(tcx.sess, "encoding serialized graph", || {
+        serialized_graph.encode(encoder)
+    })?;
 
     Ok(())
 }
@@ -245,5 +253,7 @@ fn encode_work_products(dep_graph: &DepGraph,
 fn encode_query_cache(tcx: TyCtxt,
                       encoder: &mut Encoder)
                       -> io::Result<()> {
-    tcx.serialize_query_result_cache(encoder)
+    time(tcx.sess, "serialize query result cache", || {
+        tcx.serialize_query_result_cache(encoder)
+    })
 }
index 54e3f544acb68b0258186b0729245a02b324070a..1619637b827dfe99a1bad79271fa3a6f6c318fa2 100644 (file)
@@ -28,6 +28,12 @@ fn detect_llvm_link() -> (&'static str, &'static str) {
 }
 
 fn main() {
+    if env::var_os("RUST_CHECK").is_some() {
+        // If we're just running `check`, there's no need for LLVM to be built.
+        println!("cargo:rerun-if-env-changed=RUST_CHECK");
+        return;
+    }
+
     let target = env::var("TARGET").expect("TARGET was not set");
     let llvm_config = env::var_os("LLVM_CONFIG")
         .map(PathBuf::from)
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
deleted file mode 100644 (file)
index 71b1564..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
-
-use isolated_encoder::IsolatedEncoder;
-use schema::*;
-
-use rustc::hir;
-use rustc::ty::{self, TyCtxt};
-
-use rustc::ich::Fingerprint;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-
-#[derive(RustcEncodable, RustcDecodable)]
-pub struct Ast<'tcx> {
-    pub body: Lazy<hir::Body>,
-    pub tables: Lazy<ty::TypeckTables<'tcx>>,
-    pub nested_bodies: LazySeq<hir::Body>,
-    pub rvalue_promotable_to_static: bool,
-    pub stable_bodies_hash: Fingerprint,
-}
-
-impl_stable_hash_for!(struct Ast<'tcx> {
-    body,
-    tables,
-    nested_bodies,
-    rvalue_promotable_to_static,
-    stable_bodies_hash
-});
-
-impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
-    pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
-        let body = self.tcx.hir.body(body_id);
-
-        // In order to avoid having to hash hir::Bodies from extern crates, we
-        // hash them here, during export, and store the hash with metadata.
-        let stable_bodies_hash = {
-            let mut hcx = self.tcx.create_stable_hashing_context();
-            let mut hasher = StableHasher::new();
-
-            hcx.while_hashing_hir_bodies(true, |hcx| {
-                body.hash_stable(hcx, &mut hasher);
-            });
-
-            hasher.finish()
-        };
-
-        let lazy_body = self.lazy(body);
-        let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
-        let tables = self.tcx.typeck_tables_of(body_owner_def_id);
-        let lazy_tables = self.lazy(tables);
-
-        let mut visitor = NestedBodyCollector {
-            tcx: self.tcx,
-            bodies_found: Vec::new(),
-        };
-        visitor.visit_body(body);
-        let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
-
-        let rvalue_promotable_to_static =
-            self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
-
-        self.lazy(&Ast {
-            body: lazy_body,
-            tables: lazy_tables,
-            nested_bodies: lazy_nested_bodies,
-            rvalue_promotable_to_static,
-            stable_bodies_hash,
-        })
-    }
-}
-
-struct NestedBodyCollector<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    bodies_found: Vec<&'tcx hir::Body>,
-}
-
-impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_nested_body(&mut self, body: hir::BodyId) {
-        let body = self.tcx.hir.body(body);
-        self.bodies_found.push(body);
-        self.visit_body(body);
-    }
-}
index 2c995d2f5cde637be697c85cc20935ab6fb3eb47..a11b95cb5b6c1a02bbb33881587176017807f714 100644 (file)
@@ -142,7 +142,6 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     mir_const_qualif => {
         (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSetBuf::new_empty(0)))
     }
-    typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
@@ -161,9 +160,9 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     // This is only used by rustdoc anyway, which shouldn't have
     // incremental recompilation ever enabled.
     fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
+    rendered_const => { cdata.get_rendered_const(def_id.index) }
     impl_parent => { cdata.get_parent_impl(def_id.index) }
     trait_of_item => { cdata.get_trait_of_item(def_id.index) }
-    item_body_nested_bodies => { cdata.item_body_nested_bodies(tcx, def_id.index) }
     const_is_rvalue_promotable_to_static => {
         cdata.const_is_rvalue_promotable_to_static(def_id.index)
     }
@@ -243,11 +242,6 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     defined_lang_items => { Lrc::new(cdata.get_lang_items()) }
     missing_lang_items => { Lrc::new(cdata.get_missing_lang_items()) }
 
-    extern_const_body => {
-        debug!("item_body({:?}): inlining item", def_id);
-        cdata.extern_const_body(tcx, def_id.index)
-    }
-
     missing_extern_crate_item => {
         let r = match *cdata.extern_crate.borrow() {
             Some(extern_crate) if !extern_crate.direct => true,
index 936d680380c993a994cae26b43b69ea08cfc9398..0147e8dc6075948f38e20a8fd0ac72f6e7726dc8 100644 (file)
@@ -17,8 +17,7 @@
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash,
                       DisambiguatedDefPathData};
 use rustc::hir;
-use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
-                            ExternBodyNestedBodies};
+use rustc::middle::cstore::LinkagePreference;
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
@@ -33,7 +32,6 @@
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
 
-use std::collections::BTreeMap;
 use std::io;
 use std::mem;
 use std::u32;
@@ -433,7 +431,7 @@ pub fn list_crate_metadata(&self,
 impl<'tcx> EntryKind<'tcx> {
     fn to_def(&self, did: DefId) -> Option<Def> {
         Some(match *self {
-            EntryKind::Const(_) => Def::Const(did),
+            EntryKind::Const(..) => Def::Const(did),
             EntryKind::AssociatedConst(..) => Def::AssociatedConst(did),
             EntryKind::ImmStatic |
             EntryKind::ForeignImmStatic => Def::Static(did, false),
@@ -794,54 +792,12 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
         }
     }
 
-    pub fn extern_const_body(&self,
-                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             id: DefIndex)
-                             -> ExternConstBody<'tcx> {
-        assert!(!self.is_proc_macro(id));
-        let ast = self.entry(id).ast.unwrap();
-        let def_id = self.local_def_id(id);
-        let ast = ast.decode((self, tcx));
-        let body = ast.body.decode((self, tcx));
-        ExternConstBody {
-            body: tcx.hir.intern_inlined_body(def_id, body),
-            fingerprint: ast.stable_bodies_hash,
-        }
-    }
-
-    pub fn item_body_tables(&self,
-                            id: DefIndex,
-                            tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                            -> &'tcx ty::TypeckTables<'tcx> {
-        let ast = self.entry(id).ast.unwrap().decode(self);
-        tcx.alloc_tables(ast.tables.decode((self, tcx)))
-    }
-
-    pub fn item_body_nested_bodies(&self,
-                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   id: DefIndex)
-                                   -> ExternBodyNestedBodies {
-        if let Some(ref ast) = self.entry(id).ast {
-            let mut ast = ast.decode(self);
-            let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
-                                                   .decode((self, tcx.sess))
-                                                   .map(|body| (body.id(), body))
-                                                   .collect();
-            ExternBodyNestedBodies {
-                nested_bodies: Lrc::new(nested_bodies),
-                fingerprint: ast.stable_bodies_hash,
-            }
-        } else {
-            ExternBodyNestedBodies {
-                nested_bodies: Lrc::new(BTreeMap::new()),
-                fingerprint: Fingerprint::ZERO,
-            }
-        }
-    }
-
     pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
-        self.entry(id).ast.expect("const item missing `ast`")
-            .decode(self).rvalue_promotable_to_static
+        match self.entry(id).kind {
+            EntryKind::AssociatedConst(_, data, _) |
+            EntryKind::Const(data, _) => data.ast_promotable,
+            _ => bug!(),
+        }
     }
 
     pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
@@ -861,10 +817,10 @@ pub fn maybe_get_optimized_mir(&self,
 
     pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
         match self.entry(id).kind {
-            EntryKind::Const(qualif) |
-            EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) |
-            EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => {
-                qualif
+            EntryKind::Const(qualif, _) |
+            EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif, _) |
+            EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => {
+                qualif.mir
             }
             _ => bug!(),
         }
@@ -877,7 +833,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
         let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
 
         let (kind, container, has_self) = match item.kind {
-            EntryKind::AssociatedConst(container, _) => {
+            EntryKind::AssociatedConst(container, _, _) => {
                 (ty::AssociatedKind::Const, container, false)
             }
             EntryKind::Method(data) => {
@@ -1076,6 +1032,14 @@ pub fn exported_symbols(&self,
         lazy_seq.decode((self, tcx)).collect()
     }
 
+    pub fn get_rendered_const(&self, id: DefIndex) -> String {
+        match self.entry(id).kind {
+            EntryKind::Const(_, data) |
+            EntryKind::AssociatedConst(_, _, data) => data.decode(self).0,
+            _ => bug!(),
+        }
+    }
+
     pub fn wasm_custom_sections(&self) -> Vec<DefId> {
         let sections = self.root
             .wasm_custom_sections
index a61428b841fea83748d56fe353982414ca9187ae..d7a06f7932fef396a8de850578e442efea6435a9 100644 (file)
@@ -622,7 +622,6 @@ fn encode_enum_variant_info(&mut self,
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: None,
             mir: self.encode_optimized_mir(def_id),
         }
     }
@@ -660,7 +659,6 @@ fn encode_info_for_mod(&mut self,
             generics: None,
             predicates: None,
 
-            ast: None,
             mir: None
         }
     }
@@ -701,7 +699,6 @@ fn encode_field(&mut self,
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: None,
             mir: None,
         }
     }
@@ -759,7 +756,6 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: None,
             mir: self.encode_optimized_mir(def_id),
         }
     }
@@ -795,7 +791,18 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
 
         let kind = match trait_item.kind {
             ty::AssociatedKind::Const => {
-                EntryKind::AssociatedConst(container, 0)
+                let const_qualif =
+                    if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node {
+                        self.const_qualif(0, body)
+                    } else {
+                        ConstQualif { mir: 0, ast_promotable: false }
+                    };
+
+                let rendered =
+                    hir::print::to_string(&self.tcx.hir, |s| s.print_trait_item(ast_item));
+                let rendered_const = self.lazy(&RenderedConst(rendered));
+
+                EntryKind::AssociatedConst(container, const_qualif, rendered_const)
             }
             ty::AssociatedKind::Method => {
                 let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
@@ -855,15 +862,22 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node {
-                Some(self.encode_body(body))
-            } else {
-                None
-            },
             mir: self.encode_optimized_mir(def_id),
         }
     }
 
+    fn metadata_output_only(&self) -> bool {
+        // MIR optimisation can be skipped when we're just interested in the metadata.
+        !self.tcx.sess.opts.output_types.should_trans()
+    }
+
+    fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif {
+        let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
+        let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
+
+        ConstQualif { mir, ast_promotable }
+    }
+
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
         let tcx = self.tcx;
@@ -881,8 +895,15 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
 
         let kind = match impl_item.kind {
             ty::AssociatedKind::Const => {
-                EntryKind::AssociatedConst(container,
-                    self.tcx.at(ast_item.span).mir_const_qualif(def_id).0)
+                if let hir::ImplItemKind::Const(_, body_id) = ast_item.node {
+                    let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0;
+
+                    EntryKind::AssociatedConst(container,
+                        self.const_qualif(mir, body_id),
+                        self.encode_rendered_const_for_body(body_id))
+                } else {
+                    bug!()
+                }
             }
             ty::AssociatedKind::Method => {
                 let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
@@ -903,19 +924,21 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
         };
 
-        let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node {
-            (Some(body), true)
-        } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
-            let generics = self.tcx.generics_of(def_id);
-            let types = generics.parent_types as usize + generics.types.len();
-            let needs_inline = types > 0 || tcx.trans_fn_attrs(def_id).requests_inline();
-            let is_const_fn = sig.constness == hir::Constness::Const;
-            let ast = if is_const_fn { Some(body) } else { None };
-            let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-            (ast, needs_inline || is_const_fn || always_encode_mir)
-        } else {
-            (None, false)
-        };
+        let mir =
+            match ast_item.node {
+                hir::ImplItemKind::Const(..) => true,
+                hir::ImplItemKind::Method(ref sig, _) => {
+                    let generics = self.tcx.generics_of(def_id);
+                    let types = generics.parent_types as usize + generics.types.len();
+                    let needs_inline =
+                        (types > 0 || tcx.trans_fn_attrs(def_id).requests_inline())
+                            && !self.metadata_output_only();
+                    let is_const_fn = sig.constness == hir::Constness::Const;
+                    let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
+                    needs_inline || is_const_fn || always_encode_mir
+                },
+                hir::ImplItemKind::Type(..) => false,
+            };
 
         Entry {
             kind,
@@ -936,7 +959,6 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: ast.map(|body| self.encode_body(body)),
             mir: if mir { self.encode_optimized_mir(def_id) } else { None },
         }
     }
@@ -993,6 +1015,13 @@ fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation
         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
     }
 
+    fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> {
+        let body = self.tcx.hir.body(body_id);
+        let rendered = hir::print::to_string(&self.tcx.hir, |s| s.print_expr(&body.value));
+        let rendered_const = &RenderedConst(rendered);
+        self.lazy(rendered_const)
+    }
+
     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
         let tcx = self.tcx;
 
@@ -1001,8 +1030,12 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
         let kind = match item.node {
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
             hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
-            hir::ItemConst(..) => {
-                EntryKind::Const(tcx.at(item.span).mir_const_qualif(def_id).0)
+            hir::ItemConst(_, body_id) => {
+                let mir = tcx.at(item.span).mir_const_qualif(def_id).0;
+                EntryKind::Const(
+                    self.const_qualif(mir, body_id),
+                    self.encode_rendered_const_for_body(body_id)
+                )
             }
             hir::ItemFn(_, _, constness, .., body) => {
                 let data = FnData {
@@ -1185,13 +1218,6 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 _ => None,
             },
 
-            ast: match item.node {
-                hir::ItemConst(_, body) |
-                hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => {
-                    Some(self.encode_body(body))
-                }
-                _ => None,
-            },
             mir: match item.node {
                 hir::ItemStatic(..) => {
                     self.encode_optimized_mir(def_id)
@@ -1199,7 +1225,8 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemConst(..) => self.encode_optimized_mir(def_id),
                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
                     let has_tps = generics.ty_params().next().is_some();
-                    let needs_inline = has_tps || tcx.trans_fn_attrs(def_id).requests_inline();
+                    let needs_inline = (has_tps || tcx.trans_fn_attrs(def_id).requests_inline()) &&
+                        !self.metadata_output_only();
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     if needs_inline || constness == hir::Constness::Const || always_encode_mir {
                         self.encode_optimized_mir(def_id)
@@ -1233,7 +1260,6 @@ fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx
             variances: LazySeq::empty(),
             generics: None,
             predicates: None,
-            ast: None,
             mir: None,
         }
     }
@@ -1262,7 +1288,6 @@ fn encode_info_for_ty_param(&mut self,
             generics: None,
             predicates: None,
 
-            ast: None,
             mir: None,
         }
     }
@@ -1285,7 +1310,6 @@ fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: None,
             mir: None,
         }
     }
@@ -1330,7 +1354,6 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: None,
 
-            ast: None,
             mir: self.encode_optimized_mir(def_id),
         }
     }
@@ -1339,10 +1362,12 @@ fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id);
         let tcx = self.tcx;
         let id = tcx.hir.as_local_node_id(def_id).unwrap();
-        let body = tcx.hir.body_owned_by(id);
+        let body_id = tcx.hir.body_owned_by(id);
+        let const_data = self.encode_rendered_const_for_body(body_id);
+        let mir = tcx.mir_const_qualif(def_id).0;
 
         Entry {
-            kind: EntryKind::Const(tcx.mir_const_qualif(def_id).0),
+            kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data),
             visibility: self.lazy(&ty::Visibility::Public),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: LazySeq::empty(),
@@ -1356,7 +1381,6 @@ fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: Some(self.encode_body(body)),
             mir: self.encode_optimized_mir(def_id),
         }
     }
@@ -1558,7 +1582,6 @@ fn encode_info_for_foreign_item(&mut self,
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: None,
             mir: None,
         }
     }
index 689c190966ee8214bc4fe827f04fa55e9eabb0d0..88594afa32024f5cb69c11897a61e47a1302abf2 100644 (file)
@@ -55,10 +55,4 @@ pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
     {
         self.ecx.lazy_seq_ref(slice.iter())
     }
-
-    pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
-        where T: Encodable
-    {
-        self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
-    }
 }
index cbbc9d74228de9e8bf9de8c7d262cec33aefd7ed..9ecb3fd6cddf6aae48e57ddabbc54fabda79bd85 100644 (file)
@@ -44,7 +44,6 @@
 
 mod diagnostics;
 
-mod astencode;
 mod index_builder;
 mod index;
 mod encoder;
index 23ea5e4cc55043b97ef075feb1c90302aaaa1c58..5d6db1abe7b68f0663ba66cdd4234e5d6c7e366e 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use astencode;
 use index;
 
 use rustc::hir;
@@ -266,7 +265,6 @@ pub struct Entry<'tcx> {
     pub generics: Option<Lazy<ty::Generics>>,
     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
 
-    pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
 }
 
@@ -283,13 +281,12 @@ pub struct Entry<'tcx> {
     variances,
     generics,
     predicates,
-    ast,
     mir
 });
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub enum EntryKind<'tcx> {
-    Const(u8),
+    Const(ConstQualif, Lazy<RenderedConst>),
     ImmStatic,
     MutStatic,
     ForeignImmStatic,
@@ -313,7 +310,7 @@ pub enum EntryKind<'tcx> {
     Impl(Lazy<ImplData<'tcx>>),
     Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
-    AssociatedConst(AssociatedContainer, u8),
+    AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
 }
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
@@ -333,8 +330,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             EntryKind::Type => {
                 // Nothing else to hash here.
             }
-            EntryKind::Const(qualif) => {
+            EntryKind::Const(qualif, ref const_data) => {
                 qualif.hash_stable(hcx, hasher);
+                const_data.hash_stable(hcx, hasher);
             }
             EntryKind::Enum(ref repr_options) => {
                 repr_options.hash_stable(hcx, hasher);
@@ -375,7 +373,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             EntryKind::AssociatedType(associated_container) => {
                 associated_container.hash_stable(hcx, hasher);
             }
-            EntryKind::AssociatedConst(associated_container, qualif) => {
+            EntryKind::AssociatedConst(associated_container, qualif, _) => {
                 associated_container.hash_stable(hcx, hasher);
                 qualif.hash_stable(hcx, hasher);
             }
@@ -383,6 +381,29 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+/// Additional data for EntryKind::Const and EntryKind::AssociatedConst
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
+pub struct ConstQualif {
+    pub mir: u8,
+    pub ast_promotable: bool,
+}
+
+impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable });
+
+/// Contains a constant which has been rendered to a String.
+/// Used by rustdoc.
+#[derive(RustcEncodable, RustcDecodable)]
+pub struct RenderedConst(pub String);
+
+impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        self.0.hash_stable(hcx, hasher);
+    }
+}
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
     pub reexports: LazySeq<def::Export>,
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
new file mode 100644 (file)
index 0000000..ccfb44a
--- /dev/null
@@ -0,0 +1,328 @@
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use borrow_check::place_ext::PlaceExt;
+use dataflow::indexes::BorrowIndex;
+use rustc::mir::traversal;
+use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::{self, Location, Mir, Place};
+use rustc::ty::{Region, TyCtxt};
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc_data_structures::indexed_vec::IndexVec;
+use std::fmt;
+use std::hash::Hash;
+use std::ops::Index;
+
+crate struct BorrowSet<'tcx> {
+    /// The fundamental map relating bitvector indexes to the borrows
+    /// in the MIR.
+    crate borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
+
+    /// Each borrow is also uniquely identified in the MIR by the
+    /// `Location` of the assignment statement in which it appears on
+    /// the right hand side; we map each such location to the
+    /// corresponding `BorrowIndex`.
+    crate location_map: FxHashMap<Location, BorrowIndex>,
+
+    /// Locations which activate borrows.
+    /// NOTE: A given location may activate more than one borrow in the future
+    /// when more general two-phase borrow support is introduced, but for now we
+    /// only need to store one borrow index
+    crate activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
+
+    /// Every borrow has a region; this maps each such regions back to
+    /// its borrow-indexes.
+    crate region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+
+    /// Map from local to all the borrows on that local
+    crate local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
+}
+
+impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
+    type Output = BorrowData<'tcx>;
+
+    fn index(&self, index: BorrowIndex) -> &BorrowData<'tcx> {
+        &self.borrows[index]
+    }
+}
+
+#[derive(Debug)]
+crate struct BorrowData<'tcx> {
+    /// Location where the borrow reservation starts.
+    /// In many cases, this will be equal to the activation location but not always.
+    crate reserve_location: Location,
+    /// Location where the borrow is activated. None if this is not a
+    /// 2-phase borrow.
+    crate activation_location: Option<Location>,
+    /// What kind of borrow this is
+    crate kind: mir::BorrowKind,
+    /// The region for which this borrow is live
+    crate region: Region<'tcx>,
+    /// Place from which we are borrowing
+    crate borrowed_place: mir::Place<'tcx>,
+    /// Place to which the borrow was stored
+    crate assigned_place: mir::Place<'tcx>,
+}
+
+impl<'tcx> fmt::Display for BorrowData<'tcx> {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        let kind = match self.kind {
+            mir::BorrowKind::Shared => "",
+            mir::BorrowKind::Unique => "uniq ",
+            mir::BorrowKind::Mut { .. } => "mut ",
+        };
+        let region = format!("{}", self.region);
+        let region = if region.len() > 0 {
+            format!("{} ", region)
+        } else {
+            region
+        };
+        write!(w, "&{}{}{:?}", region, kind, self.borrowed_place)
+    }
+}
+
+impl<'tcx> BorrowSet<'tcx> {
+    pub fn build(tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> Self {
+        let mut visitor = GatherBorrows {
+            tcx,
+            mir,
+            idx_vec: IndexVec::new(),
+            location_map: FxHashMap(),
+            activation_map: FxHashMap(),
+            region_map: FxHashMap(),
+            local_map: FxHashMap(),
+            pending_activations: FxHashMap(),
+        };
+
+        for (block, block_data) in traversal::preorder(mir) {
+            visitor.visit_basic_block_data(block, block_data);
+        }
+
+        // Double check: We should have found an activation for every pending
+        // activation.
+        assert_eq!(
+            visitor
+                .pending_activations
+                .iter()
+                .find(|&(_local, &borrow_index)| visitor.idx_vec[borrow_index]
+                    .activation_location
+                    .is_none()),
+            None,
+            "never found an activation for this borrow!",
+        );
+
+        BorrowSet {
+            borrows: visitor.idx_vec,
+            location_map: visitor.location_map,
+            activation_map: visitor.activation_map,
+            region_map: visitor.region_map,
+            local_map: visitor.local_map,
+        }
+    }
+
+    crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] {
+        self.activation_map
+            .get(&location)
+            .map(|activations| &activations[..])
+            .unwrap_or(&[])
+    }
+}
+
+struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
+    location_map: FxHashMap<Location, BorrowIndex>,
+    activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
+    region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+    local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
+
+    /// When we encounter a 2-phase borrow statement, it will always
+    /// be assigning into a temporary TEMP:
+    ///
+    ///    TEMP = &foo
+    ///
+    /// We add TEMP into this map with `b`, where `b` is the index of
+    /// the borrow. When we find a later use of this activation, we
+    /// remove from the map (and add to the "tombstone" set below).
+    pending_activations: FxHashMap<mir::Local, BorrowIndex>,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
+    fn visit_assign(
+        &mut self,
+        block: mir::BasicBlock,
+        assigned_place: &mir::Place<'tcx>,
+        rvalue: &mir::Rvalue<'tcx>,
+        location: mir::Location,
+    ) {
+        if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
+            if borrowed_place.is_unsafe_place(self.tcx, self.mir) {
+                return;
+            }
+
+            let borrow = BorrowData {
+                kind,
+                region,
+                reserve_location: location,
+                activation_location: None,
+                borrowed_place: borrowed_place.clone(),
+                assigned_place: assigned_place.clone(),
+            };
+            let idx = self.idx_vec.push(borrow);
+            self.location_map.insert(location, idx);
+
+            self.insert_as_pending_if_two_phase(location, &assigned_place, region, kind, idx);
+
+            insert(&mut self.region_map, &region, idx);
+            if let Some(local) = borrowed_place.root_local() {
+                insert(&mut self.local_map, &local, idx);
+            }
+        }
+
+        return self.super_assign(block, assigned_place, rvalue, location);
+
+        fn insert<'a, K, V>(map: &'a mut FxHashMap<K, FxHashSet<V>>, k: &K, v: V)
+        where
+            K: Clone + Eq + Hash,
+            V: Eq + Hash,
+        {
+            map.entry(k.clone()).or_insert(FxHashSet()).insert(v);
+        }
+    }
+
+    fn visit_place(
+        &mut self,
+        place: &mir::Place<'tcx>,
+        context: PlaceContext<'tcx>,
+        location: Location,
+    ) {
+        self.super_place(place, context, location);
+
+        // We found a use of some temporary TEMP...
+        if let Place::Local(temp) = place {
+            // ... check whether we (earlier) saw a 2-phase borrow like
+            //
+            //     TMP = &mut place
+            match self.pending_activations.get(temp) {
+                Some(&borrow_index) => {
+                    let borrow_data = &mut self.idx_vec[borrow_index];
+
+                    // Watch out: the use of TMP in the borrow
+                    // itself doesn't count as an
+                    // activation. =)
+                    if borrow_data.reserve_location == location && context == PlaceContext::Store {
+                        return;
+                    }
+
+                    if let Some(other_activation) = borrow_data.activation_location {
+                        span_bug!(
+                            self.mir.source_info(location).span,
+                            "found two activations for 2-phase borrow temporary {:?}: \
+                             {:?} and {:?}",
+                            temp,
+                            location,
+                            other_activation,
+                        );
+                    }
+
+                    // Otherwise, this is the unique later use
+                    // that we expect.
+                    borrow_data.activation_location = Some(location);
+                    self.activation_map
+                        .entry(location)
+                        .or_insert(Vec::new())
+                        .push(borrow_index);
+                }
+
+                None => {}
+            }
+        }
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
+        if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
+            // double-check that we already registered a BorrowData for this
+
+            let borrow_index = self.location_map[&location];
+            let borrow_data = &self.idx_vec[borrow_index];
+            assert_eq!(borrow_data.reserve_location, location);
+            assert_eq!(borrow_data.kind, kind);
+            assert_eq!(borrow_data.region, region);
+            assert_eq!(borrow_data.borrowed_place, *place);
+        }
+
+        return self.super_rvalue(rvalue, location);
+    }
+
+    fn visit_statement(
+        &mut self,
+        block: mir::BasicBlock,
+        statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        return self.super_statement(block, statement, location);
+    }
+}
+
+impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
+    /// Returns true if the borrow represented by `kind` is
+    /// allowed to be split into separate Reservation and
+    /// Activation phases.
+    fn allow_two_phase_borrow(&self, kind: mir::BorrowKind) -> bool {
+        self.tcx.two_phase_borrows()
+            && (kind.allows_two_phase_borrow()
+                || self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref)
+    }
+
+    /// If this is a two-phase borrow, then we will record it
+    /// as "pending" until we find the activating use.
+    fn insert_as_pending_if_two_phase(
+        &mut self,
+        start_location: Location,
+        assigned_place: &mir::Place<'tcx>,
+        region: Region<'tcx>,
+        kind: mir::BorrowKind,
+        borrow_index: BorrowIndex,
+    ) {
+        debug!(
+            "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?}, {:?})",
+            start_location, assigned_place, region, borrow_index,
+        );
+
+        if !self.allow_two_phase_borrow(kind) {
+            debug!("  -> {:?}", start_location);
+            return;
+        }
+
+        // When we encounter a 2-phase borrow statement, it will always
+        // be assigning into a temporary TEMP:
+        //
+        //    TEMP = &foo
+        //
+        // so extract `temp`.
+        let temp = if let &mir::Place::Local(temp) = assigned_place {
+            temp
+        } else {
+            span_bug!(
+                self.mir.source_info(start_location).span,
+                "expected 2-phase borrow to assign to a local, not `{:?}`",
+                assigned_place,
+            );
+        };
+
+        // Insert `temp` into the list of pending activations. From
+        // now on, we'll be on the lookout for a use of it. Note that
+        // we are guaranteed that this use will come after the
+        // assignment.
+        let old_value = self.pending_activations.insert(temp, borrow_index);
+        assert!(old_value.is_none());
+    }
+}
index aaed1dd871bac458bff5698002d6c3dea5e5ed50..3dc5a7a84900cb280376e1933ddb24b5413321fd 100644 (file)
@@ -18,7 +18,9 @@
 
 use super::{Context, MirBorrowckCtxt};
 use super::{InitializationRequiringAction, PrefixSet};
-use dataflow::{Borrows, BorrowData, FlowAtLocation, MovingOutStatements};
+use super::borrow_set::BorrowData;
+
+use dataflow::{FlowAtLocation, MovingOutStatements};
 use dataflow::move_paths::MovePathIndex;
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
@@ -261,7 +263,6 @@ pub(super) fn report_conflicting_borrow(
         (place, span): (&Place<'tcx>, Span),
         gen_borrow_kind: BorrowKind,
         issued_borrow: &BorrowData<'tcx>,
-        end_issued_loan_span: Option<Span>,
     ) {
         let issued_span = self.retrieve_borrow_span(issued_borrow);
 
@@ -295,7 +296,7 @@ pub(super) fn report_conflicting_borrow(
                     "it",
                     rgt,
                     "",
-                    end_issued_loan_span,
+                    None,
                     Origin::Mir,
                 )
             }
@@ -307,7 +308,7 @@ pub(super) fn report_conflicting_borrow(
                     "",
                     issued_span,
                     "",
-                    end_issued_loan_span,
+                    None,
                     Origin::Mir,
                 )
             }
@@ -317,7 +318,7 @@ pub(super) fn report_conflicting_borrow(
                     span,
                     &desc_place,
                     issued_span,
-                    end_issued_loan_span,
+                    None,
                     Origin::Mir,
                 )
             }
@@ -329,7 +330,7 @@ pub(super) fn report_conflicting_borrow(
                 issued_span,
                 "it",
                 "",
-                end_issued_loan_span,
+                None,
                 Origin::Mir,
             ),
 
@@ -341,7 +342,7 @@ pub(super) fn report_conflicting_borrow(
                     lft,
                     issued_span,
                     "",
-                    end_issued_loan_span,
+                    None,
                     Origin::Mir,
                 )
             }
@@ -354,7 +355,7 @@ pub(super) fn report_conflicting_borrow(
                     lft,
                     issued_span,
                     "",
-                    end_issued_loan_span,
+                    None,
                     Origin::Mir,
                 )
             }
@@ -389,10 +390,8 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
         context: Context,
         borrow: &BorrowData<'tcx>,
         drop_span: Span,
-        borrows: &Borrows<'cx, 'gcx, 'tcx>
     ) {
-        let end_span = borrows.opt_region_end_span(&borrow.region);
-        let scope_tree = borrows.scope_tree();
+        let scope_tree = self.tcx.region_scope_tree(self.mir_def_id);
         let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
             .last()
             .unwrap();
@@ -426,7 +425,6 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
                     drop_span,
                     borrow_span,
                     proper_span,
-                    end_span,
                 );
             }
             (RegionKind::ReScope(_), None) => {
@@ -437,7 +435,6 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
                     drop_span,
                     borrow_span,
                     proper_span,
-                    end_span,
                 );
             }
             (RegionKind::ReEarlyBound(_), Some(name))
@@ -453,7 +450,6 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
                     drop_span,
                     borrow_span,
                     proper_span,
-                    end_span,
                 );
             }
             (RegionKind::ReEarlyBound(_), None)
@@ -468,7 +464,6 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
                     drop_span,
                     borrow_span,
                     proper_span,
-                    end_span,
                 );
             }
             (RegionKind::ReLateBound(_, _), _)
@@ -490,7 +485,6 @@ fn report_scoped_local_value_does_not_live_long_enough(
         drop_span: Span,
         borrow_span: Span,
         _proper_span: Span,
-        end_span: Option<Span>,
     ) {
         let tcx = self.tcx;
         let mut err =
@@ -500,9 +494,6 @@ fn report_scoped_local_value_does_not_live_long_enough(
             drop_span,
             format!("`{}` dropped here while still borrowed", name),
         );
-        if let Some(end) = end_span {
-            err.span_label(end, "borrowed value needs to live until here");
-        }
         self.explain_why_borrow_contains_point(context, borrow, &mut err);
         err.emit();
     }
@@ -515,7 +506,6 @@ fn report_scoped_temporary_value_does_not_live_long_enough(
         drop_span: Span,
         _borrow_span: Span,
         proper_span: Span,
-        end_span: Option<Span>,
     ) {
         let tcx = self.tcx;
         let mut err =
@@ -526,9 +516,6 @@ fn report_scoped_temporary_value_does_not_live_long_enough(
             "temporary value dropped here while still borrowed",
         );
         err.note("consider using a `let` binding to increase its lifetime");
-        if let Some(end) = end_span {
-            err.span_label(end, "temporary value needs to live until here");
-        }
         self.explain_why_borrow_contains_point(context, borrow, &mut err);
         err.emit();
     }
@@ -542,7 +529,6 @@ fn report_unscoped_local_value_does_not_live_long_enough(
         drop_span: Span,
         borrow_span: Span,
         _proper_span: Span,
-        _end_span: Option<Span>,
     ) {
         debug!(
             "report_unscoped_local_value_does_not_live_long_enough(\
@@ -557,16 +543,6 @@ fn report_unscoped_local_value_does_not_live_long_enough(
         err.span_label(borrow_span, "borrowed value does not live long enough");
         err.span_label(drop_span, "borrowed value only lives until here");
 
-        if !tcx.nll() {
-            tcx.note_and_explain_region(
-                scope_tree,
-                &mut err,
-                "borrowed value must be valid for ",
-                borrow.region,
-                "...",
-            );
-        }
-
         self.explain_why_borrow_contains_point(context, borrow, &mut err);
         err.emit();
     }
@@ -579,7 +555,6 @@ fn report_unscoped_temporary_value_does_not_live_long_enough(
         drop_span: Span,
         _borrow_span: Span,
         proper_span: Span,
-        _end_span: Option<Span>,
     ) {
         debug!(
             "report_unscoped_temporary_value_does_not_live_long_enough(\
@@ -594,16 +569,6 @@ fn report_unscoped_temporary_value_does_not_live_long_enough(
         err.span_label(proper_span, "temporary value does not live long enough");
         err.span_label(drop_span, "temporary value only lives until here");
 
-        if !tcx.nll() {
-            tcx.note_and_explain_region(
-                scope_tree,
-                &mut err,
-                "borrowed value must be valid for ",
-                borrow.region,
-                "...",
-            );
-        }
-
         self.explain_why_borrow_contains_point(context, borrow, &mut err);
         err.emit();
     }
@@ -834,7 +799,7 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
     }
 
     // Retrieve span of given borrow from the current MIR representation
-    pub fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
+    crate fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
         self.mir.source_info(borrow.reserve_location).span
     }
 
index ceff380c594ed48f37abdcab322c14f6f4ef2f4d..070dc1d09bf6bd855bc45cf58affb4f3cc39832d 100644 (file)
 //! but is not as ugly as it is right now.
 
 use rustc::mir::{BasicBlock, Location};
+use rustc_data_structures::indexed_set::Iter;
 
 use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use dataflow::{EverInitializedPlaces, MovingOutStatements};
 use dataflow::{Borrows};
 use dataflow::{FlowAtLocation, FlowsAtLocation};
 use dataflow::move_paths::HasMoveData;
+use dataflow::move_paths::indexes::BorrowIndex;
 use std::fmt;
 
 // (forced to be `pub` due to its use as an associated type below.)
-pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
-    pub borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
+crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
+    borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
     pub inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
     pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
     pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
@@ -32,7 +34,7 @@ pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
 }
 
 impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
-    pub fn new(
+    crate fn new(
         borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
         inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
         uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
@@ -47,6 +49,14 @@ pub fn new(
             ever_inits,
         }
     }
+
+    crate fn borrows_in_scope(&self) -> impl Iterator<Item = BorrowIndex> + '_ {
+        self.borrows.iter_incoming()
+    }
+
+    crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter<BorrowIndex>)) {
+        self.borrows.with_iter_outgoing(op)
+    }
 }
 
 macro_rules! each_flow {
@@ -88,9 +98,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                 s.push_str(", ");
             };
             saw_one = true;
-            let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
-            s.push_str(&format!("{}{}", borrow_data,
-                                if borrow.is_activation() { "@active" } else { "" }));
+            let borrow_data = &self.borrows.operator().borrows()[borrow];
+            s.push_str(&format!("{}", borrow_data));
         });
         s.push_str("] ");
 
@@ -101,7 +110,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                 s.push_str(", ");
             };
             saw_one = true;
-            let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
+            let borrow_data = &self.borrows.operator().borrows()[borrow];
             s.push_str(&format!("{}", borrow_data));
         });
         s.push_str("] ");
index 62acdf76546248cae0733df9959bd93dfc1bd4c3..4dd8d245d3beaff1474d47f0d4961202c40b5dbe 100644 (file)
 use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
 use rustc::mir::ClosureRegionRequirements;
 
+use rustc_data_structures::control_flow_graph::dominators::Dominators;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
 
 use std::rc::Rc;
 
-use syntax::ast;
 use syntax_pos::Span;
 
 use dataflow::{do_dataflow, DebugFormatted};
@@ -37,7 +37,7 @@
 use dataflow::{DataflowResultsConsumer};
 use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use dataflow::{EverInitializedPlaces, MovingOutStatements};
-use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex};
+use dataflow::Borrows;
 use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
 use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
 
 use std::iter;
 
+use self::borrow_set::{BorrowSet, BorrowData};
 use self::flows::Flows;
 use self::prefixes::PrefixSet;
 use self::MutateMode::{JustWrite, WriteAndRead};
 
+crate mod borrow_set;
 mod error_reporting;
 mod flows;
+crate mod place_ext;
 mod prefixes;
 
 pub(crate) mod nll;
@@ -70,7 +73,7 @@ fn mir_borrowck<'a, 'tcx>(
     let input_mir = tcx.mir_validated(def_id);
     debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
 
-    if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir() {
+    if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() {
         return None;
     }
 
@@ -95,19 +98,13 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         .as_local_node_id(def_id)
         .expect("do_mir_borrowck: non-local DefId");
 
-    // Make our own copy of the MIR. This copy will be modified (in place) to
-    // contain non-lexical lifetimes. It will have a lifetime tied
-    // to the inference context.
+    // Replace all regions with fresh inference variables. This
+    // requires first making our own copy of the MIR. This copy will
+    // be modified (in place) to contain non-lexical lifetimes. It
+    // will have a lifetime tied to the inference context.
     let mut mir: Mir<'tcx> = input_mir.clone();
-    let free_regions = if !tcx.nll() {
-        None
-    } else {
-        let mir = &mut mir;
-
-        // Replace all regions with fresh inference variables.
-        Some(nll::replace_regions_in_mir(infcx, def_id, param_env, mir))
-    };
-    let mir = &mir;
+    let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir);
+    let mir = &mir; // no further changes
 
     let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) {
         Ok(move_data) => move_data,
@@ -189,22 +186,20 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         |bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
     ));
 
+    let borrow_set = Rc::new(BorrowSet::build(tcx, mir));
+
     // If we are in non-lexical mode, compute the non-lexical lifetimes.
-    let (opt_regioncx, opt_closure_req) = if let Some(free_regions) = free_regions {
-        let (regioncx, opt_closure_req) = nll::compute_regions(
-            infcx,
-            def_id,
-            free_regions,
-            mir,
-            param_env,
-            &mut flow_inits,
-            &mdpe.move_data,
-        );
-        (Some(Rc::new(regioncx)), opt_closure_req)
-    } else {
-        assert!(!tcx.nll());
-        (None, None)
-    };
+    let (regioncx, opt_closure_req) = nll::compute_regions(
+        infcx,
+        def_id,
+        free_regions,
+        mir,
+        param_env,
+        &mut flow_inits,
+        &mdpe.move_data,
+        &borrow_set,
+    );
+    let regioncx = Rc::new(regioncx);
     let flow_inits = flow_inits; // remove mut
 
     let flow_borrows = FlowAtLocation::new(do_dataflow(
@@ -213,24 +208,24 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         id,
         &attributes,
         &dead_unwinds,
-        Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id),
-        |rs, i| {
-            DebugFormatted::new(&(i.kind(), rs.location(i.borrow_index())))
-        }
+        Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set),
+        |rs, i| DebugFormatted::new(&rs.location(i)),
     ));
 
-    let movable_generator = !match tcx.hir.get(id) {
+    let movable_generator = match tcx.hir.get(id) {
         hir::map::Node::NodeExpr(&hir::Expr {
             node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)),
             ..
-        }) => true,
-        _ => false,
+        }) => false,
+        _ => true,
     };
 
+    let dominators = mir.dominators();
+
     let mut mbcx = MirBorrowckCtxt {
         tcx: tcx,
         mir: mir,
-        node_id: id,
+        mir_def_id: def_id,
         move_data: &mdpe.move_data,
         param_env: param_env,
         movable_generator,
@@ -241,8 +236,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         access_place_error_reported: FxHashSet(),
         reservation_error_reported: FxHashSet(),
         moved_error_reported: FxHashSet(),
-        nonlexical_regioncx: opt_regioncx,
+        nonlexical_regioncx: regioncx,
         nonlexical_cause_info: None,
+        borrow_set,
+        dominators,
     };
 
     let mut state = Flows::new(
@@ -262,7 +259,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
 pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     mir: &'cx Mir<'tcx>,
-    node_id: ast::NodeId,
+    mir_def_id: DefId,
     move_data: &'cx MoveData<'tcx>,
     param_env: ParamEnv<'gcx>,
     movable_generator: bool,
@@ -293,8 +290,14 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// Non-lexical region inference context, if NLL is enabled.  This
     /// contains the results from region inference and lets us e.g.
     /// find out which CFG points are contained in each borrow region.
-    nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
+    nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
     nonlexical_cause_info: Option<RegionCausalInfo>,
+
+    /// The set of borrows extracted from the MIR
+    borrow_set: Rc<BorrowSet<'tcx>>,
+
+    /// Dominators for MIR
+    dominators: Dominators<BasicBlock>,
 }
 
 // Check that:
@@ -535,11 +538,10 @@ fn visit_terminator_entry(
 
                 if self.movable_generator {
                     // Look for any active borrows to locals
-                    let domain = flow_state.borrows.operator();
-                    let data = domain.borrows();
-                    flow_state.borrows.with_iter_outgoing(|borrows| {
+                    let borrow_set = self.borrow_set.clone();
+                    flow_state.with_outgoing_borrows(|borrows| {
                         for i in borrows {
-                            let borrow = &data[i.borrow_index()];
+                            let borrow = &borrow_set[i];
                             self.check_for_local_borrow(borrow, span);
                         }
                     });
@@ -551,13 +553,12 @@ fn visit_terminator_entry(
                 // Often, the storage will already have been killed by an explicit
                 // StorageDead, but we don't always emit those (notably on unwind paths),
                 // so this "extra check" serves as a kind of backup.
-                let domain = flow_state.borrows.operator();
-                let data = domain.borrows();
-                flow_state.borrows.with_iter_outgoing(|borrows| {
+                let borrow_set = self.borrow_set.clone();
+                flow_state.with_outgoing_borrows(|borrows| {
                     for i in borrows {
-                        let borrow = &data[i.borrow_index()];
+                        let borrow = &borrow_set[i];
                         let context = ContextKind::StorageDead.new(loc);
-                        self.check_for_invalidation_at_exit(context, borrow, span, flow_state);
+                        self.check_for_invalidation_at_exit(context, borrow, span);
                     }
                 });
             }
@@ -836,27 +837,34 @@ fn check_access_for_conflict(
         rw: ReadOrWrite,
         flow_state: &Flows<'cx, 'gcx, 'tcx>,
     ) -> bool {
+        debug!(
+            "check_access_for_conflict(context={:?}, place_span={:?}, sd={:?}, rw={:?})",
+            context,
+            place_span,
+            sd,
+            rw,
+        );
+
         let mut error_reported = false;
         self.each_borrow_involving_path(
             context,
             (sd, place_span.0),
             flow_state,
-            |this, index, borrow| match (rw, borrow.kind) {
+            |this, borrow_index, borrow| match (rw, borrow.kind) {
                 // Obviously an activation is compatible with its own
                 // reservation (or even prior activating uses of same
                 // borrow); so don't check if they interfere.
                 //
                 // NOTE: *reservations* do conflict with themselves;
                 // thus aren't injecting unsoundenss w/ this check.)
-                (Activation(_, activating), _) if activating == index.borrow_index() => {
+                (Activation(_, activating), _) if activating == borrow_index => {
                     debug!(
                         "check_access_for_conflict place_span: {:?} sd: {:?} rw: {:?} \
-                         skipping {:?} b/c activation of same borrow_index: {:?}",
+                         skipping {:?} b/c activation of same borrow_index",
                         place_span,
                         sd,
                         rw,
-                        (index, borrow),
-                        index.borrow_index()
+                        (borrow_index, borrow),
                     );
                     Control::Continue
                 }
@@ -867,7 +875,8 @@ fn check_access_for_conflict(
 
                 (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
                     // Reading from mere reservations of mutable-borrows is OK.
-                    if this.allow_two_phase_borrow(borrow.kind) && index.is_reservation() {
+                    if !this.is_active(borrow, context.loc) {
+                        assert!(this.allow_two_phase_borrow(borrow.kind));
                         return Control::Continue;
                     }
 
@@ -877,17 +886,12 @@ fn check_access_for_conflict(
                             this.report_use_while_mutably_borrowed(context, place_span, borrow)
                         }
                         ReadKind::Borrow(bk) => {
-                            let end_issued_loan_span = flow_state
-                                .borrows
-                                .operator()
-                                .opt_region_end_span(&borrow.region);
                             error_reported = true;
                             this.report_conflicting_borrow(
                                 context,
                                 place_span,
                                 bk,
                                 &borrow,
-                                end_issued_loan_span,
                             )
                         }
                     }
@@ -919,18 +923,12 @@ fn check_access_for_conflict(
 
                     match kind {
                         WriteKind::MutableBorrow(bk) => {
-                            let end_issued_loan_span = flow_state
-                                .borrows
-                                .operator()
-                                .opt_region_end_span(&borrow.region);
-
                             error_reported = true;
                             this.report_conflicting_borrow(
                                 context,
                                 place_span,
                                 bk,
                                 &borrow,
-                                end_issued_loan_span,
                             )
                         }
                         WriteKind::StorageDeadOrDrop => {
@@ -939,7 +937,6 @@ fn check_access_for_conflict(
                                 context,
                                 borrow,
                                 place_span.1,
-                                flow_state.borrows.operator(),
                             );
                         }
                         WriteKind::Mutate => {
@@ -1141,7 +1138,6 @@ fn check_for_invalidation_at_exit(
         context: Context,
         borrow: &BorrowData<'tcx>,
         span: Span,
-        flow_state: &Flows<'cx, 'gcx, 'tcx>,
     ) {
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
@@ -1194,7 +1190,6 @@ fn check_for_invalidation_at_exit(
                 context,
                 borrow,
                 span,
-                flow_state.borrows.operator(),
             )
         }
     }
@@ -1249,36 +1244,30 @@ fn check_activations(
         // Two-phase borrow support: For each activation that is newly
         // generated at this statement, check if it interferes with
         // another borrow.
-        let domain = flow_state.borrows.operator();
-        let data = domain.borrows();
-        flow_state.borrows.each_gen_bit(|gen| {
-            if gen.is_activation() {
-                let borrow_index = gen.borrow_index();
-                let borrow = &data[borrow_index];
-                // currently the flow analysis registers
-                // activations for both mutable and immutable
-                // borrows. So make sure we are talking about a
-                // mutable borrow before we check it.
-                match borrow.kind {
-                    BorrowKind::Shared => return,
-                    BorrowKind::Unique | BorrowKind::Mut { .. } => {}
-                }
-
-                self.access_place(
-                    ContextKind::Activation.new(location),
-                    (&borrow.borrowed_place, span),
-                    (
-                        Deep,
-                        Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index),
-                    ),
-                    LocalMutationIsAllowed::No,
-                    flow_state,
-                );
-                // We do not need to call `check_if_path_or_subpath_is_moved`
-                // again, as we already called it when we made the
-                // initial reservation.
-            }
-        });
+        let borrow_set = self.borrow_set.clone();
+        for &borrow_index in borrow_set.activations_at_location(location) {
+            let borrow = &borrow_set[borrow_index];
+
+            // only mutable borrows should be 2-phase
+            assert!(match borrow.kind {
+                BorrowKind::Shared => false,
+                BorrowKind::Unique | BorrowKind::Mut { .. } => true,
+            });
+
+            self.access_place(
+                ContextKind::Activation.new(location),
+                (&borrow.borrowed_place, span),
+                (
+                    Deep,
+                    Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index),
+                ),
+                LocalMutationIsAllowed::No,
+                flow_state,
+            );
+            // We do not need to call `check_if_path_or_subpath_is_moved`
+            // again, as we already called it when we made the
+            // initial reservation.
+        }
     }
 }
 
@@ -1639,10 +1628,18 @@ fn check_access_permissions(
                                             } else {
                                                 self.get_default_err_msg(place)
                                             };
+                                            let sp = self.mir.source_info(locations[0]).span;
+                                            let mut to_suggest_span = String::new();
+                                            if let Ok(src) =
+                                                self.tcx.sess.codemap().span_to_snippet(sp) {
+                                                    to_suggest_span = src[1..].to_string();
+                                            };
                                             err_info = Some((
-                                                self.mir.source_info(locations[0]).span,
+                                                    sp,
                                                     "consider changing this to be a \
-                                                    mutable reference: `&mut`", item_msg,
+                                                    mutable reference",
+                                                    to_suggest_span,
+                                                    item_msg,
                                                     self.get_primary_err_msg(base)));
                                         }
                                 },
@@ -1652,9 +1649,15 @@ fn check_access_permissions(
                         _ => {},
                     }
 
-                    if let Some((err_help_span, err_help_stmt, item_msg, sec_span)) = err_info {
+                    if let Some((err_help_span,
+                                 err_help_stmt,
+                                 to_suggest_span,
+                                 item_msg,
+                                 sec_span)) = err_info {
                         let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
-                        err.span_suggestion(err_help_span, err_help_stmt, format!(""));
+                        err.span_suggestion(err_help_span,
+                                            err_help_stmt,
+                                            format!("&mut {}", to_suggest_span));
                         if place != place_err {
                             err.span_label(span, sec_span);
                         }
@@ -2203,18 +2206,15 @@ fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>> {
         unreachable!("iter::repeat returned None")
     }
 
-    /// This function iterates over all of the current borrows
-    /// (represented by 1-bits in `flow_state.borrows`) that conflict
-    /// with an access to a place, invoking the `op` callback for each
-    /// one.
+    /// This function iterates over all of the in-scope borrows that
+    /// conflict with an access to a place, invoking the `op` callback
+    /// for each one.
     ///
     /// "Current borrow" here means a borrow that reaches the point in
     /// the control-flow where the access occurs.
     ///
-    /// The borrow's phase is represented by the ReserveOrActivateIndex
-    /// passed to the callback: one can call `is_reservation()` and
-    /// `is_activation()` to determine what phase the borrow is
-    /// currently in, when such distinction matters.
+    /// The borrow's phase is represented by the IsActive parameter
+    /// passed to the callback.
     fn each_borrow_involving_path<F>(
         &mut self,
         _context: Context,
@@ -2222,20 +2222,18 @@ fn each_borrow_involving_path<F>(
         flow_state: &Flows<'cx, 'gcx, 'tcx>,
         mut op: F,
     ) where
-        F: FnMut(&mut Self, ReserveOrActivateIndex, &BorrowData<'tcx>) -> Control,
+        F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>) -> Control,
     {
         let (access, place) = access_place;
 
         // FIXME: analogous code in check_loans first maps `place` to
         // its base_path.
 
-        let data = flow_state.borrows.operator().borrows();
-
         // check for loan restricting path P being used. Accounts for
         // borrows of P, P.a.b, etc.
-        let mut iter_incoming = flow_state.borrows.iter_incoming();
-        while let Some(i) = iter_incoming.next() {
-            let borrowed = &data[i.borrow_index()];
+        let borrow_set = self.borrow_set.clone();
+        for i in flow_state.borrows_in_scope() {
+            let borrowed = &borrow_set[i];
 
             if self.places_conflict(&borrowed.borrowed_place, place, access) {
                 debug!(
@@ -2249,6 +2247,65 @@ fn each_borrow_involving_path<F>(
             }
         }
     }
+
+    fn is_active(
+        &self,
+        borrow_data: &BorrowData<'tcx>,
+        location: Location
+    ) -> bool {
+        debug!("is_active(borrow_data={:?}, location={:?})", borrow_data, location);
+
+        // If this is not a 2-phase borrow, it is always active.
+        let activation_location = match borrow_data.activation_location {
+            Some(v) => v,
+            None => return true,
+        };
+
+        // Otherwise, it is active for every location *except* in between
+        // the reservation and the activation:
+        //
+        //       X
+        //      /
+        //     R      <--+ Except for this
+        //    / \        | diamond
+        //    \ /        |
+        //     A  <------+
+        //     |
+        //     Z
+        //
+        // Note that we assume that:
+        // - the reservation R dominates the activation A
+        // - the activation A post-dominates the reservation R (ignoring unwinding edges).
+        //
+        // This means that there can't be an edge that leaves A and
+        // comes back into that diamond unless it passes through R.
+        //
+        // Suboptimal: In some cases, this code walks the dominator
+        // tree twice when it only has to be walked once. I am
+        // lazy. -nmatsakis
+
+        // If dominated by the activation A, then it is active. The
+        // activation occurs upon entering the point A, so this is
+        // also true if location == activation_location.
+        if activation_location.dominates(location, &self.dominators) {
+            return true;
+        }
+
+        // The reservation starts *on exiting* the reservation block,
+        // so check if the location is dominated by R.successor. If so,
+        // this point falls in between the reservation and location.
+        let reserve_location = borrow_data.reserve_location.successor_within_block();
+        if reserve_location.dominates(location, &self.dominators) {
+            false
+        } else {
+            // Otherwise, this point is outside the diamond, so
+            // consider the borrow active. This could happen for
+            // example if the borrow remains active around a loop (in
+            // which case it would be active also for the point R,
+            // which would generate an error).
+            true
+        }
+    }
 }
 
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
index 187bfc2bf90f926784a35c571b88d3f23dcfe1d1..d5e11a312ec26fb763f3be5dc6f8e9c5162131be 100644 (file)
@@ -10,7 +10,7 @@
 
 use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
 use borrow_check::{Context, MirBorrowckCtxt};
-use dataflow::BorrowData;
+use borrow_check::borrow_set::BorrowData;
 use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
 use rustc::mir::{Local, Location, Mir};
 use rustc_data_structures::fx::FxHashSet;
@@ -29,82 +29,81 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
         borrow: &BorrowData<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
     ) {
-        if let Some(regioncx) = &self.nonlexical_regioncx {
-            let mir = self.mir;
+        let regioncx = &&self.nonlexical_regioncx;
+        let mir = self.mir;
 
-            if self.nonlexical_cause_info.is_none() {
-                self.nonlexical_cause_info = Some(regioncx.compute_causal_info(mir));
-            }
+        if self.nonlexical_cause_info.is_none() {
+            self.nonlexical_cause_info = Some(regioncx.compute_causal_info(mir));
+        }
+
+        let cause_info = self.nonlexical_cause_info.as_ref().unwrap();
+        if let Some(cause) = cause_info.why_region_contains_point(borrow.region, context.loc) {
+            match *cause.root_cause() {
+                Cause::LiveVar(local, location) => {
+                    match find_regular_use(mir, regioncx, borrow, location, local) {
+                        Some(p) => {
+                            err.span_label(
+                                mir.source_info(p).span,
+                                format!("borrow later used here"),
+                            );
+                        }
+
+                        None => {
+                            span_bug!(
+                                mir.source_info(context.loc).span,
+                                "Cause should end in a LiveVar"
+                            );
+                        }
+                    }
+                }
 
-            let cause_info = self.nonlexical_cause_info.as_ref().unwrap();
-            if let Some(cause) = cause_info.why_region_contains_point(borrow.region, context.loc) {
-                match *cause.root_cause() {
-                    Cause::LiveVar(local, location) => {
-                        match find_regular_use(mir, regioncx, borrow, location, local) {
-                            Some(p) => {
+                Cause::DropVar(local, location) => {
+                    match find_drop_use(mir, regioncx, borrow, location, local) {
+                        Some(p) => match &mir.local_decls[local].name {
+                            Some(local_name) => {
                                 err.span_label(
                                     mir.source_info(p).span,
-                                    format!("borrow later used here"),
+                                    format!(
+                                        "borrow later used here, when `{}` is dropped",
+                                        local_name
+                                    ),
                                 );
                             }
-
                             None => {
-                                span_bug!(
-                                    mir.source_info(context.loc).span,
-                                    "Cause should end in a LiveVar"
+                                err.span_label(
+                                    mir.local_decls[local].source_info.span,
+                                    "borrow may end up in a temporary, created here",
                                 );
-                            }
-                        }
-                    }
 
-                    Cause::DropVar(local, location) => {
-                        match find_drop_use(mir, regioncx, borrow, location, local) {
-                            Some(p) => match &mir.local_decls[local].name {
-                                Some(local_name) => {
-                                    err.span_label(
-                                        mir.source_info(p).span,
-                                        format!(
-                                            "borrow later used here, when `{}` is dropped",
-                                            local_name
-                                        ),
-                                    );
-                                }
-                                None => {
-                                    err.span_label(
-                                        mir.local_decls[local].source_info.span,
-                                        "borrow may end up in a temporary, created here",
-                                    );
-
-                                    err.span_label(
-                                        mir.source_info(p).span,
-                                        "temporary later dropped here, \
-                                         potentially using the reference",
-                                    );
-                                }
-                            },
-
-                            None => {
-                                span_bug!(
-                                    mir.source_info(context.loc).span,
-                                    "Cause should end in a DropVar"
+                                err.span_label(
+                                    mir.source_info(p).span,
+                                    "temporary later dropped here, \
+                                     potentially using the reference",
                                 );
                             }
-                        }
-                    }
+                        },
 
-                    Cause::UniversalRegion(region_vid) => {
-                        if let Some(region) = regioncx.to_error_region(region_vid) {
-                            self.tcx.note_and_explain_free_region(
-                                err,
-                                "borrowed value must be valid for ",
-                                region,
-                                "...",
+                        None => {
+                            span_bug!(
+                                mir.source_info(context.loc).span,
+                                "Cause should end in a DropVar"
                             );
                         }
                     }
+                }
 
-                    _ => {}
+                Cause::UniversalRegion(region_vid) => {
+                    if let Some(region) = regioncx.to_error_region(region_vid) {
+                        self.tcx.note_and_explain_free_region(
+                            err,
+                            "borrowed value must be valid for ",
+                            region,
+                            "...",
+                        );
+                    }
                 }
+
+                _ => {}
             }
         }
     }
index 942e4fb56cabc0471c3e960e939d6d9f505d0f07..3ca1bd23e86ef4c9556ebcc289dabd076a53354a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use borrow_check::borrow_set::BorrowSet;
 use rustc::hir::def_id::DefId;
 use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir};
 use rustc::infer::InferCtxt;
@@ -73,6 +74,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     param_env: ty::ParamEnv<'gcx>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
+    _borrow_set: &BorrowSet<'tcx>,
 ) -> (
     RegionInferenceContext<'tcx>,
     Option<ClosureRegionRequirements<'gcx>>,
index 2f0b4c24bd6f14ca8aef242511a95c13e3ba53b9..d15d85792d99dc93964a96ffcbaed29eb05009e0 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::mir::{BasicBlock, Location, Mir};
-use rustc::ty::RegionVid;
+use rustc::ty::{self, RegionVid};
 use syntax::codemap::Span;
 
 use super::{Cause, CauseExt, TrackCauses};
@@ -263,7 +263,17 @@ fn add_internal<F>(&mut self, r: RegionVid, i: RegionElementIndex, make_cause: F
             if let Some(causes) = &mut self.causes {
                 let cause = make_cause(causes);
                 let old_cause = causes.get_mut(&(r, i)).unwrap();
-                if cause < **old_cause {
+                // #49998: compare using root cause alone to avoid
+                // useless traffic from similar outlives chains.
+
+                let overwrite = if ty::tls::with(|tcx| {
+                    tcx.sess.opts.debugging_opts.nll_subminimal_causes
+                }) {
+                    cause.root_cause() < old_cause.root_cause()
+                } else {
+                    cause < **old_cause
+                };
+                if overwrite {
                     *old_cause = Rc::new(cause);
                     return true;
                 }
index faa382738b06f6fe071b0545ebed0533946a225e..ec7ee466008a514684ee158e89b78f684f9e6888 100644 (file)
@@ -275,7 +275,7 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                         tcx.predicates_of(def_id).instantiate(tcx, substs);
                     let predicates =
                         type_checker.normalize(&instantiated_predicates.predicates, location);
-                    type_checker.prove_predicates(predicates.iter().cloned(), location);
+                    type_checker.prove_predicates(predicates, location);
                 }
 
                 value.ty
@@ -1516,34 +1516,34 @@ fn prove_aggregate_predicates(
 
         let predicates = self.normalize(&instantiated_predicates.predicates, location);
         debug!("prove_aggregate_predicates: predicates={:?}", predicates);
-        self.prove_predicates(predicates.iter().cloned(), location);
+        self.prove_predicates(predicates, location);
     }
 
     fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) {
         self.prove_predicates(
-            [ty::Predicate::Trait(
+            Some(ty::Predicate::Trait(
                 trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
-            )].iter()
-                .cloned(),
+            )),
             location,
         );
     }
 
-    fn prove_predicates(
-        &mut self,
-        predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>,
-        location: Location,
-    {
-        let mut predicates_iter = predicates.into_iter();
+    fn prove_predicates<T>(&mut self, predicates: T, location: Location)
+    where
+        T: IntoIterator<Item = ty::Predicate<'tcx>>,
+        T::IntoIter: Clone,
+    {
+        let predicates = predicates.into_iter();
 
         debug!(
             "prove_predicates(predicates={:?}, location={:?})",
-            predicates_iter.by_ref().collect::<Vec<_>>(),
-            location
+            predicates.clone().collect::<Vec<_>>(),
+            location,
         );
         self.fully_perform_op(location.at_self(), |this| {
             let cause = this.misc(this.last_span);
-            let obligations = predicates_iter
+            let obligations = predicates
+                .into_iter()
                 .map(|p| traits::Obligation::new(cause.clone(), this.param_env, p))
                 .collect();
             Ok(InferOk {
@@ -1611,7 +1611,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &
 
         // When NLL is enabled, the borrow checker runs the typeck
         // itself, so we don't need this MIR pass anymore.
-        if tcx.nll() {
+        if tcx.use_mir_borrowck() {
             return;
         }
 
index 39dc29ba18b645ae00339258f987b8f16b06f329..0fe6265345de1ecfa7fd6f988dae5fb9acfa42f4 100644 (file)
@@ -259,18 +259,18 @@ pub fn closure_mapping(
 
     /// True if `r` is a member of this set of universal regions.
     pub fn is_universal_region(&self, r: RegionVid) -> bool {
-        (FIRST_GLOBAL_INDEX..self.num_universals).contains(r.index())
+        (FIRST_GLOBAL_INDEX..self.num_universals).contains(&r.index())
     }
 
     /// Classifies `r` as a universal region, returning `None` if this
     /// is not a member of this set of universal regions.
     pub fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> {
         let index = r.index();
-        if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(index) {
+        if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(&index) {
             Some(RegionClassification::Global)
-        } else if (self.first_extern_index..self.first_local_index).contains(index) {
+        } else if (self.first_extern_index..self.first_local_index).contains(&index) {
             Some(RegionClassification::External)
-        } else if (self.first_local_index..self.num_universals).contains(index) {
+        } else if (self.first_local_index..self.num_universals).contains(&index) {
             Some(RegionClassification::Local)
         } else {
             None
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
new file mode 100644 (file)
index 0000000..f6ffe3c
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir;
+use rustc::mir::ProjectionElem;
+use rustc::mir::{Local, Mir, Place};
+use rustc::ty::{self, TyCtxt};
+
+/// Extension methods for the `Place` type.
+crate trait PlaceExt<'tcx> {
+    /// True if this is a deref of a raw pointer.
+    fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool;
+
+    /// If this is a place like `x.f.g`, returns the local
+    /// `x`. Returns `None` if this is based in a static.
+    fn root_local(&self) -> Option<Local>;
+}
+
+impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
+    fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool {
+        match self {
+            Place::Local(_) => false,
+            Place::Static(static_) => {
+                tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
+            }
+            Place::Projection(proj) => match proj.elem {
+                ProjectionElem::Field(..)
+                | ProjectionElem::Downcast(..)
+                | ProjectionElem::Subslice { .. }
+                | ProjectionElem::ConstantIndex { .. }
+                | ProjectionElem::Index(_) => proj.base.is_unsafe_place(tcx, mir),
+                ProjectionElem::Deref => {
+                    let ty = proj.base.ty(mir, tcx).to_ty(tcx);
+                    match ty.sty {
+                        ty::TyRawPtr(..) => true,
+                        _ => proj.base.is_unsafe_place(tcx, mir),
+                    }
+                }
+            },
+        }
+    }
+
+    fn root_local(&self) -> Option<Local> {
+        let mut p = self;
+        loop {
+            match p {
+                Place::Projection(pi) => p = &pi.base,
+                Place::Static(_) => return None,
+                Place::Local(l) => return Some(*l),
+            }
+        }
+    }
+}
index 4e95ee6444dcf956754807bb61380204c2bf9c44..147b8cc2175af9d88de2a6400b16cb5f24c644f1 100644 (file)
@@ -113,6 +113,7 @@ fn simplify_match_pair<'pat>(&mut self,
             PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
                 let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
                     i == variant_index || {
+                        self.hir.tcx().features().never_type &&
                         self.hir.tcx().features().exhaustive_patterns &&
                         self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
                     }
index aa991427be09397b615d9ef466536c7b8afdd5a2..a21691813a4d4bdd8f8edaa579da1430bfef6346 100644 (file)
@@ -8,31 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use borrow_check::borrow_set::{BorrowSet, BorrowData};
+use borrow_check::place_ext::PlaceExt;
+
 use rustc;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::mir::{self, Location, Place, Mir};
-use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::ty::{self, Region, TyCtxt};
+use rustc::ty::TyCtxt;
 use rustc::ty::RegionKind;
 use rustc::ty::RegionKind::ReScope;
-use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
-use rustc_data_structures::bitslice::{BitwiseOperator};
-use rustc_data_structures::indexed_set::{IdxSet};
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::bitslice::BitwiseOperator;
+use rustc_data_structures::indexed_set::IdxSet;
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::sync::Lrc;
 
 use dataflow::{BitDenotation, BlockSets, InitialFlow};
-pub use dataflow::indexes::{BorrowIndex, ReserveOrActivateIndex};
+pub use dataflow::indexes::BorrowIndex;
 use borrow_check::nll::region_infer::RegionInferenceContext;
 use borrow_check::nll::ToRegionVid;
 
-use syntax_pos::Span;
-
-use std::fmt;
-use std::hash::Hash;
 use std::rc::Rc;
 
 /// `Borrows` stores the data used in the analyses that track the flow
@@ -48,534 +45,102 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     scope_tree: Lrc<region::ScopeTree>,
     root_scope: Option<region::Scope>,
 
-    /// The fundamental map relating bitvector indexes to the borrows
-    /// in the MIR.
-    borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
-
-    /// Each borrow is also uniquely identified in the MIR by the
-    /// `Location` of the assignment statement in which it appears on
-    /// the right hand side; we map each such location to the
-    /// corresponding `BorrowIndex`.
-    location_map: FxHashMap<Location, BorrowIndex>,
-
-    /// Every borrow in MIR is immediately stored into a place via an
-    /// assignment statement. This maps each such assigned place back
-    /// to its borrow-indexes.
-    assigned_map: FxHashMap<Place<'tcx>, FxHashSet<BorrowIndex>>,
-
-    /// Locations which activate borrows.
-    activation_map: FxHashMap<Location, FxHashSet<BorrowIndex>>,
-
-    /// Every borrow has a region; this maps each such regions back to
-    /// its borrow-indexes.
-    region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
-
-    /// Map from local to all the borrows on that local
-    local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
-
-    /// Maps regions to their corresponding source spans
-    /// Only contains ReScope()s as keys
-    region_span_map: FxHashMap<RegionKind, Span>,
+    borrow_set: Rc<BorrowSet<'tcx>>,
 
     /// NLL region inference context with which NLL queries should be resolved
-    nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
-}
-
-// temporarily allow some dead fields: `kind` and `region` will be
-// needed by borrowck; `borrowed_place` will probably be a MovePathIndex when
-// that is extended to include borrowed data paths.
-#[allow(dead_code)]
-#[derive(Debug)]
-pub struct BorrowData<'tcx> {
-    /// Location where the borrow reservation starts.
-    /// In many cases, this will be equal to the activation location but not always.
-    pub(crate) reserve_location: Location,
-    /// What kind of borrow this is
-    pub(crate) kind: mir::BorrowKind,
-    /// The region for which this borrow is live
-    pub(crate) region: Region<'tcx>,
-    /// Place from which we are borrowing
-    pub(crate) borrowed_place: mir::Place<'tcx>,
-    /// Place to which the borrow was stored
-    pub(crate) assigned_place: mir::Place<'tcx>,
-}
-
-impl<'tcx> fmt::Display for BorrowData<'tcx> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
-        let kind = match self.kind {
-            mir::BorrowKind::Shared => "",
-            mir::BorrowKind::Unique => "uniq ",
-            mir::BorrowKind::Mut { .. } => "mut ",
-        };
-        let region = format!("{}", self.region);
-        let region = if region.len() > 0 { format!("{} ", region) } else { region };
-        write!(w, "&{}{}{:?}", region, kind, self.borrowed_place)
-    }
-}
-
-impl ReserveOrActivateIndex {
-    fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) }
-    fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) }
-
-    pub(crate) fn is_reservation(self) -> bool { self.index() % 2 == 0 }
-    pub(crate) fn is_activation(self) -> bool { self.index() % 2 == 1}
-
-    pub(crate) fn kind(self) -> &'static str {
-        if self.is_reservation() { "reserved" } else { "active" }
-    }
-    pub(crate) fn borrow_index(self) -> BorrowIndex {
-        BorrowIndex::new(self.index() / 2)
-    }
+    nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
-               nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
-               def_id: DefId,
-               body_id: Option<hir::BodyId>)
-               -> Self {
+    crate fn new(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        mir: &'a Mir<'tcx>,
+        nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
+        def_id: DefId,
+        body_id: Option<hir::BodyId>,
+        borrow_set: &Rc<BorrowSet<'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)
         });
-        let mut visitor = GatherBorrows {
-            tcx,
-            mir,
-            idx_vec: IndexVec::new(),
-            location_map: FxHashMap(),
-            assigned_map: FxHashMap(),
-            activation_map: FxHashMap(),
-            region_map: FxHashMap(),
-            local_map: FxHashMap(),
-            region_span_map: FxHashMap(),
-            nonlexical_regioncx: nonlexical_regioncx.clone()
-        };
-        visitor.visit_mir(mir);
-        return Borrows { tcx: tcx,
-                         mir: mir,
-                         borrows: visitor.idx_vec,
-                         scope_tree,
-                         root_scope,
-                         location_map: visitor.location_map,
-                         assigned_map: visitor.assigned_map,
-                         activation_map: visitor.activation_map,
-                         region_map: visitor.region_map,
-                         local_map: visitor.local_map,
-                         region_span_map: visitor.region_span_map,
-                         nonlexical_regioncx };
-
-        struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
-            tcx: TyCtxt<'a, 'gcx, 'tcx>,
-            mir: &'a Mir<'tcx>,
-            idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
-            location_map: FxHashMap<Location, BorrowIndex>,
-            assigned_map: FxHashMap<Place<'tcx>, FxHashSet<BorrowIndex>>,
-            activation_map: FxHashMap<Location, FxHashSet<BorrowIndex>>,
-            region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
-            local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
-            region_span_map: FxHashMap<RegionKind, Span>,
-            nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
-        }
-
-        impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
-            fn visit_assign(&mut self,
-                            block: mir::BasicBlock,
-                            assigned_place: &mir::Place<'tcx>,
-                            rvalue: &mir::Rvalue<'tcx>,
-                            location: mir::Location) {
-                fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> {
-                    loop { match p {
-                        mir::Place::Projection(pi) => p = &pi.base,
-                        mir::Place::Static(_) => return None,
-                        mir::Place::Local(l) => return Some(*l)
-                    }}
-                }
-
-                if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
-                    if is_unsafe_place(self.tcx, self.mir, borrowed_place) { return; }
-
-                    let activate_location = self.compute_activation_location(location,
-                                                                             &assigned_place,
-                                                                             region,
-                                                                             kind);
-                    let borrow = BorrowData {
-                        kind, region,
-                        reserve_location: location,
-                        borrowed_place: borrowed_place.clone(),
-                        assigned_place: assigned_place.clone(),
-                    };
-                    let idx = self.idx_vec.push(borrow);
-                    self.location_map.insert(location, idx);
-
-                    insert(&mut self.activation_map, &activate_location, idx);
-                    insert(&mut self.assigned_map, assigned_place, idx);
-                    insert(&mut self.region_map, &region, idx);
-                    if let Some(local) = root_local(borrowed_place) {
-                        insert(&mut self.local_map, &local, idx);
-                    }
-                }
-
-                return self.super_assign(block, assigned_place, rvalue, location);
-
-                fn insert<'a, K, V>(map: &'a mut FxHashMap<K, FxHashSet<V>>,
-                                    k: &K,
-                                    v: V)
-                    where K: Clone+Eq+Hash, V: Eq+Hash
-                {
-                    map.entry(k.clone())
-                        .or_insert(FxHashSet())
-                        .insert(v);
-                }
-            }
-
-            fn visit_rvalue(&mut self,
-                            rvalue: &mir::Rvalue<'tcx>,
-                            location: mir::Location) {
-                if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
-                    // double-check that we already registered a BorrowData for this
-
-                    let mut found_it = false;
-                    for idx in &self.region_map[region] {
-                        let bd = &self.idx_vec[*idx];
-                        if bd.reserve_location == location &&
-                            bd.kind == kind &&
-                            bd.region == region &&
-                            bd.borrowed_place == *place
-                        {
-                            found_it = true;
-                            break;
-                        }
-                    }
-                    assert!(found_it, "Ref {:?} at {:?} missing BorrowData", rvalue, location);
-                }
-
-                return self.super_rvalue(rvalue, location);
-            }
-
-            fn visit_statement(&mut self,
-                               block: mir::BasicBlock,
-                               statement: &mir::Statement<'tcx>,
-                               location: Location) {
-                if let mir::StatementKind::EndRegion(region_scope) = statement.kind {
-                    self.region_span_map.insert(ReScope(region_scope), statement.source_info.span);
-                }
-                return self.super_statement(block, statement, location);
-            }
-        }
-
-        /// A MIR visitor that determines if a specific place is used in a two-phase activating
-        /// manner in a given chunk of MIR.
-        struct ContainsUseOfPlace<'b, 'tcx: 'b> {
-            target: &'b Place<'tcx>,
-            use_found: bool,
-        }
-
-        impl<'b, 'tcx: 'b> ContainsUseOfPlace<'b, 'tcx> {
-            fn new(place: &'b Place<'tcx>) -> Self {
-                Self { target: place, use_found: false }
-            }
-
-            /// return whether `context` should be considered a "use" of a
-            /// place found in that context. "Uses" activate associated
-            /// borrows (at least when such uses occur while the borrow also
-            /// has a reservation at the time).
-            fn is_potential_use(context: PlaceContext) -> bool {
-                match context {
-                    // storage effects on a place do not activate it
-                    PlaceContext::StorageLive | PlaceContext::StorageDead => false,
-
-                    // validation effects do not activate a place
-                    //
-                    // FIXME: Should they? Is it just another read? Or can we
-                    // guarantee it won't dereference the stored address? How
-                    // "deep" does validation go?
-                    PlaceContext::Validate => false,
-
-                    // FIXME: This is here to not change behaviour from before
-                    // AsmOutput existed, but it's not necessarily a pure overwrite.
-                    // so it's possible this should activate the place.
-                    PlaceContext::AsmOutput |
-                    // pure overwrites of a place do not activate it. (note
-                    // PlaceContext::Call is solely about dest place)
-                    PlaceContext::Store | PlaceContext::Call => false,
-
-                    // reads of a place *do* activate it
-                    PlaceContext::Move |
-                    PlaceContext::Copy |
-                    PlaceContext::Drop |
-                    PlaceContext::Inspect |
-                    PlaceContext::Borrow { .. } |
-                    PlaceContext::Projection(..) => true,
-                }
-            }
-        }
-
-        impl<'b, 'tcx: 'b> Visitor<'tcx> for ContainsUseOfPlace<'b, 'tcx> {
-            fn visit_place(&mut self,
-                           place: &mir::Place<'tcx>,
-                           context: PlaceContext<'tcx>,
-                           location: Location) {
-                if Self::is_potential_use(context) && place == self.target {
-                    self.use_found = true;
-                    return;
-                    // There is no need to keep checking the statement, we already found a use
-                }
-
-                self.super_place(place, context, location);
-            }
-        }
-
-        impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
-            /// Returns true if the borrow represented by `kind` is
-            /// allowed to be split into separate Reservation and
-            /// Activation phases.
-            fn allow_two_phase_borrow(&self, kind: mir::BorrowKind) -> bool {
-                self.tcx.two_phase_borrows() &&
-                    (kind.allows_two_phase_borrow() ||
-                     self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref)
-            }
-
-            /// Returns true if the given location contains an NLL-activating use of the given place
-            fn location_contains_use(&self, location: Location, place: &Place) -> bool {
-                let mut use_checker = ContainsUseOfPlace::new(place);
-                let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
-                    panic!("could not find block at location {:?}", location);
-                });
-                if location.statement_index != block.statements.len() {
-                    // This is a statement
-                    let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| {
-                        panic!("could not find statement at location {:?}");
-                    });
-                    use_checker.visit_statement(location.block, stmt, location);
-                } else {
-                    // This is a terminator
-                    match block.terminator {
-                        Some(ref term) => {
-                            use_checker.visit_terminator(location.block, term, location);
-                        }
-                        None => {
-                            // There is no way for Place to be used by the terminator if there is no
-                            // terminator
-                        }
-                    }
-                }
-
-                use_checker.use_found
-            }
-
-            /// Determines if the provided region is terminated after the provided location.
-            /// EndRegion statements terminate their enclosed region::Scope.
-            /// We also consult with the NLL region inference engine, should one be available
-            fn region_terminated_after(&self, region: Region<'tcx>, location: Location) -> bool {
-                let block_data = &self.mir[location.block];
-                if location.statement_index != block_data.statements.len() {
-                    let stmt = &block_data.statements[location.statement_index];
-                    if let mir::StatementKind::EndRegion(region_scope) = stmt.kind {
-                        if &ReScope(region_scope) == region {
-                            // We encountered an EndRegion statement that terminates the provided
-                            // region
-                            return true;
-                        }
-                    }
-                }
-                if let Some(ref regioncx) = self.nonlexical_regioncx {
-                    if !regioncx.region_contains_point(region, location) {
-                        // NLL says the region has ended already
-                        return true;
-                    }
-                }
-
-                false
-            }
-
-            /// Computes the activation location of a borrow.
-            /// The general idea is to start at the beginning of the region and perform a DFS
-            /// until we exit the region, either via an explicit EndRegion or because NLL tells
-            /// us so. If we find more than one valid activation point, we currently panic the
-            /// compiler since two-phase borrows are only currently supported for compiler-
-            /// generated code. More precisely, we only allow two-phase borrows for:
-            ///   - Function calls (fn some_func(&mut self, ....))
-            ///   - *Assign operators (a += b -> fn add_assign(&mut self, other: Self))
-            /// See
-            ///   - https://github.com/rust-lang/rust/issues/48431
-            /// for detailed design notes.
-            /// See the FIXME in the body of the function for notes on extending support to more
-            /// general two-phased borrows.
-            fn compute_activation_location(&self,
-                                           start_location: Location,
-                                           assigned_place: &mir::Place<'tcx>,
-                                           region: Region<'tcx>,
-                                           kind: mir::BorrowKind) -> Location {
-                debug!("Borrows::compute_activation_location({:?}, {:?}, {:?})",
-                       start_location,
-                       assigned_place,
-                       region);
-                if !self.allow_two_phase_borrow(kind) {
-                    debug!("  -> {:?}", start_location);
-                    return start_location;
-                }
-
-                // Perform the DFS.
-                // `stack` is the stack of locations still under consideration
-                // `visited` is the set of points we have already visited
-                // `found_use` is an Option that becomes Some when we find a use
-                let mut stack = vec![start_location];
-                let mut visited = FxHashSet();
-                let mut found_use = None;
-                while let Some(curr_loc) = stack.pop() {
-                    let block_data = &self.mir.basic_blocks()
-                        .get(curr_loc.block)
-                        .unwrap_or_else(|| {
-                            panic!("could not find block at location {:?}", curr_loc);
-                        });
-
-                    if self.region_terminated_after(region, curr_loc) {
-                        // No need to process this statement.
-                        // It's either an EndRegion (and thus couldn't use assigned_place) or not
-                        // contained in the NLL region and thus a use would be invalid
-                        continue;
-                    }
-
-                    if !visited.insert(curr_loc) {
-                        debug!("  Already visited {:?}", curr_loc);
-                        continue;
-                    }
-
-                    if self.location_contains_use(curr_loc, assigned_place) {
-                        // FIXME: Handle this case a little more gracefully. Perhaps collect
-                        // all uses in a vector, and find the point in the CFG that dominates
-                        // all of them?
-                        // Right now this is sufficient though since there should only be exactly
-                        // one borrow-activating use of the borrow.
-                        assert!(found_use.is_none(), "Found secondary use of place");
-                        found_use = Some(curr_loc);
-                    }
-
-                    // Push the points we should consider next.
-                    if curr_loc.statement_index < block_data.statements.len() {
-                        stack.push(curr_loc.successor_within_block());
-                    } else {
-                        stack.extend(block_data.terminator().successors().iter().map(
-                            |&basic_block| {
-                                Location {
-                                    statement_index: 0,
-                                    block: basic_block
-                                }
-                            }
-                        ))
-                    }
-                }
 
-                let found_use = found_use.expect("Did not find use of two-phase place");
-                debug!("  -> {:?}", found_use);
-                found_use
-            }
-        }
-    }
-
-    /// Returns the span for the "end point" given region. This will
-    /// return `None` if NLL is enabled, since that concept has no
-    /// meaning there.  Otherwise, return region span if it exists and
-    /// span for end of the function if it doesn't exist.
-    pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option<Span> {
-        match self.nonlexical_regioncx {
-            Some(_) => None,
-            None => {
-                match self.region_span_map.get(region) {
-                    Some(span) => Some(self.tcx.sess.codemap().end_point(*span)),
-                    None => Some(self.tcx.sess.codemap().end_point(self.mir.span))
-                }
-            }
+        Borrows {
+            tcx: tcx,
+            mir: mir,
+            borrow_set: borrow_set.clone(),
+            scope_tree,
+            root_scope,
+            nonlexical_regioncx,
         }
     }
 
-    pub fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrows }
+    crate fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrow_set.borrows }
 
     pub fn scope_tree(&self) -> &Lrc<region::ScopeTree> { &self.scope_tree }
 
     pub fn location(&self, idx: BorrowIndex) -> &Location {
-        &self.borrows[idx].reserve_location
+        &self.borrow_set.borrows[idx].reserve_location
     }
 
     /// Add all borrows to the kill set, if those borrows are out of scope at `location`.
     /// That means either they went out of either a nonlexical scope, if we care about those
     /// at the moment, or the location represents a lexical EndRegion
     fn kill_loans_out_of_scope_at_location(&self,
-                                           sets: &mut BlockSets<ReserveOrActivateIndex>,
+                                           sets: &mut BlockSets<BorrowIndex>,
                                            location: Location) {
-        if let Some(ref regioncx) = self.nonlexical_regioncx {
-            // NOTE: The state associated with a given `location`
-            // reflects the dataflow on entry to the statement. If it
-            // does not contain `borrow_region`, then then that means
-            // that the statement at `location` kills the borrow.
-            //
-            // We are careful always to call this function *before* we
-            // set up the gen-bits for the statement or
-            // termanator. That way, if the effect of the statement or
-            // terminator *does* introduce a new loan of the same
-            // region, then setting that gen-bit will override any
-            // potential kill introduced here.
-            for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
-                let borrow_region = borrow_data.region.to_region_vid();
-                if !regioncx.region_contains_point(borrow_region, location) {
-                    sets.kill(&ReserveOrActivateIndex::reserved(borrow_index));
-                    sets.kill(&ReserveOrActivateIndex::active(borrow_index));
-                }
+        let regioncx = &self.nonlexical_regioncx;
+
+        // NOTE: The state associated with a given `location`
+        // reflects the dataflow on entry to the statement. If it
+        // does not contain `borrow_region`, then then that means
+        // that the statement at `location` kills the borrow.
+        //
+        // We are careful always to call this function *before* we
+        // set up the gen-bits for the statement or
+        // termanator. That way, if the effect of the statement or
+        // terminator *does* introduce a new loan of the same
+        // region, then setting that gen-bit will override any
+        // potential kill introduced here.
+        for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() {
+            let borrow_region = borrow_data.region.to_region_vid();
+            if !regioncx.region_contains_point(borrow_region, location) {
+                sets.kill(&borrow_index);
             }
         }
     }
 
     fn kill_borrows_on_local(&self,
-                             sets: &mut BlockSets<ReserveOrActivateIndex>,
+                             sets: &mut BlockSets<BorrowIndex>,
                              local: &rustc::mir::Local)
     {
-        if let Some(borrow_indexes) = self.local_map.get(local) {
-            sets.kill_all(borrow_indexes.iter()
-                          .map(|b| ReserveOrActivateIndex::reserved(*b)));
-            sets.kill_all(borrow_indexes.iter()
-                          .map(|b| ReserveOrActivateIndex::active(*b)));
-        }
-    }
-
-    /// Performs the activations for a given location
-    fn perform_activations_at_location(&self,
-                                       sets: &mut BlockSets<ReserveOrActivateIndex>,
-                                       location: Location) {
-        // Handle activations
-        match self.activation_map.get(&location) {
-            Some(activations) => {
-                for activated in activations {
-                    debug!("activating borrow {:?}", activated);
-                    sets.gen(&ReserveOrActivateIndex::active(*activated))
-                }
-            }
-            None => {}
+        if let Some(borrow_indexes) = self.borrow_set.local_map.get(local) {
+            sets.kill_all(borrow_indexes);
         }
     }
 }
 
 impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
-    type Idx = ReserveOrActivateIndex;
+    type Idx = BorrowIndex;
     fn name() -> &'static str { "borrows" }
     fn bits_per_block(&self) -> usize {
-        self.borrows.len() * 2
+        self.borrow_set.borrows.len() * 2
     }
 
-    fn start_block_effect(&self, _entry_set: &mut IdxSet<ReserveOrActivateIndex>) {
+    fn start_block_effect(&self, _entry_set: &mut IdxSet<BorrowIndex>) {
         // no borrows of code region_scopes have been taken prior to
         // function execution, so this method has no effect on
         // `_sets`.
     }
 
     fn before_statement_effect(&self,
-                               sets: &mut BlockSets<ReserveOrActivateIndex>,
+                               sets: &mut BlockSets<BorrowIndex>,
                                location: Location) {
         debug!("Borrows::before_statement_effect sets: {:?} location: {:?}", sets, location);
         self.kill_loans_out_of_scope_at_location(sets, location);
     }
 
-    fn statement_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, location: Location) {
+    fn statement_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Location) {
         debug!("Borrows::statement_effect sets: {:?} location: {:?}", sets, location);
 
         let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
@@ -585,21 +150,10 @@ fn statement_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locatio
             panic!("could not find statement at location {:?}");
         });
 
-        self.perform_activations_at_location(sets, location);
         self.kill_loans_out_of_scope_at_location(sets, location);
 
         match stmt.kind {
-            // EndRegion kills any borrows (reservations and active borrows both)
-            mir::StatementKind::EndRegion(region_scope) => {
-                if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) {
-                    assert!(self.nonlexical_regioncx.is_none());
-                    for idx in borrow_indexes {
-                        sets.kill(&ReserveOrActivateIndex::reserved(*idx));
-                        sets.kill(&ReserveOrActivateIndex::active(*idx));
-                    }
-                } else {
-                    // (if there is no entry, then there are no borrows to be tracked)
-                }
+            mir::StatementKind::EndRegion(_) => {
             }
 
             mir::StatementKind::Assign(ref lhs, ref rhs) => {
@@ -617,22 +171,22 @@ fn statement_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locatio
                 // propagate_call_return method.
 
                 if let mir::Rvalue::Ref(region, _, ref place) = *rhs {
-                    if is_unsafe_place(self.tcx, self.mir, place) { return; }
-                    let index = self.location_map.get(&location).unwrap_or_else(|| {
+                    if place.is_unsafe_place(self.tcx, self.mir) { return; }
+                    let index = self.borrow_set.location_map.get(&location).unwrap_or_else(|| {
                         panic!("could not find BorrowIndex for location {:?}", location);
                     });
 
                     if let RegionKind::ReEmpty = region {
                         // If the borrowed value dies before the borrow is used, the region for
                         // the borrow can be empty. Don't track the borrow in that case.
-                        sets.kill(&ReserveOrActivateIndex::active(*index));
+                        sets.kill(&index);
                         return
                     }
 
-                    assert!(self.region_map.get(region).unwrap_or_else(|| {
+                    assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| {
                         panic!("could not find BorrowIndexs for region {:?}", region);
                     }).contains(&index));
-                    sets.gen(&ReserveOrActivateIndex::reserved(*index));
+                    sets.gen(&index);
 
                     // Issue #46746: Two-phase borrows handles
                     // stmts of form `Tmp = &mut Borrow` ...
@@ -643,7 +197,7 @@ fn statement_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locatio
                             // e.g. `box (&mut _)`. Current
                             // conservative solution: force
                             // immediate activation here.
-                            sets.gen(&ReserveOrActivateIndex::active(*index));
+                            sets.gen(&index);
                         }
                     }
                 }
@@ -679,13 +233,13 @@ fn statement_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locatio
     }
 
     fn before_terminator_effect(&self,
-                                sets: &mut BlockSets<ReserveOrActivateIndex>,
+                                sets: &mut BlockSets<BorrowIndex>,
                                 location: Location) {
         debug!("Borrows::before_terminator_effect sets: {:?} location: {:?}", sets, location);
         self.kill_loans_out_of_scope_at_location(sets, location);
     }
 
-    fn terminator_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, location: Location) {
+    fn terminator_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Location) {
         debug!("Borrows::terminator_effect sets: {:?} location: {:?}", sets, location);
 
         let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
@@ -693,7 +247,6 @@ fn terminator_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locati
         });
 
         let term = block.terminator();
-        self.perform_activations_at_location(sets, location);
         self.kill_loans_out_of_scope_at_location(sets, location);
 
 
@@ -707,7 +260,7 @@ fn terminator_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locati
                 // and hence most of these loans will already be dead -- but, in some cases
                 // like unwind paths, we do not always emit `EndRegion` statements, so we
                 // add some kills here as a "backup" and to avoid spurious error messages.
-                for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
+                for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() {
                     if let ReScope(scope) = borrow_data.region {
                         // Check that the scope is not actually a scope from a function that is
                         // a parent of our closure. Note that the CallSite scope itself is
@@ -716,8 +269,7 @@ fn terminator_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locati
                             if *scope != root_scope &&
                                 self.scope_tree.is_subscope_of(*scope, root_scope)
                             {
-                                sets.kill(&ReserveOrActivateIndex::reserved(borrow_index));
-                                sets.kill(&ReserveOrActivateIndex::active(borrow_index));
+                                sets.kill(&borrow_index);
                             }
                         }
                     }
@@ -738,7 +290,7 @@ fn terminator_effect(&self, sets: &mut BlockSets<ReserveOrActivateIndex>, locati
     }
 
     fn propagate_call_return(&self,
-                             _in_out: &mut IdxSet<ReserveOrActivateIndex>,
+                             _in_out: &mut IdxSet<BorrowIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              _dest_place: &mir::Place) {
@@ -764,34 +316,3 @@ fn bottom_value() -> bool {
     }
 }
 
-fn is_unsafe_place<'a, 'gcx: 'tcx, 'tcx: 'a>(
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
-    place: &mir::Place<'tcx>
-) -> bool {
-    use self::mir::Place::*;
-    use self::mir::ProjectionElem;
-
-    match *place {
-        Local(_) => false,
-        Static(ref static_) => tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable),
-        Projection(ref proj) => {
-            match proj.elem {
-                ProjectionElem::Field(..) |
-                ProjectionElem::Downcast(..) |
-                ProjectionElem::Subslice { .. } |
-                ProjectionElem::ConstantIndex { .. } |
-                ProjectionElem::Index(_) => {
-                    is_unsafe_place(tcx, mir, &proj.base)
-                }
-                ProjectionElem::Deref => {
-                    let ty = proj.base.ty(mir, tcx).to_ty(tcx);
-                    match ty.sty {
-                        ty::TyRawPtr(..) => true,
-                        _ => is_unsafe_place(tcx, mir, &proj.base),
-                    }
-                }
-            }
-        }
-    }
-}
index 287640439c0e8f9ab39216066e8e64eb38bc64d6..f64fd64b283ea5ea63ad992123d702695f28bffa 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::MoveDataParamEnv;
+
 use util::elaborate_drops::DropFlagState;
 
 use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex};
@@ -37,7 +38,6 @@
 
 pub use self::borrowed_locals::*;
 
-#[allow(dead_code)]
 pub(super) mod borrows;
 
 /// `MaybeInitializedPlaces` tracks all places that might be
index 454b6cbd27df1e93b20952c3964b32ef8507d02a..85458c7d6848848174a9eab94fb1ea47bf610a8a 100644 (file)
@@ -29,9 +29,8 @@
 pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements};
 pub use self::impls::EverInitializedPlaces;
-pub use self::impls::borrows::{Borrows, BorrowData};
+pub use self::impls::borrows::Borrows;
 pub use self::impls::HaveBeenBorrowedLocals;
-pub(crate) use self::impls::borrows::{ReserveOrActivateIndex};
 pub use self::at_location::{FlowAtLocation, FlowsAtLocation};
 pub(crate) use self::drop_flag_effects::*;
 
index 9f6cf8c036e19a686e44febe3a783e252f8dd44c..3a49e28f04187dbaf71b8e4e1bf7cd0cd1421f45 100644 (file)
@@ -65,9 +65,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
     /// Index into Borrows.locations
     new_index!(BorrowIndex, "bw");
-
-    /// Index into Reservations/Activations bitvector
-    new_index!(ReserveOrActivateIndex, "ra");
 }
 
 pub use self::indexes::MovePathIndex;
index 6f8b1f8e799403bd2d5497425a05f98f5c795284..ff7b4f9e0fd70e00580e03fd804a38c9d2b20bf9 100644 (file)
@@ -985,15 +985,17 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
     Ok(true)
 }
 
-fn constructor_covered_by_range(ctor: &Constructor,
-                                from: &ConstVal, to: &ConstVal,
-                                end: RangeEnd,
-                                ty: Ty)
-                                -> Result<bool, ErrorReported> {
+fn constructor_covered_by_range<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ctor: &Constructor,
+    from: &ConstVal, to: &ConstVal,
+    end: RangeEnd,
+    ty: Ty<'tcx>,
+) -> Result<bool, ErrorReported> {
     trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
-    let cmp_from = |c_from| compare_const_vals(c_from, from, ty)
+    let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, ty)
         .map(|res| res != Ordering::Less);
-    let cmp_to = |c_to| compare_const_vals(c_to, to, ty);
+    let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, ty);
     macro_rules! some_or_ok {
         ($e:expr) => {
             match $e {
@@ -1105,6 +1107,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                 },
                 _ => {
                     match constructor_covered_by_range(
+                        cx.tcx,
                         constructor, &value.val, &value.val, RangeEnd::Included,
                         value.ty,
                             ) {
@@ -1118,6 +1121,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
 
         PatternKind::Range { lo, hi, ref end } => {
             match constructor_covered_by_range(
+                cx.tcx,
                 constructor, &lo.val, &hi.val, end.clone(), lo.ty,
             ) {
                 Ok(true) => Some(vec![]),
index 8d2b73d6ba033842693aa3dd6827c1575864e8e5..9f17af8b16f1d7501cf00a0248c02495aa2509c1 100644 (file)
@@ -16,7 +16,7 @@
 pub use self::check_match::check_crate;
 pub(crate) use self::check_match::check_match;
 
-use interpret::{const_val_field, const_discr};
+use interpret::{const_val_field, const_discr, self};
 
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::{Field, BorrowKind, Mutability};
@@ -372,7 +372,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                     (PatternKind::Constant { value: lo },
                      PatternKind::Constant { value: hi }) => {
                         use std::cmp::Ordering;
-                        match (end, compare_const_vals(&lo.val, &hi.val, ty).unwrap()) {
+                        match (end, compare_const_vals(self.tcx, &lo.val, &hi.val, ty).unwrap()) {
                             (RangeEnd::Excluded, Ordering::Less) =>
                                 PatternKind::Range { lo, hi, end },
                             (RangeEnd::Excluded, _) => {
@@ -1076,7 +1076,12 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
     }
 }
 
-pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering> {
+pub fn compare_const_vals<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    a: &ConstVal,
+    b: &ConstVal,
+    ty: Ty<'tcx>,
+) -> Option<Ordering> {
     use rustc_const_math::ConstFloat;
     trace!("compare_const_vals: {:?}, {:?}", a, b);
     use rustc::mir::interpret::{Value, PrimVal};
@@ -1096,7 +1101,11 @@ pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering
                     // FIXME(oli-obk): report cmp errors?
                     l.try_cmp(r).ok()
                 },
-                ty::TyInt(_) => Some((a as i128).cmp(&(b as i128))),
+                ty::TyInt(_) => {
+                    let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt");
+                    let b = interpret::sign_extend(tcx, b, ty).expect("layout error for TyInt");
+                    Some((a as i128).cmp(&(b as i128)))
+                },
                 _ => Some(a.cmp(&b)),
             }
         },
index 954a3dbe5b9ab0e78224cb1a508925810b4606a5..6fa68eb6ff1f098195d51a9f13e97e519aa30c68 100644 (file)
@@ -56,7 +56,7 @@ pub fn mk_eval_cx<'a, 'tcx>(
     Ok(ecx)
 }
 
-pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
+pub fn eval_promoted<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cid: GlobalId<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
@@ -66,7 +66,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
     match res {
         Ok(val) => Some(val),
         Err(mut err) => {
-            ecx.report(&mut err, true, None);
+            ecx.report(&mut err, false, None);
             None
         }
     }
index 03785f9623b8c0b6925d15f77556cd3f6b57add1..a5ddd50ae10c50f969224c294159aff76e412ba0 100644 (file)
@@ -260,7 +260,7 @@ pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalR
             self.param_env,
             def_id,
             substs,
-        ).ok_or(EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue
+        ).ok_or_else(|| EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue
     }
 
     pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
@@ -279,9 +279,9 @@ pub fn load_mir(
         trace!("load mir {:?}", instance);
         match instance {
             ty::InstanceDef::Item(def_id) => {
-                self.tcx.maybe_optimized_mir(def_id).ok_or_else(|| {
+                self.tcx.maybe_optimized_mir(def_id).ok_or_else(||
                     EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into()
-                })
+                )
             }
             _ => Ok(self.tcx.instance_mir(instance)),
         }
@@ -691,7 +691,7 @@ pub(super) fn eval_rvalue_into_place(
                                     self.param_env,
                                     def_id,
                                     substs,
-                                ).ok_or(EvalErrorKind::TypeckError.into());
+                                ).ok_or_else(|| EvalErrorKind::TypeckError.into());
                                 let fn_ptr = self.memory.create_fn_alloc(instance?);
                                 let valty = ValTy {
                                     value: Value::ByVal(PrimVal::Ptr(fn_ptr)),
@@ -1679,27 +1679,17 @@ pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span
     }
 
     pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
-        let layout = self.layout_of(ty)?;
-        let size = layout.size.bits();
-        assert!(layout.abi.is_signed());
-        // sign extend
-        let amt = 128 - size;
-        // shift the unsigned value to the left
-        // and back to the right as signed (essentially fills with FF on the left)
-        Ok((((value << amt) as i128) >> amt) as u128)
+        super::sign_extend(self.tcx.tcx, value, ty)
     }
 
     pub fn truncate(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
-        let size = self.layout_of(ty)?.size.bits();
-        let amt = 128 - size;
-        // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
-        Ok((value << amt) >> amt)
+        super::truncate(self.tcx.tcx, value, ty)
     }
 }
 
 impl<'mir, 'tcx> Frame<'mir, 'tcx> {
     pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> {
-        self.locals[local].ok_or(EvalErrorKind::DeadLocal.into())
+        self.locals[local].ok_or_else(|| EvalErrorKind::DeadLocal.into())
     }
 
     fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> {
index ae6337d82c3e3bd954be2be08b91ae57b6823e1d..e0e05d6ae60ae868c18a78915173ff41974a654d 100644 (file)
@@ -19,7 +19,7 @@
 pub use self::memory::{Memory, MemoryKind, HasMemory};
 
 pub use self::const_eval::{
-    eval_body_with_mir,
+    eval_promoted,
     mk_borrowck_eval_cx,
     eval_body,
     CompileTimeEvaluator,
 pub use self::machine::Machine;
 
 pub use self::memory::{write_target_uint, write_target_int, read_target_uint};
+
+use rustc::mir::interpret::{EvalResult, EvalErrorKind};
+use rustc::ty::{Ty, TyCtxt, ParamEnv};
+
+pub fn sign_extend<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
+    let param_env = ParamEnv::empty();
+    let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?;
+    let size = layout.size.bits();
+    assert!(layout.abi.is_signed());
+    // sign extend
+    let amt = 128 - size;
+    // shift the unsigned value to the left
+    // and back to the right as signed (essentially fills with FF on the left)
+    Ok((((value << amt) as i128) >> amt) as u128)
+}
+
+pub fn truncate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
+    let param_env = ParamEnv::empty();
+    let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?;
+    let size = layout.size.bits();
+    let amt = 128 - size;
+    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
+    Ok((value << amt) >> amt)
+}
index a701fe3144266766d32bb8212a29f969605e274d..a47b3cacc517e1fc6694c632a9a851349886b4f3 100644 (file)
@@ -20,6 +20,7 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(catch_expr)]
+#![feature(crate_visibility_modifier)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
@@ -32,6 +33,7 @@
 #![feature(nonzero)]
 #![feature(inclusive_range_fields)]
 #![feature(crate_visibility_modifier)]
+#![feature(never_type)]
 #![cfg_attr(stage0, feature(try_trait))]
 
 extern crate arena;
index 008165f33b2bbc69f23fffa1c9a7aac0ae907c5b..610e70b39ccf994e035da02f327858e325e33d3a 100644 (file)
@@ -1177,7 +1177,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         param_substs: instance.substs,
     }.visit_mir(&mir);
     let param_env = ty::ParamEnv::reveal_all();
-    for (i, promoted) in mir.promoted.iter().enumerate() {
+    for i in 0..mir.promoted.len() {
         use rustc_data_structures::indexed_vec::Idx;
         let cid = GlobalId {
             instance,
@@ -1185,9 +1185,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
         match tcx.const_eval(param_env.and(cid)) {
             Ok(val) => collect_const(tcx, val, instance.substs, output),
-            Err(err) => {
-                err.report(tcx, promoted.span, "promoted");
-            }
+            Err(_) => {},
         }
     }
 }
index f133d6e9c6dee847be829b68e1246284cc62091c..a3d96f0c0739d6b0c45191d1ba604e7b2dda155e 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, PrimVal, GlobalId};
-use interpret::{eval_body_with_mir, mk_borrowck_eval_cx, ValTy};
+use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy};
 use transform::{MirPass, MirSource};
 use syntax::codemap::Span;
 use rustc::ty::subst::Substs;
@@ -161,7 +161,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
-                let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, self.param_env)?;
+                let (value, _, ty) = eval_promoted(self.tcx, cid, self.mir, self.param_env)?;
                 let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 Some(val)
index aeefd5ab1d5aca903db44e5e8b20d7d2e4e3744b..591732fbba911481c309062023a2af830daf9c67 100644 (file)
@@ -964,7 +964,7 @@ fn visit_terminator_kind(&mut self,
                     let (msg, note) = if let UnstableFeatures::Disallow =
                             self.tcx.sess.opts.unstable_features {
                         (format!("calls in {}s are limited to \
-                                  struct and enum constructors",
+                                  tuple structs and tuple variants",
                                  self.mode),
                          Some("a limited form of compile-time function \
                                evaluation is available on a nightly \
@@ -972,7 +972,7 @@ struct and enum constructors",
                     } else {
                         (format!("calls in {}s are limited \
                                   to constant functions, \
-                                  struct and enum constructors",
+                                  tuple structs and tuple variants",
                                  self.mode),
                          None)
                     };
index 1866122454c7057cab50c8511a3a1d2775512a0a..6708640379a54d2157a5f5adaba426a4d35c1d76 100644 (file)
@@ -273,7 +273,9 @@ fn visit_item(&mut self, item: &'a Item) {
                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
                 }
                 if defaultness == Defaultness::Default {
-                    self.err_handler().span_err(item.span, "inherent impls cannot be default");
+                    self.err_handler()
+                        .struct_span_err(item.span, "inherent impls cannot be default")
+                        .note("only trait implementations may be annotated with default").emit();
                 }
             }
             ItemKind::ForeignMod(..) => {
index 01940ee4fd0f6b09da8e84e4f0fdef7fa89d1a2d..671856c4e549e34507dc8dbf18d5eaaf83a50e30 100644 (file)
@@ -962,38 +962,38 @@ enum TypeParameters<'a, 'b> {
                       RibKind<'a>),
 }
 
-// The rib kind controls the translation of local
-// definitions (`Def::Local`) to upvars (`Def::Upvar`).
+/// The rib kind controls the translation of local
+/// definitions (`Def::Local`) to upvars (`Def::Upvar`).
 #[derive(Copy, Clone, Debug)]
 enum RibKind<'a> {
-    // No translation needs to be applied.
+    /// No translation needs to be applied.
     NormalRibKind,
 
-    // We passed through a closure scope at the given node ID.
-    // Translate upvars as appropriate.
+    /// We passed through a closure scope at the given node ID.
+    /// Translate upvars as appropriate.
     ClosureRibKind(NodeId /* func id */),
 
-    // We passed through an impl or trait and are now in one of its
-    // methods or associated types. Allow references to ty params that impl or trait
-    // binds. Disallow any other upvars (including other ty params that are
-    // upvars).
+    /// We passed through an impl or trait and are now in one of its
+    /// methods or associated types. Allow references to ty params that impl or trait
+    /// binds. Disallow any other upvars (including other ty params that are
+    /// upvars).
     TraitOrImplItemRibKind,
 
-    // We passed through an item scope. Disallow upvars.
+    /// We passed through an item scope. Disallow upvars.
     ItemRibKind,
 
-    // We're in a constant item. Can't refer to dynamic stuff.
+    /// We're in a constant item. Can't refer to dynamic stuff.
     ConstantItemRibKind,
 
-    // We passed through a module.
+    /// We passed through a module.
     ModuleRibKind(Module<'a>),
 
-    // We passed through a `macro_rules!` statement
+    /// We passed through a `macro_rules!` statement
     MacroDefinition(DefId),
 
-    // All bindings in this rib are type parameters that can't be used
-    // from the default of a type parameter because they're not declared
-    // before said type parameter. Also see the `visit_generics` override.
+    /// All bindings in this rib are type parameters that can't be used
+    /// from the default of a type parameter because they're not declared
+    /// before said type parameter. Also see the `visit_generics` override.
     ForwardTyParamBanRibKind,
 }
 
@@ -1198,7 +1198,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-// Records a possibly-private value, type, or module definition.
+/// Records a possibly-private value, type, or module definition.
 #[derive(Clone, Debug)]
 pub struct NameBinding<'a> {
     kind: NameBindingKind<'a>,
@@ -1408,36 +1408,36 @@ pub struct Resolver<'a> {
 
     prelude: Option<Module<'a>>,
 
-    // n.b. This is used only for better diagnostics, not name resolution itself.
+    /// n.b. This is used only for better diagnostics, not name resolution itself.
     has_self: FxHashSet<DefId>,
 
-    // Names of fields of an item `DefId` accessible with dot syntax.
-    // Used for hints during error reporting.
+    /// Names of fields of an item `DefId` accessible with dot syntax.
+    /// Used for hints during error reporting.
     field_names: FxHashMap<DefId, Vec<Name>>,
 
-    // All imports known to succeed or fail.
+    /// All imports known to succeed or fail.
     determined_imports: Vec<&'a ImportDirective<'a>>,
 
-    // All non-determined imports.
+    /// All non-determined imports.
     indeterminate_imports: Vec<&'a ImportDirective<'a>>,
 
-    // The module that represents the current item scope.
+    /// The module that represents the current item scope.
     current_module: Module<'a>,
 
-    // The current set of local scopes for types and values.
-    // FIXME #4948: Reuse ribs to avoid allocation.
+    /// The current set of local scopes for types and values.
+    /// FIXME #4948: Reuse ribs to avoid allocation.
     ribs: PerNS<Vec<Rib<'a>>>,
 
-    // The current set of local scopes, for labels.
+    /// The current set of local scopes, for labels.
     label_ribs: Vec<Rib<'a>>,
 
-    // The trait that the current context can refer to.
+    /// The trait that the current context can refer to.
     current_trait_ref: Option<(Module<'a>, TraitRef)>,
 
-    // The current self type if inside an impl (used for better errors).
+    /// The current self type if inside an impl (used for better errors).
     current_self_type: Option<Ty>,
 
-    // The idents for the primitive types.
+    /// The idents for the primitive types.
     primitive_type_table: PrimitiveTypeTable,
 
     def_map: DefMap,
@@ -1446,20 +1446,20 @@ pub struct Resolver<'a> {
     pub export_map: ExportMap,
     pub trait_map: TraitMap,
 
-    // A map from nodes to anonymous modules.
-    // Anonymous modules are pseudo-modules that are implicitly created around items
-    // contained within blocks.
-    //
-    // For example, if we have this:
-    //
-    //  fn f() {
-    //      fn g() {
-    //          ...
-    //      }
-    //  }
-    //
-    // There will be an anonymous module created around `g` with the ID of the
-    // entry block for `f`.
+    /// A map from nodes to anonymous modules.
+    /// Anonymous modules are pseudo-modules that are implicitly created around items
+    /// contained within blocks.
+    ///
+    /// For example, if we have this:
+    ///
+    ///  fn f() {
+    ///      fn g() {
+    ///          ...
+    ///      }
+    ///  }
+    ///
+    /// There will be an anonymous module created around `g` with the ID of the
+    /// entry block for `f`.
     block_map: NodeMap<Module<'a>>,
     module_map: FxHashMap<DefId, Module<'a>>,
     extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
@@ -1487,7 +1487,8 @@ pub struct Resolver<'a> {
 
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
-    use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
+    /// true if `#![feature(use_extern_macros)]`
+    use_extern_macros: bool,
 
     crate_loader: &'a mut CrateLoader,
     macro_names: FxHashSet<Ident>,
@@ -1501,29 +1502,29 @@ pub struct Resolver<'a> {
     pub whitelisted_legacy_custom_derives: Vec<Name>,
     pub found_unresolved_macro: bool,
 
-    // List of crate local macros that we need to warn about as being unused.
-    // Right now this only includes macro_rules! macros, and macros 2.0.
+    /// List of crate local macros that we need to warn about as being unused.
+    /// Right now this only includes macro_rules! macros, and macros 2.0.
     unused_macros: FxHashSet<DefId>,
 
-    // Maps the `Mark` of an expansion to its containing module or block.
+    /// Maps the `Mark` of an expansion to its containing module or block.
     invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
 
-    // Avoid duplicated errors for "name already defined".
+    /// Avoid duplicated errors for "name already defined".
     name_already_seen: FxHashMap<Name, Span>,
 
-    // If `#![feature(proc_macro)]` is set
+    /// If `#![feature(proc_macro)]` is set
     proc_macro_enabled: bool,
 
-    // A set of procedural macros imported by `#[macro_use]` that have already been warned about
+    /// 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,
-    // it's not used during normal resolution, only for better error reporting.
+    /// This table maps struct IDs into struct constructor IDs,
+    /// it's not used during normal resolution, only for better error reporting.
     struct_constructors: DefIdMap<(Def, ty::Visibility)>,
 
-    // Only used for better errors on `fn(): fn()`
+    /// Only used for better errors on `fn(): fn()`
     current_type_ascription: Vec<Span>,
 
     injected_crate: Option<Module<'a>>,
index 0388465b485cb5527727dc50045c16db5ed16351..3a859c02c16c433629c8c6acfac5eeff40effa1e 100644 (file)
@@ -397,6 +397,18 @@ fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: b
 
     fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                             -> Result<Def, Determinacy> {
+        if path.segments.len() > 1 {
+            if !self.session.features_untracked().proc_macro_path_invoc {
+                emit_feature_err(
+                    &self.session.parse_sess,
+                    "proc_macro_path_invoc",
+                    path.span,
+                    GateIssue::Language,
+                    "paths of length greater than one in macro invocations are \
+                     currently unstable",
+                );
+            }
+        }
         let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
         if def != Err(Determinacy::Undetermined) {
             // Do not report duplicated errors on every undetermined resolution.
index df6793e8a604c2e0ba43cf42d21d4e388aacaae5..36e60cee788dc6ea2f04ad9e947b09d84843804e 100644 (file)
@@ -108,6 +108,7 @@ fn into_from_env_goal(self) -> DomainGoal<'tcx> {
             FromEnv(..) |
             WellFormedTy(..) |
             FromEnvTy(..) |
+            Normalize(..) |
             RegionOutlives(..) |
             TypeOutlives(..) => self,
         }
@@ -118,10 +119,20 @@ fn into_from_env_goal(self) -> DomainGoal<'tcx> {
                                        -> Lrc<&'tcx Slice<Clause<'tcx>>>
 {
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-    let item = tcx.hir.expect_item(node_id);
-    match item.node {
-        hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
-        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
+    let node = tcx.hir.find(node_id).unwrap();
+    match node {
+        hir::map::Node::NodeItem(item) => match item.node {
+            hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
+            hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
+            _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
+        }
+        hir::map::Node::NodeImplItem(item) => {
+            if let hir::ImplItemKind::Type(..) = item.node {
+                program_clauses_for_associated_type_value(tcx, def_id)
+            } else {
+                Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()))
+            }
+        },
 
         // FIXME: other constructions e.g. traits, associated types...
         _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
@@ -233,6 +244,58 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
     Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))))
 }
 
+pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    item_id: DefId,
+) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
+    // Rule Normalize-From-Impl (see rustc guide)
+    //
+    // ```impl<P0..Pn> Trait<A1..An> for A0
+    // {
+    //     type AssocType<Pn+1..Pm> where WC = T;
+    // }```
+    //
+    // ```
+    // forall<P0..Pm> {
+    //   forall<Pn+1..Pm> {
+    //     Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T) :-
+    //       Implemented(A0: Trait<A1..An>) && WC
+    //   }
+    // }
+    // ```
+
+    let item = tcx.associated_item(item_id);
+    debug_assert_eq!(item.kind, ty::AssociatedKind::Type);
+    let impl_id = if let ty::AssociatedItemContainer::ImplContainer(impl_id) = item.container {
+        impl_id
+    } else {
+        bug!()
+    };
+    // `A0 as Trait<A1..An>`
+    let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
+    // `T`
+    let ty = tcx.type_of(item_id);
+    // `Implemented(A0: Trait<A1..An>)`
+    let trait_implemented = ty::Binder::dummy(ty::TraitPredicate { trait_ref }.lower());
+    // `WC`
+    let item_where_clauses = tcx.predicates_of(item_id).predicates.lower();
+    // `Implemented(A0: Trait<A1..An>) && WC`
+    let mut where_clauses = vec![trait_implemented];
+    where_clauses.extend(item_where_clauses);
+    // `<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm>`
+    let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.name);
+    // `Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T)`
+    let normalize_goal = DomainGoal::Normalize(ty::ProjectionPredicate { projection_ty, ty });
+    // `Normalize(... -> T) :- ...`
+    let clause = ProgramClause {
+        goal: normalize_goal,
+        hypotheses: tcx.mk_goals(
+            where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx))
+        ),
+    };
+    Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))))
+}
+
 pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     if !tcx.features().rustc_attrs {
         return;
index f2dd2ed8460ebbfa65d1776cae8d703d1a5c8d1b..ffebb959ebfde494abdd58d680e008da35f76f18 100644 (file)
@@ -43,13 +43,11 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
                 AllocatorTy::Ptr => args.push(i8p),
                 AllocatorTy::Usize => args.push(usize),
 
-                AllocatorTy::Bang |
                 AllocatorTy::ResultPtr |
                 AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
         }
         let output = match method.output {
-            AllocatorTy::Bang => None,
             AllocatorTy::ResultPtr => Some(i8p),
             AllocatorTy::Unit => None,
 
index c968b8525a5b1c90784cffbb335192e20a0ff611..eb5c7396ae055606df48efe378bafe04fc417ba7 100644 (file)
@@ -174,12 +174,12 @@ pub fn provide(providers: &mut Providers) {
             // rustdoc needs to be able to document functions that use all the features, so
             // whitelist them all
             Lrc::new(llvm_util::all_known_features()
-                .map(|c| c.to_string())
+                .map(|(a, b)| (a.to_string(), b.map(|s| s.to_string())))
                 .collect())
         } else {
             Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
                 .iter()
-                .map(|c| c.to_string())
+                .map(|&(a, b)| (a.to_string(), b.map(|s| s.to_string())))
                 .collect())
         }
     };
index ebcf06d63be26c74e8baf9cba6c6f46a2883bcd0..e001e809ee5f0a8d2cceb611ecc64f6664ca440b 100644 (file)
@@ -960,6 +960,7 @@ fn no_position_independent_executable(&mut self) {
 
     fn finalize(&mut self) -> Command {
         self.cmd.arg("--threads");
+        self.cmd.arg("-z").arg("stack-size=1048576");
 
         // FIXME we probably shouldn't pass this but instead pass an explicit
         // whitelist of symbols we'll allow to be undefined. Unfortunately
index 1da6f25fd639a0506daac80ef52e1e0d04359e30..a4e1b7f2925dca3f802ff23bc9ada907f3a4f8e6 100644 (file)
@@ -492,7 +492,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc
     // You can also find more info on why Windows is whitelisted here in:
     //      https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
     if !cx.sess().no_landing_pads() ||
-       cx.sess().target.target.options.is_like_windows {
+       cx.sess().target.target.options.requires_uwtable {
         attributes::emit_uwtable(lldecl, true);
     }
 
index f3d95cf794babc101891650882d441cafbea29b5..eb550d7a605c5c0b774819868e092f8ef76fbd2f 100644 (file)
@@ -23,6 +23,7 @@
 use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
                       DICompositeType, DILexicalBlock, DIFlags};
 
+use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use rustc::ty::fold::TypeVisitor;
@@ -41,7 +42,7 @@
 use std::fmt::Write;
 use std::ptr;
 use std::path::{Path, PathBuf};
-use syntax::{ast, attr};
+use syntax::ast;
 use syntax::symbol::{Interner, InternedString, Symbol};
 use syntax_pos::{self, Span, FileName};
 
@@ -1644,11 +1645,17 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
     }
 
     let tcx = cx.tcx;
-    let no_mangle = attr::contains_name(&tcx.get_attrs(def_id), "no_mangle");
+    let attrs = tcx.trans_fn_attrs(def_id);
+
+    if attrs.flags.contains(TransFnAttrFlags::NO_DEBUG) {
+        return;
+    }
+
+    let no_mangle = attrs.flags.contains(TransFnAttrFlags::NO_MANGLE);
     // We may want to remove the namespace scope if we're in an extern block, see:
     // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
     let var_scope = get_namespace_for_item(cx, def_id);
-    let span = cx.tcx.def_span(def_id);
+    let span = tcx.def_span(def_id);
 
     let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP {
         let loc = span_start(cx, span);
index 28311018ee7d7d3e3ecbed32d7042d5239c12fda..706dc3dca8a6143c2b10dc6faeb26d4dcd031f35 100644 (file)
@@ -23,6 +23,7 @@
 use llvm;
 use llvm::{ModuleRef, ContextRef, ValueRef};
 use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
+use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def_id::{DefId, CrateNum};
 use rustc::ty::subst::Substs;
 
@@ -30,7 +31,7 @@
 use common::CodegenCx;
 use builder::Builder;
 use monomorphize::Instance;
-use rustc::ty::{self, ParamEnv, Ty};
+use rustc::ty::{self, ParamEnv, Ty, InstanceDef};
 use rustc::mir;
 use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
@@ -210,13 +211,12 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return FunctionDebugContext::DebugInfoDisabled;
     }
 
-    for attr in instance.def.attrs(cx.tcx).iter() {
-        if attr.check_name("no_debug") {
+    if let InstanceDef::Item(def_id) = instance.def {
+        if cx.tcx.trans_fn_attrs(def_id).flags.contains(TransFnAttrFlags::NO_DEBUG) {
             return FunctionDebugContext::FunctionWithoutDebugInfo;
         }
     }
 
-    let containing_scope = get_containing_scope(cx, instance);
     let span = mir.span;
 
     // This can be the case for functions inlined from another crate
@@ -226,6 +226,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     }
 
     let def_id = instance.def_id();
+    let containing_scope = get_containing_scope(cx, instance);
     let loc = span_start(cx, span);
     let file_metadata = file_metadata(cx, &loc.file.name, def_id.krate);
 
index a38d51e754670dd96d8d4cb55cac1fe572d0b493..49d0f638f206137c2685d65c15d110f67383588c 100644 (file)
@@ -29,7 +29,6 @@
 #![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
 #![feature(inclusive_range_fields)]
-#![feature(underscore_lifetimes)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
index fa3ecb1cc1199810fe3093a488ba908c3b4b34d5..bbd1c39a19e0eb95d534cd4cda6e0cebc9d0f7ec 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::session::config::PrintRequest;
 use libc::c_int;
 use std::ffi::CString;
+use syntax::feature_gate::UnstableFeatures;
 
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Once;
@@ -82,40 +83,95 @@ unsafe fn configure_llvm(sess: &Session) {
 // to LLVM or the feature detection code will walk past the end of the feature
 // array, leading to crashes.
 
-const ARM_WHITELIST: &'static [&'static str] = &["neon", "v7", "vfp2", "vfp3", "vfp4"];
-
-const AARCH64_WHITELIST: &'static [&'static str] = &["fp", "neon", "sve", "crc", "crypto",
-                                                     "ras", "lse", "rdm", "fp16", "rcpc",
-                                                     "dotprod", "v8.1a", "v8.2a", "v8.3a"];
-
-const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw",
-                                                 "avx512cd", "avx512dq", "avx512er",
-                                                 "avx512f", "avx512ifma", "avx512pf",
-                                                 "avx512vbmi", "avx512vl", "avx512vpopcntdq",
-                                                 "bmi1", "bmi2", "fma", "fxsr",
-                                                 "lzcnt", "mmx", "pclmulqdq",
-                                                 "popcnt", "rdrand", "rdseed",
-                                                 "sha",
-                                                 "sse", "sse2", "sse3", "sse4.1",
-                                                 "sse4.2", "sse4a", "ssse3",
-                                                 "tbm", "xsave", "xsavec",
-                                                 "xsaveopt", "xsaves"];
-
-const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx", "hvx-double"];
-
-const POWERPC_WHITELIST: &'static [&'static str] = &["altivec",
-                                                     "power8-altivec", "power9-altivec",
-                                                     "power8-vector", "power9-vector",
-                                                     "vsx"];
-
-const MIPS_WHITELIST: &'static [&'static str] = &["fp64", "msa"];
+const ARM_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("neon", Some("arm_target_feature")),
+    ("v7", Some("arm_target_feature")),
+    ("vfp2", Some("arm_target_feature")),
+    ("vfp3", Some("arm_target_feature")),
+    ("vfp4", Some("arm_target_feature")),
+];
+
+const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("fp", Some("aarch64_target_feature")),
+    ("neon", Some("aarch64_target_feature")),
+    ("sve", Some("aarch64_target_feature")),
+    ("crc", Some("aarch64_target_feature")),
+    ("crypto", Some("aarch64_target_feature")),
+    ("ras", Some("aarch64_target_feature")),
+    ("lse", Some("aarch64_target_feature")),
+    ("rdm", Some("aarch64_target_feature")),
+    ("fp16", Some("aarch64_target_feature")),
+    ("rcpc", Some("aarch64_target_feature")),
+    ("dotprod", Some("aarch64_target_feature")),
+    ("v8.1a", Some("aarch64_target_feature")),
+    ("v8.2a", Some("aarch64_target_feature")),
+    ("v8.3a", Some("aarch64_target_feature")),
+];
+
+const X86_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("aes", None),
+    ("avx", None),
+    ("avx2", None),
+    ("avx512bw", Some("avx512_target_feature")),
+    ("avx512cd", Some("avx512_target_feature")),
+    ("avx512dq", Some("avx512_target_feature")),
+    ("avx512er", Some("avx512_target_feature")),
+    ("avx512f", Some("avx512_target_feature")),
+    ("avx512ifma", Some("avx512_target_feature")),
+    ("avx512pf", Some("avx512_target_feature")),
+    ("avx512vbmi", Some("avx512_target_feature")),
+    ("avx512vl", Some("avx512_target_feature")),
+    ("avx512vpopcntdq", Some("avx512_target_feature")),
+    ("bmi1", None),
+    ("bmi2", None),
+    ("fma", None),
+    ("fxsr", None),
+    ("lzcnt", None),
+    ("mmx", Some("mmx_target_feature")),
+    ("pclmulqdq", None),
+    ("popcnt", None),
+    ("rdrand", None),
+    ("rdseed", None),
+    ("sha", None),
+    ("sse", None),
+    ("sse2", None),
+    ("sse3", None),
+    ("sse4.1", None),
+    ("sse4.2", None),
+    ("sse4a", Some("sse4a_target_feature")),
+    ("ssse3", None),
+    ("tbm", Some("tbm_target_feature")),
+    ("xsave", None),
+    ("xsavec", None),
+    ("xsaveopt", None),
+    ("xsaves", None),
+];
+
+const HEXAGON_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("hvx", Some("hexagon_target_feature")),
+    ("hvx-double", Some("hexagon_target_feature")),
+];
+
+const POWERPC_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("altivec", Some("powerpc_target_feature")),
+    ("power8-altivec", Some("powerpc_target_feature")),
+    ("power9-altivec", Some("powerpc_target_feature")),
+    ("power8-vector", Some("powerpc_target_feature")),
+    ("power9-vector", Some("powerpc_target_feature")),
+    ("vsx", Some("powerpc_target_feature")),
+];
+
+const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("fp64", Some("mips_target_feature")),
+    ("msa", Some("mips_target_feature")),
+];
 
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primtives may be documented.
 ///
 /// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
 /// iterator!
-pub fn all_known_features() -> impl Iterator<Item=&'static str> {
+pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<&'static str>)> {
     ARM_WHITELIST.iter().cloned()
         .chain(AARCH64_WHITELIST.iter().cloned())
         .chain(X86_WHITELIST.iter().cloned())
@@ -144,6 +200,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
     let target_machine = create_target_machine(sess, true);
     target_feature_whitelist(sess)
         .iter()
+        .filter_map(|&(feature, gate)| {
+            if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
+                Some(feature)
+            } else {
+                None
+            }
+        })
         .filter(|feature| {
             let llvm_feature = to_llvm_feature(sess, feature);
             let cstr = CString::new(llvm_feature).unwrap();
@@ -152,7 +215,9 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
         .map(|feature| Symbol::intern(feature)).collect()
 }
 
-pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {
+pub fn target_feature_whitelist(sess: &Session)
+    -> &'static [(&'static str, Option<&'static str>)]
+{
     match &*sess.target.target.arch {
         "arm" => ARM_WHITELIST,
         "aarch64" => AARCH64_WHITELIST,
index dd34dc0345886aa1f08f13cb46a60cf4e6c527d7..0fe7163da7a02d2457b1b37d1f3cb3feb433def2 100644 (file)
@@ -12,6 +12,7 @@
 //! which do not.
 
 use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::control_flow_graph::dominators::Dominators;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::mir::{self, Location, TerminatorKind};
 use rustc::mir::visit::{Visitor, PlaceContext};
@@ -21,7 +22,7 @@
 use type_of::LayoutLlvmExt;
 use super::FunctionCx;
 
-pub fn memory_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
+pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
@@ -43,43 +44,60 @@ pub fn memory_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
             // (e.g. structs) into an alloca unconditionally, just so
             // that we don't have to deal with having two pathways
             // (gep vs extractvalue etc).
-            analyzer.mark_as_memory(mir::Local::new(index));
+            analyzer.not_ssa(mir::Local::new(index));
         }
     }
 
-    analyzer.memory_locals
+    analyzer.non_ssa_locals
 }
 
 struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
     fx: &'mir FunctionCx<'a, 'tcx>,
-    memory_locals: BitVector,
-    seen_assigned: BitVector
+    dominators: Dominators<mir::BasicBlock>,
+    non_ssa_locals: BitVector,
+    // 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>
 }
 
 impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
     fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
+        let invalid_location =
+            mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
         let mut analyzer = LocalAnalyzer {
             fx,
-            memory_locals: BitVector::new(fx.mir.local_decls.len()),
-            seen_assigned: BitVector::new(fx.mir.local_decls.len())
+            dominators: fx.mir.dominators(),
+            non_ssa_locals: BitVector::new(fx.mir.local_decls.len()),
+            first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
         };
 
         // Arguments get assigned to by means of the function being called
-        for idx in 0..fx.mir.arg_count {
-            analyzer.seen_assigned.insert(idx + 1);
+        for arg in fx.mir.args_iter() {
+            analyzer.first_assignment[arg] = mir::START_BLOCK.start_location();
         }
 
         analyzer
     }
 
-    fn mark_as_memory(&mut self, local: mir::Local) {
-        debug!("marking {:?} as memory", local);
-        self.memory_locals.insert(local.index());
+    fn first_assignment(&self, local: mir::Local) -> Option<Location> {
+        let location = self.first_assignment[local];
+        if location.block.index() < self.fx.mir.basic_blocks().len() {
+            Some(location)
+        } else {
+            None
+        }
     }
 
-    fn mark_assigned(&mut self, local: mir::Local) {
-        if !self.seen_assigned.insert(local.index()) {
-            self.mark_as_memory(local);
+    fn not_ssa(&mut self, local: mir::Local) {
+        debug!("marking {:?} as non-SSA", local);
+        self.non_ssa_locals.insert(local.index());
+    }
+
+    fn assign(&mut self, local: mir::Local, location: Location) {
+        if self.first_assignment(local).is_some() {
+            self.not_ssa(local);
+        } else {
+            self.first_assignment[local] = location;
         }
     }
 }
@@ -93,9 +111,9 @@ fn visit_assign(&mut self,
         debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
 
         if let mir::Place::Local(index) = *place {
-            self.mark_assigned(index);
+            self.assign(index, location);
             if !self.fx.rvalue_creates_operand(rvalue) {
-                self.mark_as_memory(index);
+                self.not_ssa(index);
             }
         } else {
             self.visit_place(place, PlaceContext::Store, location);
@@ -161,7 +179,7 @@ fn visit_place(&mut self,
                     if layout.is_llvm_immediate() || layout.is_llvm_scalar_pair() {
                         // Recurse with the same context, instead of `Projection`,
                         // potentially stopping at non-operand projections,
-                        // which would trigger `mark_as_memory` on locals.
+                        // which would trigger `not_ssa` on locals.
                         self.visit_place(&proj.base, context, location);
                         return;
                     }
@@ -178,35 +196,50 @@ fn visit_place(&mut self,
     }
 
     fn visit_local(&mut self,
-                   &index: &mir::Local,
+                   &local: &mir::Local,
                    context: PlaceContext<'tcx>,
-                   _: Location) {
+                   location: Location) {
         match context {
             PlaceContext::Call => {
-                self.mark_assigned(index);
+                self.assign(local, location);
             }
 
             PlaceContext::StorageLive |
             PlaceContext::StorageDead |
-            PlaceContext::Validate |
+            PlaceContext::Validate => {}
+
             PlaceContext::Copy |
-            PlaceContext::Move => {}
+            PlaceContext::Move => {
+                // Reads from uninitialized variables (e.g. in dead code, after
+                // optimizations) require locals to be in (uninitialized) memory.
+                // NB: there can be uninitialized reads of a local visited after
+                // an assignment to that local, if they happen on disjoint paths.
+                let ssa_read = match self.first_assignment(local) {
+                    Some(assignment_location) => {
+                        assignment_location.dominates(location, &self.dominators)
+                    }
+                    None => false
+                };
+                if !ssa_read {
+                    self.not_ssa(local);
+                }
+            }
 
             PlaceContext::Inspect |
             PlaceContext::Store |
             PlaceContext::AsmOutput |
             PlaceContext::Borrow { .. } |
             PlaceContext::Projection(..) => {
-                self.mark_as_memory(index);
+                self.not_ssa(local);
             }
 
             PlaceContext::Drop => {
-                let ty = mir::Place::Local(index).ty(self.fx.mir, self.fx.cx.tcx);
+                let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx);
                 let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx));
 
                 // Only need the place if we're actually dropping it.
                 if self.fx.cx.type_needs_drop(ty) {
-                    self.mark_as_memory(index);
+                    self.not_ssa(local);
                 }
             }
         }
index 11dabbeae7430145be4d82e249cf30f880ccd243..c55836919a97fa0a010e84cdd85c53397fdc56a9 100644 (file)
@@ -252,7 +252,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
         },
     };
 
-    let memory_locals = analyze::memory_locals(&fx);
+    let memory_locals = analyze::non_ssa_locals(&fx);
 
     // Allocate variable and temp allocas
     fx.locals = {
index 75df349de41ee9d7075a90c36f407bd3e9157854..656ab95a28cf3e1730c78092260dc9ec40e9fb90 100644 (file)
@@ -399,7 +399,14 @@ pub fn trans_operand(&mut self,
                 self.mir_constant_to_miri_value(bx, constant)
                     .and_then(|c| OperandRef::from_const(bx, c, ty))
                     .unwrap_or_else(|err| {
-                        err.report(bx.tcx(), constant.span, "const operand");
+                        match constant.literal {
+                            mir::Literal::Promoted { .. } => {
+                                // don't report errors inside promoteds, just warnings.
+                            },
+                            mir::Literal::Value { .. } => {
+                                err.report(bx.tcx(), constant.span, "const operand")
+                            },
+                        }
                         // We've errored, so we don't have to produce working code.
                         let layout = bx.cx.layout_of(ty);
                         PlaceRef::new_sized(
index 5cf9819288b5ef7628c1a8b670c05f979aa37b10..b7895631c6092dc75cfa2d9ce18cd9c4d0342e42 100644 (file)
@@ -44,7 +44,7 @@
 use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
 use rustc_back::target::Target;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_mir::monomorphize::collector;
 use link::{build_link_meta, out_filename};
 
@@ -203,7 +203,7 @@ fn provide(&self, providers: &mut Providers) {
         ::symbol_names::provide(providers);
 
         providers.target_features_whitelist = |_tcx, _cnum| {
-            Lrc::new(FxHashSet()) // Just a dummy
+            Lrc::new(FxHashMap()) // Just a dummy
         };
     }
     fn provide_extern(&self, _providers: &mut Providers) {}
index ecfe1416050290b3277aa6fbf3da5b97de944fca..c0d6993c7d4dde1c133d3e11257dc3f5ce7951ae 100644 (file)
@@ -502,10 +502,6 @@ fn check_for_cast(&self,
                                             &format!("{}, producing the closest possible value",
                                                      msg),
                                             cast_suggestion);
-                        err.warn("casting here will cause undefined behavior if the value is \
-                                  finite but larger or smaller than the largest or smallest \
-                                  finite value representable by `f32` (this is a bug and will be \
-                                  fixed)");
                     }
                     true
                 }
index de5709566225c54cc595f7340155edbc9264fdf7..073f36b9f3c505b2000ad42f152211d33d602ce9 100644 (file)
@@ -471,6 +471,9 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::TyStr => {
                 let lang_def_id = lang_items.str_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.str_alloc_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TySlice(_) => {
                 let lang_def_id = lang_items.slice_impl();
@@ -478,6 +481,12 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
 
                 let lang_def_id = lang_items.slice_u8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.slice_alloc_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.slice_u8_alloc_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 let lang_def_id = lang_items.const_ptr_impl();
@@ -538,10 +547,16 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::TyFloat(ast::FloatTy::F32) => {
                 let lang_def_id = lang_items.f32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.f32_runtime_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyFloat(ast::FloatTy::F64) => {
                 let lang_def_id = lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.f64_runtime_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             _ => {}
         }
index ca35153d571dbd0048cf8ada21af03d6d5832a04..acde10a6396936b445b83aae2f97e72f40519c1c 100644 (file)
@@ -2217,7 +2217,8 @@ fn resolve_generator_interiors(&self, def_id: DefId) {
     }
 
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
-    // Non-numerics get replaced with !, unconstrained ints with i32,
+    // Non-numerics get replaced with ! or () (depending on whether
+    // feature(never_type) is enabled, unconstrained ints with i32,
     // unconstrained floats with f64.
     // Fallback becomes very dubious if we have encountered type-checking errors.
     // In that case, fallback to TyError.
@@ -2231,7 +2232,7 @@ fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
             _ if self.is_tainted_by_errors() => self.tcx().types.err,
             UnconstrainedInt => self.tcx.types.i32,
             UnconstrainedFloat => self.tcx.types.f64,
-            Neither if self.type_var_diverges(ty) => self.tcx.types.never,
+            Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(),
             Neither => return false,
         };
         debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback);
index d43ab0d3713cb93c9dc11b155818ae290cd7402e..532f1da4f301b4201ed6aa7b9b010baa59144631 100644 (file)
@@ -114,6 +114,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyChar => {
                 self.check_primitive_impl(def_id,
                                           lang_items.char_impl(),
+                                          None,
                                           "char",
                                           "char",
                                           item.span);
@@ -121,6 +122,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyStr => {
                 self.check_primitive_impl(def_id,
                                           lang_items.str_impl(),
+                                          lang_items.str_alloc_impl(),
                                           "str",
                                           "str",
                                           item.span);
@@ -128,6 +130,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_u8_impl(),
+                                          lang_items.slice_u8_alloc_impl(),
                                           "slice_u8",
                                           "[u8]",
                                           item.span);
@@ -135,6 +138,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TySlice(_) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_impl(),
+                                          lang_items.slice_alloc_impl(),
                                           "slice",
                                           "[T]",
                                           item.span);
@@ -142,6 +146,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.const_ptr_impl(),
+                                          None,
                                           "const_ptr",
                                           "*const T",
                                           item.span);
@@ -149,6 +154,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.mut_ptr_impl(),
+                                          None,
                                           "mut_ptr",
                                           "*mut T",
                                           item.span);
@@ -156,6 +162,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I8) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i8_impl(),
+                                          None,
                                           "i8",
                                           "i8",
                                           item.span);
@@ -163,6 +170,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I16) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i16_impl(),
+                                          None,
                                           "i16",
                                           "i16",
                                           item.span);
@@ -170,6 +178,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i32_impl(),
+                                          None,
                                           "i32",
                                           "i32",
                                           item.span);
@@ -177,6 +186,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i64_impl(),
+                                          None,
                                           "i64",
                                           "i64",
                                           item.span);
@@ -184,6 +194,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I128) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i128_impl(),
+                                          None,
                                           "i128",
                                           "i128",
                                           item.span);
@@ -191,6 +202,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::Isize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.isize_impl(),
+                                          None,
                                           "isize",
                                           "isize",
                                           item.span);
@@ -198,6 +210,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U8) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u8_impl(),
+                                          None,
                                           "u8",
                                           "u8",
                                           item.span);
@@ -205,6 +218,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U16) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u16_impl(),
+                                          None,
                                           "u16",
                                           "u16",
                                           item.span);
@@ -212,6 +226,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u32_impl(),
+                                          None,
                                           "u32",
                                           "u32",
                                           item.span);
@@ -219,6 +234,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u64_impl(),
+                                          None,
                                           "u64",
                                           "u64",
                                           item.span);
@@ -226,6 +242,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U128) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u128_impl(),
+                                          None,
                                           "u128",
                                           "u128",
                                           item.span);
@@ -233,6 +250,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::Usize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.usize_impl(),
+                                          None,
                                           "usize",
                                           "usize",
                                           item.span);
@@ -240,6 +258,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyFloat(ast::FloatTy::F32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.f32_impl(),
+                                          lang_items.f32_runtime_impl(),
                                           "f32",
                                           "f32",
                                           item.span);
@@ -247,6 +266,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyFloat(ast::FloatTy::F64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.f64_impl(),
+                                          lang_items.f64_runtime_impl(),
                                           "f64",
                                           "f64",
                                           item.span);
@@ -305,11 +325,15 @@ fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
     fn check_primitive_impl(&self,
                             impl_def_id: DefId,
                             lang_def_id: Option<DefId>,
+                            lang_def_id2: Option<DefId>,
                             lang: &str,
                             ty: &str,
                             span: Span) {
-        match lang_def_id {
-            Some(lang_def_id) if lang_def_id == impl_def_id => {
+        match (lang_def_id, lang_def_id2) {
+            (Some(lang_def_id), _) if lang_def_id == impl_def_id => {
+                // OK
+            }
+            (_, Some(lang_def_id)) if lang_def_id == impl_def_id => {
                 // OK
             }
             _ => {
index f386e1d8b825d4d355336e23bfdd6560bc64566e..6bd38244e8caf9956f02233c0b518552e2a69fad 100644 (file)
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::util::Discr;
 use rustc::util::captures::Captures;
-use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::util::nodemap::FxHashMap;
 
 use syntax::{abi, ast};
 use syntax::ast::MetaItemKind;
 use syntax::attr::{InlineAttr, list_contains_name, mark_used};
 use syntax::codemap::Spanned;
 use syntax::symbol::{Symbol, keywords};
+use syntax::feature_gate;
 use syntax_pos::{Span, DUMMY_SP};
 
 use rustc::hir::{self, map as hir_map, TransFnAttrs, TransFnAttrFlags, Unsafety};
@@ -1682,7 +1683,7 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn from_target_feature(
     tcx: TyCtxt,
     attr: &ast::Attribute,
-    whitelist: &FxHashSet<String>,
+    whitelist: &FxHashMap<String, Option<String>>,
     target_features: &mut Vec<Symbol>,
 ) {
     let list = match attr.meta_item_list() {
@@ -1694,16 +1695,19 @@ fn from_target_feature(
             return
         }
     };
-
+    let rust_features = tcx.features();
     for item in list {
+        // Only `enable = ...` is accepted in the meta item list
         if !item.check_name("enable") {
             let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
                        currently";
             tcx.sess.span_err(item.span, &msg);
             continue
         }
+
+        // Must be of the form `enable = "..."` ( a string)
         let value = match item.value_str() {
-            Some(list) => list,
+            Some(value) => value,
             None => {
                 let msg = "#[target_feature] attribute must be of the form \
                            #[target_feature(enable = \"..\")]";
@@ -1711,24 +1715,55 @@ fn from_target_feature(
                 continue
             }
         };
-        let value = value.as_str();
-        for feature in value.split(',') {
-            if whitelist.contains(feature) {
-                target_features.push(Symbol::intern(feature));
-                continue
-            }
-
-            let msg = format!("the feature named `{}` is not valid for \
-                               this target", feature);
-            let mut err = tcx.sess.struct_span_err(item.span, &msg);
 
-            if feature.starts_with("+") {
-                let valid = whitelist.contains(&feature[1..]);
-                if valid {
-                    err.help("consider removing the leading `+` in the feature name");
+        // We allow comma separation to enable multiple features
+        for feature in value.as_str().split(',') {
+
+            // Only allow whitelisted features per platform
+            let feature_gate = match whitelist.get(feature) {
+                Some(g) => g,
+                None => {
+                    let msg = format!("the feature named `{}` is not valid for \
+                                       this target", feature);
+                    let mut err = tcx.sess.struct_span_err(item.span, &msg);
+
+                    if feature.starts_with("+") {
+                        let valid = whitelist.contains_key(&feature[1..]);
+                        if valid {
+                            err.help("consider removing the leading `+` in the feature name");
+                        }
+                    }
+                    err.emit();
+                    continue
                 }
+            };
+
+            // Only allow features whose feature gates have been enabled
+            let allowed = match feature_gate.as_ref().map(|s| &**s) {
+                Some("arm_target_feature") => rust_features.arm_target_feature,
+                Some("aarch64_target_feature") => rust_features.aarch64_target_feature,
+                Some("hexagon_target_feature") => rust_features.hexagon_target_feature,
+                Some("powerpc_target_feature") => rust_features.powerpc_target_feature,
+                Some("mips_target_feature") => rust_features.mips_target_feature,
+                Some("avx512_target_feature") => rust_features.avx512_target_feature,
+                Some("mmx_target_feature") => rust_features.mmx_target_feature,
+                Some("sse4a_target_feature") => rust_features.sse4a_target_feature,
+                Some("tbm_target_feature") => rust_features.tbm_target_feature,
+                Some(name) => bug!("unknown target feature gate {}", name),
+                None => true,
+            };
+            if !allowed {
+                feature_gate::emit_feature_err(
+                    &tcx.sess.parse_sess,
+                    feature_gate.as_ref().unwrap(),
+                    item.span,
+                    feature_gate::GateIssue::Language,
+                    &format!("the target feature `{}` is currently unstable",
+                             feature),
+                );
+                continue
             }
-            err.emit();
+            target_features.push(Symbol::intern(feature));
         }
     }
 }
@@ -1790,6 +1825,8 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
             trans_fn_attrs.flags |= TransFnAttrFlags::NO_MANGLE;
         } else if attr.check_name("rustc_std_internal_symbol") {
             trans_fn_attrs.flags |= TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+        } else if attr.check_name("no_debug") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::NO_DEBUG;
         } else if attr.check_name("inline") {
             trans_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
                 if attr.path != "inline" {
@@ -1835,20 +1872,6 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
                     .emit();
             }
         } else if attr.check_name("target_feature") {
-            // handle deprecated #[target_feature = "..."]
-            if let Some(val) = attr.value_str() {
-                for feat in val.as_str().split(",").map(|f| f.trim()) {
-                    if !feat.is_empty() && !feat.contains('\0') {
-                        trans_fn_attrs.target_features.push(Symbol::intern(feat));
-                    }
-                }
-                let msg = "#[target_feature = \"..\"] is deprecated and will \
-                           eventually be removed, use \
-                           #[target_feature(enable = \"..\")] instead";
-                tcx.sess.span_warn(attr.span, &msg);
-                continue
-            }
-
             if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
                 let msg = "#[target_feature(..)] can only be applied to \
                            `unsafe` function";
index ae3b2b22ea114c198218bc5c54d46e1907fe9aa7..e3f7ff5cb3f74406c4bf809adf29e31716e63e28 100644 (file)
@@ -4526,23 +4526,23 @@ fn foo<U: Iterator>(&self, _: &U) { } // error method `foo` has incompatible
 The error happens on numeric literals:
 
 ```compile_fail,E0689
-2.0.powi(2);
+2.0.recip();
 ```
 
 and on numeric bindings without an identified concrete type:
 
 ```compile_fail,E0689
 let x = 2.0;
-x.powi(2);  // same error as above
+x.recip();  // same error as above
 ```
 
 Because of this, you must give the numeric literal or binding a type:
 
 ```
-let _ = 2.0_f32.powi(2);
+let _ = 2.0_f32.recip();
 let x: f32 = 2.0;
-let _ = x.powi(2);
-let _ = (2.0 as f32).powi(2);
+let _ = x.recip();
+let _ = (2.0 as f32).recip();
 ```
 "##,
 
index a4477e80b988a51003948e8cbdc26e796ab12623..ed0cfe38a7ad95c7d4218d271f45e1ebdeb62f45 100644 (file)
@@ -82,7 +82,7 @@
 #![feature(slice_patterns)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(dyn_trait)]
-#![feature(underscore_lifetimes)]
+#![feature(never_type)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
index 090adc27ef01083d609abe5cd99954b7ea573c53..23e0c2625eeeb6b0607d2d7fa8d63cdc1211e251 100644 (file)
 
 //! Support for inlining external documentation into the current AST.
 
-use std::collections::BTreeMap;
-use std::io;
 use std::iter::once;
-use rustc_data_structures::sync::Lrc;
 
 use syntax::ast;
 use rustc::hir;
@@ -289,10 +286,15 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
         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(),
     ];
@@ -408,27 +410,8 @@ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
     }
 }
 
-struct InlinedConst {
-    nested_bodies: Lrc<BTreeMap<hir::BodyId, hir::Body>>
-}
-
-impl hir::print::PpAnn for InlinedConst {
-    fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested)
-              -> io::Result<()> {
-        if let hir::print::Nested::Body(body) = nested {
-            state.print_expr(&self.nested_bodies[&body].value)
-        } else {
-            Ok(())
-        }
-    }
-}
-
 pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
-    let body = cx.tcx.extern_const_body(did).body;
-    let inlined = InlinedConst {
-        nested_bodies: cx.tcx.item_body_nested_bodies(did).nested_bodies
-    };
-    hir::print::to_string(&inlined, |s| s.print_expr(&body.value))
+    cx.tcx.rendered_const(did)
 }
 
 fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
index da8085d84c3f6729d8cda184f862d1a52b20147b..443caa7618d7414f81896fe56e01cacb021d3d94 100644 (file)
@@ -1178,6 +1178,10 @@ enum PathKind {
     Type,
 }
 
+fn resolution_failure(cx: &DocContext, path_str: &str) {
+    cx.sess().warn(&format!("[{}] cannot be resolved, ignoring it...", path_str));
+}
+
 impl Clean<Attributes> for [ast::Attribute] {
     fn clean(&self, cx: &DocContext) -> Attributes {
         let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
@@ -1228,6 +1232,7 @@ fn clean(&self, cx: &DocContext) -> Attributes {
                             if let Ok(def) = resolve(cx, path_str, true) {
                                 def
                             } else {
+                                resolution_failure(cx, path_str);
                                 // this could just be a normal link or a broken link
                                 // we could potentially check if something is
                                 // "intra-doc-link-like" and warn in that case
@@ -1238,6 +1243,7 @@ fn clean(&self, cx: &DocContext) -> Attributes {
                             if let Ok(def) = resolve(cx, path_str, false) {
                                 def
                             } else {
+                                resolution_failure(cx, path_str);
                                 // this could just be a normal link
                                 continue;
                             }
@@ -1282,6 +1288,7 @@ fn clean(&self, cx: &DocContext) -> Attributes {
                             } else if let Ok(value_def) = resolve(cx, path_str, true) {
                                 value_def
                             } else {
+                                resolution_failure(cx, path_str);
                                 // this could just be a normal link
                                 continue;
                             }
@@ -1290,6 +1297,7 @@ fn clean(&self, cx: &DocContext) -> Attributes {
                             if let Some(def) = macro_resolve(cx, path_str) {
                                 (def, None)
                             } else {
+                                resolution_failure(cx, path_str);
                                 continue
                             }
                         }
index 781379d2d8c3e161fee2ad0c0581fed0b27b1c65..2bd1e72f0eb173057cdecbf2ac264145bfe6ef64 100644 (file)
@@ -18,6 +18,7 @@
 use rustc::ty::{self, TyCtxt, AllArenas};
 use rustc::hir::map as hir_map;
 use rustc::lint;
+use rustc::session::config::ErrorOutputType;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_resolve as resolve;
 use rustc_metadata::creader::CrateLoader;
 use syntax::codemap;
 use syntax::edition::Edition;
 use syntax::feature_gate::UnstableFeatures;
+use syntax::json::JsonEmitter;
 use errors;
-use errors::emitter::ColorConfig;
+use errors::emitter::{Emitter, EmitterWriter};
 
 use std::cell::{RefCell, Cell};
 use std::mem;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use std::rc::Rc;
 use std::path::PathBuf;
 
@@ -115,7 +117,6 @@ fn is_doc_reachable(&self, did: DefId) -> bool {
     }
 }
 
-
 pub fn run_core(search_paths: SearchPaths,
                 cfgs: Vec<String>,
                 externs: config::Externs,
@@ -126,7 +127,8 @@ pub fn run_core(search_paths: SearchPaths,
                 crate_name: Option<String>,
                 force_unstable_if_unmarked: bool,
                 edition: Edition,
-                cg: CodegenOptions) -> (clean::Crate, RenderInfo)
+                cg: CodegenOptions,
+                error_format: ErrorOutputType) -> (clean::Crate, RenderInfo)
 {
     // Parse, resolve, and typecheck the given crate.
 
@@ -138,6 +140,7 @@ pub fn run_core(search_paths: SearchPaths,
     let warning_lint = lint::builtin::WARNINGS.name_lower();
 
     let host_triple = TargetTriple::from_triple(config::host_triple());
+    // plays with error output here!
     let sessopts = config::Options {
         maybe_sysroot,
         search_paths,
@@ -152,17 +155,45 @@ pub fn run_core(search_paths: SearchPaths,
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions {
             force_unstable_if_unmarked,
-            edition,
             ..config::basic_debugging_options()
         },
+        error_format,
+        edition,
         ..config::basic_options().clone()
     };
 
     let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
-    let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
-                                                               true,
-                                                               false,
-                                                               Some(codemap.clone()));
+    let emitter: Box<dyn Emitter + sync::Send> = match error_format {
+        ErrorOutputType::HumanReadable(color_config) => Box::new(
+            EmitterWriter::stderr(
+                color_config,
+                Some(codemap.clone()),
+                false,
+                sessopts.debugging_opts.teach,
+            ).ui_testing(sessopts.debugging_opts.ui_testing)
+        ),
+        ErrorOutputType::Json(pretty) => Box::new(
+            JsonEmitter::stderr(
+                None,
+                codemap.clone(),
+                pretty,
+                sessopts.debugging_opts.approximate_suggestions,
+            ).ui_testing(sessopts.debugging_opts.ui_testing)
+        ),
+        ErrorOutputType::Short(color_config) => Box::new(
+            EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)
+        ),
+    };
+
+    let diagnostic_handler = errors::Handler::with_emitter_and_flags(
+        emitter,
+        errors::HandlerFlags {
+            can_emit_warnings: true,
+            treat_err_as_bug: false,
+            external_macro_backtrace: false,
+            ..Default::default()
+        },
+    );
 
     let mut sess = session::build_session_(
         sessopts, cpath, diagnostic_handler, codemap,
index e9c6488c49c6cb0f9c90ea74b268fc95b136f28e..537828de2c7f35fd56bdabc7a4e89b5400c60675 100644 (file)
@@ -19,7 +19,7 @@
 /// discriminants. JavaScript then is used to decode them into the original value.
 /// Consequently, every change to this type should be synchronized to
 /// the `itemTypes` mapping table in `static/main.js`.
-#[derive(Copy, PartialEq, Clone)]
+#[derive(Copy, PartialEq, Clone, Debug)]
 pub enum ItemType {
     Module          = 0,
     ExternCrate     = 1,
index aac5d0d2601deca63ff43b781d06086a83a63a13..fd54e9bd1e06c3ab340cd2ed118537cef3085e74 100644 (file)
@@ -37,128 +37,120 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     -> io::Result<()>
 {
     write!(dst,
-r##"<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <meta name="generator" content="rustdoc">
-    <meta name="description" content="{description}">
-    <meta name="keywords" content="{keywords}">
-
-    <title>{title}</title>
-
-    <link rel="stylesheet" type="text/css" href="{root_path}normalize{suffix}.css">
-    <link rel="stylesheet" type="text/css" href="{root_path}rustdoc{suffix}.css"
-          id="mainThemeStyle">
-    {themes}
-    <link rel="stylesheet" type="text/css" href="{root_path}dark{suffix}.css">
-    <link rel="stylesheet" type="text/css" href="{root_path}light{suffix}.css" id="themeStyle">
-    <script src="{root_path}storage{suffix}.js"></script>
-    {css_extension}
-
-    {favicon}
-    {in_header}
-</head>
-<body class="rustdoc {css_class}">
-    <!--[if lte IE 8]>
-    <div class="warning">
-        This old browser is unsupported and will most likely display funky
-        things.
-    </div>
-    <![endif]-->
-
-    {before_content}
-
-    <nav class="sidebar">
-        <div class="sidebar-menu">&#9776;</div>
-        {logo}
-        {sidebar}
-    </nav>
-
-    <div class="theme-picker">
-        <button id="theme-picker" aria-label="Pick another theme!">
-            <img src="{root_path}brush{suffix}.svg" width="18" alt="Pick another theme!">
-        </button>
-        <div id="theme-choices"></div>
-    </div>
-    <script src="{root_path}theme{suffix}.js"></script>
-    <nav class="sub">
-        <form class="search-form js-only">
-            <div class="search-container">
-                <input class="search-input" name="search"
-                       autocomplete="off"
-                       placeholder="Click or press ‘S’ to search, ‘?’ for more options…"
-                       type="search">
-            </div>
-        </form>
-    </nav>
-
-    <section id='main' class="content">{content}</section>
-    <section id='search' class="content hidden"></section>
-
-    <section class="footer"></section>
-
-    <aside id="help" class="hidden">
-        <div>
-            <h1 class="hidden">Help</h1>
-
-            <div class="shortcuts">
-                <h2>Keyboard Shortcuts</h2>
-
-                <dl>
-                    <dt><kbd>?</kbd></dt>
-                    <dd>Show this help dialog</dd>
-                    <dt><kbd>S</kbd></dt>
-                    <dd>Focus the search field</dd>
-                    <dt><kbd>↑</kbd></dt>
-                    <dd>Move up in search results</dd>
-                    <dt><kbd>↓</kbd></dt>
-                    <dd>Move down in search results</dd>
-                    <dt><kbd>↹</kbd></dt>
-                    <dd>Switch tab</dd>
-                    <dt><kbd>&#9166;</kbd></dt>
-                    <dd>Go to active search result</dd>
-                    <dt><kbd>+</kbd></dt>
-                    <dd>Expand all sections</dd>
-                    <dt><kbd>-</kbd></dt>
-                    <dd>Collapse all sections</dd>
-                </dl>
-            </div>
-
-            <div class="infos">
-                <h2>Search Tricks</h2>
-
-                <p>
-                    Prefix searches with a type followed by a colon (e.g.
-                    <code>fn:</code>) to restrict the search to a given type.
-                </p>
-
-                <p>
-                    Accepted types are: <code>fn</code>, <code>mod</code>,
-                    <code>struct</code>, <code>enum</code>,
-                    <code>trait</code>, <code>type</code>, <code>macro</code>,
-                    and <code>const</code>.
-                </p>
-
-                <p>
-                    Search functions by type signature (e.g.
-                    <code>vec -> usize</code> or <code>* -> vec</code>)
-                </p>
-            </div>
-        </div>
-    </aside>
-
-    {after_content}
-
-    <script>
-        window.rootPath = "{root_path}";
-        window.currentCrate = "{krate}";
-    </script>
-    <script src="{root_path}main{suffix}.js"></script>
-    <script defer src="{root_path}search-index.js"></script>
-</body>
-</html>"##,
+"<!DOCTYPE html>\
+<html lang=\"en\">\
+<head>\
+    <meta charset=\"utf-8\">\
+    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
+    <meta name=\"generator\" content=\"rustdoc\">\
+    <meta name=\"description\" content=\"{description}\">\
+    <meta name=\"keywords\" content=\"{keywords}\">\
+    <title>{title}</title>\
+    <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}normalize{suffix}.css\">\
+    <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}rustdoc{suffix}.css\" \
+          id=\"mainThemeStyle\">\
+    {themes}\
+    <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}dark{suffix}.css\">\
+    <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}light{suffix}.css\" \
+          id=\"themeStyle\">\
+    <script src=\"{root_path}storage{suffix}.js\"></script>\
+    {css_extension}\
+    {favicon}\
+    {in_header}\
+</head>\
+<body class=\"rustdoc {css_class}\">\
+    <!--[if lte IE 8]>\
+    <div class=\"warning\">\
+        This old browser is unsupported and will most likely display funky \
+        things.\
+    </div>\
+    <![endif]-->\
+    {before_content}\
+    <nav class=\"sidebar\">\
+        <div class=\"sidebar-menu\">&#9776;</div>\
+        {logo}\
+        {sidebar}\
+    </nav>\
+    <div class=\"theme-picker\">\
+        <button id=\"theme-picker\" aria-label=\"Pick another theme!\">\
+            <img src=\"{root_path}brush{suffix}.svg\" width=\"18\" alt=\"Pick another theme!\">\
+        </button>\
+        <div id=\"theme-choices\"></div>\
+    </div>\
+    <script src=\"{root_path}theme{suffix}.js\"></script>\
+    <nav class=\"sub\">\
+        <form class=\"search-form js-only\">\
+            <div class=\"search-container\">\
+                <input class=\"search-input\" name=\"search\" \
+                       autocomplete=\"off\" \
+                       placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
+                       type=\"search\">\
+                <a id=\"settings-menu\" href=\"{root_path}settings.html\">\
+                    <img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\
+                </a>\
+            </div>\
+        </form>\
+    </nav>\
+    <section id=\"main\" class=\"content\">{content}</section>\
+    <section id=\"search\" class=\"content hidden\"></section>\
+    <section class=\"footer\"></section>\
+    <aside id=\"help\" class=\"hidden\">\
+        <div>\
+            <h1 class=\"hidden\">Help</h1>\
+            <div class=\"shortcuts\">\
+                <h2>Keyboard Shortcuts</h2>\
+                <dl>\
+                    <dt><kbd>?</kbd></dt>\
+                    <dd>Show this help dialog</dd>\
+                    <dt><kbd>S</kbd></dt>\
+                    <dd>Focus the search field</dd>\
+                    <dt><kbd>↑</kbd></dt>\
+                    <dd>Move up in search results</dd>\
+                    <dt><kbd>↓</kbd></dt>\
+                    <dd>Move down in search results</dd>\
+                    <dt><kbd>↹</kbd></dt>\
+                    <dd>Switch tab</dd>\
+                    <dt><kbd>&#9166;</kbd></dt>\
+                    <dd>Go to active search result</dd>\
+                    <dt><kbd>+</kbd></dt>\
+                    <dd>Expand all sections</dd>\
+                    <dt><kbd>-</kbd></dt>\
+                    <dd>Collapse all sections</dd>\
+                </dl>\
+            </div>\
+            <div class=\"infos\">\
+                <h2>Search Tricks</h2>\
+                <p>\
+                    Prefix searches with a type followed by a colon (e.g. \
+                    <code>fn:</code>) to restrict the search to a given type.\
+                </p>\
+                <p>\
+                    Accepted types are: <code>fn</code>, <code>mod</code>, \
+                    <code>struct</code>, <code>enum</code>, \
+                    <code>trait</code>, <code>type</code>, <code>macro</code>, \
+                    and <code>const</code>.\
+                </p>\
+                <p>\
+                    Search functions by type signature (e.g. \
+                    <code>vec -> usize</code> or <code>* -> vec</code>)\
+                </p>\
+                <p>\
+                    Search multiple things at once by splitting your query with comma (e.g. \
+                    <code>str,u8</code> or <code>String,struct:Vec,test</code>)\
+                </p>\
+            </div>\
+        </div>\
+    </aside>\
+    {after_content}\
+    <script>\
+        window.rootPath = \"{root_path}\";\
+        window.currentCrate = \"{krate}\";\
+    </script>\
+    <script src=\"{root_path}main{suffix}.js\"></script>\
+    <script defer src=\"{root_path}search-index.js\"></script>\
+    <script defer src=\"{root_path}aliases.js\"></script>\
+</body>\
+</html>",
     css_extension = if css_file_extension {
         format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme{suffix}.css\">",
                 root_path = page.root_path,
@@ -193,9 +185,10 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     themes = themes.iter()
                    .filter_map(|t| t.file_stem())
                    .filter_map(|t| t.to_str())
-                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#,
+                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
                                     page.root_path,
-                                    t.replace(".css", &format!("{}.css", page.resource_suffix))))
+                                    t,
+                                    page.resource_suffix))
                    .collect::<String>(),
     suffix=page.resource_suffix,
     )
index 9e2c7bd7ef1ed6fc808192442760279ac88b7a76..0ae946c4182864e39111e9a2202e2b769899f987 100644 (file)
@@ -107,7 +107,7 @@ pub struct SharedContext {
     /// This describes the layout of each page, and is not modified after
     /// creation of the context (contains info like the favicon and added html).
     pub layout: layout::Layout,
-    /// This flag indicates whether [src] links should be generated or not. If
+    /// This flag indicates whether `[src]` links should be generated or not. If
     /// the source files are present in the html rendering, then this will be
     /// `true`.
     pub include_sources: bool,
@@ -329,6 +329,10 @@ pub struct Cache {
     // yet when its implementation methods are being indexed. Caches such methods
     // and their parent id here and indexes them at the end of crate parsing.
     orphan_impl_items: Vec<(DefId, clean::Item)>,
+
+    /// 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>>,
 }
 
 /// Temporary storage for data obtained during `RustdocVisitor::clean()`.
@@ -369,6 +373,7 @@ struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, }
 
 /// Struct representing one entry in the JS search index. These are all emitted
 /// by hand to a large JS file at the end of cache-creation.
+#[derive(Debug)]
 struct IndexItem {
     ty: ItemType,
     name: String,
@@ -396,6 +401,7 @@ fn to_json(&self) -> Json {
 }
 
 /// A type used for the search index.
+#[derive(Debug)]
 struct Type {
     name: Option<String>,
     generics: Option<Vec<String>>,
@@ -418,9 +424,10 @@ fn to_json(&self) -> Json {
 }
 
 /// Full type of functions/methods in the search index.
+#[derive(Debug)]
 struct IndexItemFunctionType {
     inputs: Vec<Type>,
-    output: Option<Type>
+    output: Option<Type>,
 }
 
 impl ToJson for IndexItemFunctionType {
@@ -609,6 +616,7 @@ pub fn run(mut krate: clean::Crate,
         owned_box_did,
         masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()),
         typarams: external_typarams,
+        aliases: FxHashMap(),
     };
 
     // Cache where all our extern crates are located
@@ -742,6 +750,8 @@ fn write_shared(cx: &Context,
 
     write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
           include_bytes!("static/rustdoc.css"))?;
+    write(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
+          include_bytes!("static/settings.css"))?;
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
@@ -761,6 +771,8 @@ fn write_shared(cx: &Context,
 
     write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
           include_bytes!("static/brush.svg"))?;
+    write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
+          include_bytes!("static/wheel.svg"))?;
     write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
           include_bytes!("static/themes/light.css"))?;
     themes.insert("light".to_owned());
@@ -794,8 +806,7 @@ fn write_shared(cx: &Context,
         switchTheme(currentTheme, mainTheme, item);
     }};
     themes.appendChild(but);
-}});
-"#,
+}});"#,
                  themes.iter()
                        .map(|s| format!("\"{}\"", s))
                        .collect::<Vec<String>>()
@@ -804,6 +815,8 @@ fn write_shared(cx: &Context,
 
     write(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)),
                       include_bytes!("static/main.js"))?;
+    write(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
+                      include_bytes!("static/settings.js"))?;
 
     {
         let mut data = format!("var resourcesSuffix = \"{}\";\n",
@@ -847,8 +860,7 @@ fn write_shared(cx: &Context,
     write(cx.dst.join("COPYRIGHT.txt"),
           include_bytes!("static/COPYRIGHT.txt"))?;
 
-    fn collect(path: &Path, krate: &str,
-               key: &str) -> io::Result<Vec<String>> {
+    fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> {
         let mut ret = Vec::new();
         if path.exists() {
             for line in BufReader::new(File::open(path)?).lines() {
@@ -865,6 +877,40 @@ fn collect(path: &Path, krate: &str,
         Ok(ret)
     }
 
+    fn show_item(item: &IndexItem, krate: &str) -> String {
+        format!("{{'crate':'{}','ty':{},'name':'{}','path':'{}'{}}}",
+                krate, item.ty as usize, item.name, item.path,
+                if let Some(p) = item.parent_idx {
+                    format!(",'parent':{}", p)
+                } else {
+                    String::new()
+                })
+    }
+
+    let dst = cx.dst.join("aliases.js");
+    {
+        let mut all_aliases = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
+        let mut w = try_err!(File::create(&dst), &dst);
+        let mut output = String::with_capacity(100);
+        for (alias, items) in &cache.aliases {
+            if items.is_empty() {
+                continue
+            }
+            output.push_str(&format!("\"{}\":[{}],",
+                                     alias,
+                                     items.iter()
+                                          .map(|v| show_item(v, &krate.name))
+                                          .collect::<Vec<_>>()
+                                          .join(",")));
+        }
+        all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output));
+        all_aliases.sort();
+        try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst);
+        for aliases in &all_aliases {
+            try_err!(writeln!(&mut w, "{}", aliases), &dst);
+        }
+    }
+
     // Update the search index
     let dst = cx.dst.join("search-index.js");
     let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
@@ -1251,13 +1297,13 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 // `public_items` map, so we can skip inserting into the
                 // paths map if there was already an entry present and we're
                 // not a public item.
-                if
-                    !self.paths.contains_key(&item.def_id) ||
-                    self.access_levels.is_public(item.def_id)
+                if !self.paths.contains_key(&item.def_id) ||
+                   self.access_levels.is_public(item.def_id)
                 {
                     self.paths.insert(item.def_id,
                                       (self.stack.clone(), item.type_()));
                 }
+                self.add_aliases(&item);
             }
             // Link variants to their parent enum because pages aren't emitted
             // for each variant.
@@ -1268,6 +1314,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             }
 
             clean::PrimitiveItem(..) if item.visibility.is_some() => {
+                self.add_aliases(&item);
                 self.paths.insert(item.def_id, (self.stack.clone(),
                                                 item.type_()));
             }
@@ -1372,6 +1419,36 @@ fn generics(&mut self, generics: &clean::Generics) {
             }
         }
     }
+
+    fn add_aliases(&mut self, item: &clean::Item) {
+        if item.def_id.index == CRATE_DEF_INDEX {
+            return
+        }
+        if let Some(ref item_name) = item.name {
+            let path = self.paths.get(&item.def_id)
+                                 .map(|p| p.0.join("::").to_string())
+                                 .unwrap_or("std".to_owned());
+            for alias in item.attrs.lists("doc")
+                                   .filter(|a| a.check_name("alias"))
+                                   .filter_map(|a| a.value_str()
+                                                    .map(|s| s.to_string().replace("\"", "")))
+                                   .filter(|v| !v.is_empty())
+                                   .collect::<FxHashSet<_>>()
+                                   .into_iter() {
+                self.aliases.entry(alias)
+                            .or_insert(Vec::with_capacity(1))
+                            .push(IndexItem {
+                                ty: item.type_(),
+                                name: item_name.to_string(),
+                                path: path.clone(),
+                                desc: String::new(),
+                                parent: None,
+                                parent_idx: None,
+                                search_type: get_index_search_type(&item),
+                            });
+            }
+        }
+    }
 }
 
 #[derive(Debug, Eq, PartialEq, Hash)]
@@ -1503,6 +1580,51 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[derive(Debug)]
+struct Settings<'a> {
+    // (id, explanation, default value)
+    settings: Vec<(&'static str, &'static str, bool)>,
+    root_path: &'a str,
+    suffix: &'a str,
+}
+
+impl<'a> Settings<'a> {
+    pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> {
+        Settings {
+            settings: vec![
+                ("item-declarations", "Auto-hide item declarations.", true),
+                ("item-attributes", "Auto-hide item attributes.", true),
+            ],
+            root_path,
+            suffix,
+        }
+    }
+}
+
+impl<'a> fmt::Display for Settings<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f,
+"<h1 class='fqn'>\
+     <span class='in-band'>Rustdoc settings</span>\
+</h1>\
+<div class='settings'>{}</div>\
+<script src='{}settings{}.js'></script>",
+               self.settings.iter()
+                            .map(|(id, text, enabled)| {
+                                format!("<div class='setting-line'>\
+                                             <label class='toggle'>\
+                                                <input type='checkbox' id='{}' {}>\
+                                                <span class='slider'></span>\
+                                             </label>\
+                                             <div>{}</div>\
+                                         </div>", id, if *enabled { " checked" } else { "" }, text)
+                            })
+                            .collect::<String>(),
+               self.root_path,
+               self.suffix)
+    }
+}
+
 impl Context {
     /// String representation of how to get back to the root path of the 'doc/'
     /// folder in terms of a relative URL.
@@ -1546,6 +1668,8 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
         };
         let final_file = self.dst.join(&krate.name)
                                  .join("all.html");
+        let settings_file = self.dst.join("settings.html");
+
         let crate_name = krate.name.clone();
         item.name = Some(krate.name);
 
@@ -1567,7 +1691,7 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
         if !root_path.ends_with('/') {
             root_path.push('/');
         }
-        let page = layout::Page {
+        let mut page = layout::Page {
             title: "List of all items in this crate",
             css_class: "mod",
             root_path: "../",
@@ -1590,6 +1714,27 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
                                 self.shared.css_file_extension.is_some(),
                                 &self.shared.themes),
                  &final_file);
+
+        // Generating settings page.
+        let settings = Settings::new("./", &self.shared.resource_suffix);
+        page.title = "Rustdoc settings";
+        page.description = "Settings of Rustdoc";
+        page.root_path = "./";
+
+        let mut w = BufWriter::new(try_err!(File::create(&settings_file), &settings_file));
+        let mut themes = self.shared.themes.clone();
+        let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
+        themes.push(PathBuf::from("settings.css"));
+        let mut layout = self.shared.layout.clone();
+        layout.krate = String::new();
+        layout.logo = String::new();
+        layout.favicon = String::new();
+        try_err!(layout::render(&mut w, &layout,
+                                &page, &sidebar, &settings,
+                                self.shared.css_file_extension.is_some(),
+                                &themes),
+                 &settings_file);
+
         Ok(())
     }
 
@@ -1728,7 +1873,9 @@ fn item<F>(&mut self, item: clean::Item, all: &mut AllTypes, mut f: F) -> Result
                 let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                 try_err!(dst.write_all(&buf), &joint_dst);
 
-                all.append(full_path(self, &item), &item_type);
+                if !self.render_redirect_pages {
+                    all.append(full_path(self, &item), &item_type);
+                }
                 // Redirect from a sane URL using the namespace to Rustdoc's
                 // URL for the page.
                 let redir_name = format!("{}.{}.html", name, item_type.name_space());
index 3a3fa833c238ba569da70ade3fa9444ee0dd9ec0..2cae88855e3ea431daaa3576fb333200a9a8e02b 100644 (file)
                     return false;
                 }
                 var end = start + className.length;
-                if (end < elemClass.length && elemClass[end] !== ' ') {
-                    return false;
-                }
-                return true;
+                return !(end < elemClass.length && elemClass[end] !== ' ');
             }
             if (start > 0 && elemClass[start - 1] !== ' ') {
                 return false;
             }
             var end = start + className.length;
-            if (end < elemClass.length && elemClass[end] !== ' ') {
-                return false;
-            }
-            return true;
+            return !(end < elemClass.length && elemClass[end] !== ' ');
         }
         return false;
     }
         } else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) {
             var prev_id = 0;
 
-            var set_fragment = function (name) {
+            var set_fragment = function(name) {
                 if (browserSupportsHistoryApi()) {
                     history.replaceState(null, null, '#' + name);
                     window.hashchange();
                 query.search = val;
             // searching by type
             } else if (val.search("->") > -1) {
-                var trimmer = function (s) { return s.trim(); };
+                var trimmer = function(s) { return s.trim(); };
                 var parts = val.split("->").map(trimmer);
                 var input = parts[0];
                 // sort inputs so that order does not matter
                 }
             }
 
-            return {
+            var ret = {
                 'in_args': sortResults(results_in_args, true),
                 'returned': sortResults(results_returned, true),
                 'others': sortResults(results),
             };
+            if (ALIASES[window.currentCrate][query.raw]) {
+                var aliases = ALIASES[window.currentCrate][query.raw];
+                for (var i = 0; i < aliases.length; ++i) {
+                    ret['others'].unshift(aliases[i]);
+                    if (ret['others'].length > MAX_RESULTS) {
+                        ret['others'].pop();
+                    }
+                }
+            }
+            return ret;
         }
 
         /**
                 array.forEach(function(item) {
                     var name, type, href, displayPath;
 
-                    if (shown.indexOf(item) !== -1) {
+                    var id_ty = item.ty + item.path + item.name;
+                    if (shown.indexOf(id_ty) !== -1) {
                         return;
                     }
 
-                    shown.push(item);
+                    console.log(item);
+                    shown.push(id_ty);
                     name = item.name;
                     type = itemTypes[item.ty];
 
             printTab(currentTab);
         }
 
+        function execSearch(query, searchWords) {
+            var queries = query.raw.split(",");
+            var results = {
+                'in_args': [],
+                'returned': [],
+                'others': [],
+            };
+
+            for (var i = 0; i < queries.length; ++i) {
+                var query = queries[i].trim();
+                if (query.length !== 0) {
+                    var tmp = execQuery(getQuery(query), searchWords);
+
+                    results['in_args'].push(tmp['in_args']);
+                    results['returned'].push(tmp['returned']);
+                    results['others'].push(tmp['others']);
+                }
+            }
+            if (queries.length > 1) {
+                function getSmallest(arrays, positions) {
+                    var start = null;
+
+                    for (var it = 0; it < positions.length; ++it) {
+                        if (arrays[it].length > positions[it] &&
+                            (start === null || start > arrays[it][positions[it]].lev)) {
+                            start = arrays[it][positions[it]].lev;
+                        }
+                    }
+                    return start;
+                }
+
+                function mergeArrays(arrays) {
+                    var ret = [];
+                    var positions = [];
+
+                    for (var x = 0; x < arrays.length; ++x) {
+                        positions.push(0);
+                    }
+                    while (ret.length < MAX_RESULTS) {
+                        var smallest = getSmallest(arrays, positions);
+                        if (smallest === null) {
+                            break;
+                        }
+                        for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
+                            if (arrays[x].length > positions[x] &&
+                                    arrays[x][positions[x]].lev === smallest) {
+                                ret.push(arrays[x][positions[x]]);
+                                positions[x] += 1;
+                            }
+                        }
+                    }
+                    return ret;
+                }
+
+                return {
+                    'in_args': mergeArrays(results['in_args']),
+                    'returned': mergeArrays(results['returned']),
+                    'others': mergeArrays(results['others']),
+                };
+            } else {
+                return {
+                    'in_args': results['in_args'][0],
+                    'returned': results['returned'][0],
+                    'others': results['others'][0],
+                };
+            }
+        }
+
         function search(e) {
-            var query,
-                obj, i, len,
-                results = {"in_args": [], "returned": [], "others": []},
-                resultIndex;
             var params = getQueryStringParams();
+            var query = getQuery(document.getElementsByClassName('search-input')[0].value.trim());
 
-            query = getQuery(document.getElementsByClassName('search-input')[0].value);
             if (e) {
                 e.preventDefault();
             }
                 }
             }
 
-            results = execQuery(query, index);
-            showResults(results);
+            showResults(execSearch(query, index));
         }
 
         function buildIndex(rawSearchIndex) {
         startSearch();
 
         // Draw a convenient sidebar of known crates if we have a listing
-        if (rootPath === '../') {
+        if (rootPath === '../' || rootPath === "./") {
             var sidebar = document.getElementsByClassName('sidebar-elems')[0];
             if (sidebar) {
                 var div = document.createElement('div');
                 crates.sort();
                 for (var i = 0; i < crates.length; ++i) {
                     var klass = 'crate';
-                    if (crates[i] === window.currentCrate) {
+                    if (rootPath !== "./" && crates[i] === window.currentCrate) {
                         klass += ' current';
                     }
                     var link = document.createElement('a');
-                    link.href = '../' + crates[i] + '/index.html';
+                    link.href = rootPath + crates[i] + '/index.html';
                     link.title = rawSearchIndex[crates[i]].doc;
                     link.className = klass;
                     link.textContent = crates[i];
                 otherMessage = '&nbsp;Show&nbsp;type&nbsp;declaration';
             }
             e.parentNode.insertBefore(createToggle(otherMessage), e);
-            if (otherMessage) {
+            if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") {
                 collapseDocs(e.previousSibling.childNodes[0], "toggle");
             }
         }
     onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) {
         onEach(e.getElementsByClassName('attributes'), function(i_e) {
             i_e.parentNode.insertBefore(createToggleWrapper(), i_e);
-            collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
+            if (getCurrentValue("rustdoc-item-attributes") !== "false") {
+                collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
+            }
         });
     });
 
index 4c6c8dcfddafc033ba00137fa46cb416ac7396a1..d6b3ab26af8aebf5b7075eb81063744ce95ce744 100644 (file)
@@ -548,8 +548,16 @@ a {
 
 .block a.current.crate { font-weight: 500; }
 
+.search-container {
+       position: relative;
+}
+.search-container > .top-button {
+       position: absolute;
+       right: 0;
+       top: 10px;
+}
 .search-input {
-       width: 100%;
+       width: calc(100% - 34px);
        /* Override Normalize.css: we have margins and do
         not want to overflow - the `moz` attribute is necessary
         until Firefox 29, too early to drop at this point */
@@ -1224,7 +1232,14 @@ kbd {
        outline: none;
 }
 
-#theme-picker {
+#settings-menu {
+       position: absolute;
+       right: 0;
+       top: 10px;
+       outline: none;
+}
+
+#theme-picker, #settings-menu {
        padding: 4px;
        width: 27px;
        height: 29px;
diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css
new file mode 100644 (file)
index 0000000..34835f3
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * 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.
+ */
+
+.setting-line {
+       padding: 5px;
+}
+
+.setting-line > div {
+       max-width: calc(100% - 74px);
+       display: inline-block;
+       vertical-align: top;
+       font-size: 17px;
+       padding-top: 2px;
+}
+
+.toggle {
+       position: relative;
+       display: inline-block;
+       width: 45px;
+       height: 27px;
+       margin-right: 20px;
+}
+
+.toggle input {
+       display: none;
+}
+
+.slider {
+       position: absolute;
+       cursor: pointer;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+       background-color: #ccc;
+       -webkit-transition: .3s;
+       transition: .3s;
+}
+
+.slider:before {
+       position: absolute;
+       content: "";
+       height: 19px;
+       width: 19px;
+       left: 4px;
+       bottom: 4px;
+       background-color: white;
+       -webkit-transition: .3s;
+       transition: .3s;
+}
+
+input:checked + .slider {
+       background-color: #2196F3;
+}
+
+input:focus + .slider {
+       box-shadow: 0 0 1px #2196F3;
+}
+
+input:checked + .slider:before {
+       -webkit-transform: translateX(19px);
+       -ms-transform: translateX(19px);
+       transform: translateX(19px);
+}
\ No newline at end of file
diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js
new file mode 100644 (file)
index 0000000..cc7c600
--- /dev/null
@@ -0,0 +1,41 @@
+/*!
+ * Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+ * file at the top-level directory of this distribution and at
+ * http://rust-lang.org/COPYRIGHT.
+ *
+ * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+ * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+ * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+ * option. This file may not be copied, modified, or distributed
+ * except according to those terms.
+ */
+
+(function () {
+    function changeSetting(settingName, isEnabled) {
+        updateLocalStorage('rustdoc-' + settingName, isEnabled);
+    }
+
+    function getSettingValue(settingName) {
+        return getCurrentValue('rustdoc-' + settingName);
+    }
+
+    function setEvents() {
+        var elems = document.getElementsByClassName("slider");
+        if (!elems || elems.length === 0) {
+            return;
+        }
+        for (var i = 0; i < elems.length; ++i) {
+            var toggle = elems[i].previousElementSibling;
+            var settingId = toggle.id;
+            var settingValue = getSettingValue(settingId);
+            if (settingValue !== null) {
+                toggle.checked = settingValue === "true";
+            }
+            toggle.onchange = function() {
+                changeSetting(this.id, this.checked);
+            };
+        }
+    }
+
+    setEvents();
+})();
index 93971a205bf35d71d2730370423d1950efbafd11..da4be7db5aa92b43088abbc4db36cba6ffc39431 100644 (file)
@@ -362,12 +362,13 @@ kbd {
        box-shadow-color: #c6cbd1;
 }
 
-#theme-picker {
+#theme-picker, #settings-menu {
        border-color: #e0e0e0;
        background: #f0f0f0;
 }
 
-#theme-picker:hover, #theme-picker:focus {
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus {
        border-color: #ffb900;
 }
 
index e13818b4bd27867fa9bc05f2ec8651378a6f97bd..12af01d2e249809e7cde52f89116c3db8839b1fc 100644 (file)
@@ -356,12 +356,13 @@ kbd {
        box-shadow-color: #c6cbd1;
 }
 
-#theme-picker {
+#theme-picker, #settings-menu {
        border-color: #e0e0e0;
        background-color: #fff;
 }
 
-#theme-picker:hover, #theme-picker:focus {
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus {
        border-color: #717171;
 }
 
diff --git a/src/librustdoc/html/static/wheel.svg b/src/librustdoc/html/static/wheel.svg
new file mode 100644 (file)
index 0000000..44381a4
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" ?><!DOCTYPE svg  PUBLIC '-//W3C//DTD SVG 1.1//EN'  'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 27.434 29.5" height="29.5px" id="Capa_1" version="1.1" viewBox="0 0 27.434 29.5" width="27.434px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8   c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476   c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235   c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044   c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721   C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573   C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938   c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786   c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802   C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159   c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043   c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675   c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075   c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032   C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251   c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157   c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888   l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084   c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506   c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812   L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747   c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761   c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775   c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032   c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012   c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085   C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323   s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716   C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956   c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
\ No newline at end of file
index 1339a66f8b2e92baf7c6d6ea254f0db29865b4aa..60b713f2995e1089ee47478ed4c8a9dd9d58cc48 100644 (file)
@@ -23,6 +23,7 @@
 #![feature(test)]
 #![feature(vec_remove_item)]
 #![feature(entry_and_modify)]
+#![feature(dyn_trait)]
 
 extern crate arena;
 extern crate getopts;
@@ -48,6 +49,8 @@
 
 extern crate serialize as rustc_serialize; // used by deriving
 
+use errors::ColorConfig;
+
 use std::collections::{BTreeMap, BTreeSet};
 use std::default::Default;
 use std::env;
@@ -100,6 +103,7 @@ struct Output {
 
 pub fn main() {
     const STACK_SIZE: usize = 32_000_000; // 32MB
+    rustc_driver::set_sigpipe_handler();
     env_logger::init();
     let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
         syntax::with_globals(move || {
@@ -278,6 +282,21 @@ pub fn opts() -> Vec<RustcOptGroup> {
                      "edition to use when compiling rust code (default: 2015)",
                      "EDITION")
         }),
+        unstable("color", |o| {
+            o.optopt("",
+                     "color",
+                     "Configure coloring of output:
+                                          auto   = colorize, if output goes to a tty (default);
+                                          always = always colorize output;
+                                          never  = never colorize output",
+                     "auto|always|never")
+        }),
+        unstable("error-format", |o| {
+            o.optopt("",
+                     "error-format",
+                     "How errors and other messages are produced",
+                     "human|json|short")
+        }),
     ]
 }
 
@@ -362,9 +381,33 @@ pub fn main_args(args: &[String]) -> isize {
     }
     let input = &matches.free[0];
 
+    let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
+        Some("auto") => ColorConfig::Auto,
+        Some("always") => ColorConfig::Always,
+        Some("never") => ColorConfig::Never,
+        None => ColorConfig::Auto,
+        Some(arg) => {
+            print_error(&format!("argument for --color must be `auto`, `always` or `never` \
+                                  (instead was `{}`)", arg));
+            return 1;
+        }
+    };
+    let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
+        Some("human") => ErrorOutputType::HumanReadable(color),
+        Some("json") => ErrorOutputType::Json(false),
+        Some("pretty-json") => ErrorOutputType::Json(true),
+        Some("short") => ErrorOutputType::Short(color),
+        None => ErrorOutputType::HumanReadable(color),
+        Some(arg) => {
+            print_error(&format!("argument for --error-format must be `human`, `json` or \
+                                  `short` (instead was `{}`)", arg));
+            return 1;
+        }
+    };
+
     let mut libs = SearchPaths::new();
     for s in &matches.opt_strs("L") {
-        libs.add_path(s, ErrorOutputType::default());
+        libs.add_path(s, error_format);
     }
     let externs = match parse_externs(&matches) {
         Ok(ex) => ex,
@@ -464,7 +507,9 @@ pub fn main_args(args: &[String]) -> isize {
     }
 
     let output_format = matches.opt_str("w");
-    let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, move |out| {
+
+    let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, error_format,
+                            move |out| {
         let Output { krate, passes, renderinfo } = out;
         info!("going to format");
         match output_format.as_ref().map(|s| &**s) {
@@ -508,13 +553,14 @@ fn acquire_input<R, F>(input: PathBuf,
                        edition: Edition,
                        cg: CodegenOptions,
                        matches: &getopts::Matches,
+                       error_format: ErrorOutputType,
                        f: F)
                        -> Result<R, String>
 where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
     match matches.opt_str("r").as_ref().map(|s| &**s) {
-        Some("rust") => Ok(rust_input(input, externs, edition, cg, matches, f)),
+        Some("rust") => Ok(rust_input(input, externs, edition, cg, matches, error_format, f)),
         Some(s) => Err(format!("unknown input format: {}", s)),
-        None => Ok(rust_input(input, externs, edition, cg, matches, f))
+        None => Ok(rust_input(input, externs, edition, cg, matches, error_format, f))
     }
 }
 
@@ -545,6 +591,7 @@ fn rust_input<R, F>(cratefile: PathBuf,
                     edition: Edition,
                     cg: CodegenOptions,
                     matches: &getopts::Matches,
+                    error_format: ErrorOutputType,
                     f: F) -> R
 where R: 'static + Send,
       F: 'static + Send + FnOnce(Output) -> R
@@ -597,7 +644,7 @@ fn rust_input<R, F>(cratefile: PathBuf,
         let (mut krate, renderinfo) =
             core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
                            display_warnings, crate_name.clone(),
-                           force_unstable_if_unmarked, edition, cg);
+                           force_unstable_if_unmarked, edition, cg, error_format);
 
         info!("finished with rustc");
 
index 600e9eaa05f1450acbd3f5604241450fce828f0a..c4eaa48e49db62e47c6bb0bb3c4fc64b32f2871d 100644 (file)
@@ -80,9 +80,9 @@ pub fn run(input_path: &Path,
         lint_cap: Some(::rustc::lint::Level::Allow),
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions {
-            edition,
             ..config::basic_debugging_options()
         },
+        edition,
         ..config::basic_options().clone()
     };
 
@@ -223,9 +223,9 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
         test: as_test_harness,
         unstable_features: UnstableFeatures::from_environment(),
         debugging_opts: config::DebuggingOptions {
-            edition,
             ..config::basic_debugging_options()
         },
+        edition,
         ..config::basic_options().clone()
     };
 
@@ -437,7 +437,7 @@ fn partition_source(s: &str) -> (String, String) {
 
     for line in s.lines() {
         let trimline = line.trim();
-        let header = trimline.is_whitespace() ||
+        let header = trimline.chars().all(|c| c.is_whitespace()) ||
             trimline.starts_with("#![") ||
             trimline.starts_with("#[macro_use] extern crate") ||
             trimline.starts_with("extern crate");
index ff578ec42d23088ce2594175b24f3c4aeddce1b8..a8578404467b1d3185b4322abf2eb2ed9374f748 100644 (file)
 #![unstable(issue = "32838", feature = "allocator_api")]
 
 #[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap;
-#[doc(inline)] pub use alloc_crate::alloc::Global;
+#[doc(inline)] pub use alloc_crate::alloc::{Global, oom};
 #[doc(inline)] pub use alloc_system::System;
 #[doc(inline)] pub use core::alloc::*;
 
+#[cfg(not(stage0))]
+#[cfg(not(test))]
+#[doc(hidden)]
+#[lang = "oom"]
+pub extern fn rust_oom() -> ! {
+    rtabort!("memory allocation failed");
+}
+
 #[cfg(not(test))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
@@ -35,10 +43,11 @@ pub mod __default_lib_allocator {
         System.alloc(layout) as *mut u8
     }
 
+    #[cfg(stage0)]
     #[no_mangle]
     #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_oom() -> ! {
-        System.oom()
+        super::oom()
     }
 
     #[no_mangle]
index 20a4f9b508d240be95e285e97fdcbb45dcfc0952..a8c70489f443690c3151e0cd67f84a9ad43c324b 100644 (file)
@@ -11,7 +11,7 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
-use alloc::{Global, Alloc, CollectionAllocErr};
+use alloc::{CollectionAllocErr, oom};
 use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
@@ -784,7 +784,7 @@ fn raw_capacity(&self) -> usize {
     pub fn reserve(&mut self, additional: usize) {
         match self.try_reserve(additional) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
     }
@@ -1379,7 +1379,6 @@ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
     /// # Examples
     ///
     /// ```
-    /// #![feature(hash_map_remove_entry)]
     /// use std::collections::HashMap;
     ///
     /// # fn main() {
@@ -1389,7 +1388,7 @@ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
     /// assert_eq!(map.remove(&1), None);
     /// # }
     /// ```
-    #[unstable(feature = "hash_map_remove_entry", issue = "46344")]
+    #[stable(feature = "hash_map_remove_entry", since = "1.27.0")]
     pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
         where K: Borrow<Q>,
               Q: Hash + Eq
@@ -2127,8 +2126,8 @@ pub fn key(&self) -> &K {
     /// assert_eq!(map["poneyland"], 43);
     /// ```
     #[stable(feature = "entry_and_modify", since = "1.26.0")]
-    pub fn and_modify<F>(self, mut f: F) -> Self
-        where F: FnMut(&mut V)
+    pub fn and_modify<F>(self, f: F) -> Self
+        where F: FnOnce(&mut V)
     {
         match self {
             Occupied(mut entry) => {
index 93f059076d794ea84074ceb11de91b24e43255f7..52c53dc3b1251a35f83eae4ee14a5ba380243616 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::{Global, Alloc, Layout, CollectionAllocErr};
+use alloc::{Global, Alloc, Layout, CollectionAllocErr, oom};
 use cmp;
 use hash::{BuildHasher, Hash, Hasher};
 use marker;
@@ -770,7 +770,7 @@ unsafe fn try_new_uninitialized(capacity: usize) -> Result<RawTable<K, V>, Colle
     unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         match Self::try_new_uninitialized(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(table) => { table }
         }
     }
@@ -809,7 +809,7 @@ pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
     pub fn new(capacity: usize) -> RawTable<K, V> {
         match Self::try_new(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(table) => { table }
         }
     }
@@ -1124,7 +1124,7 @@ fn len(&self) -> usize {
 
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
     fn drop(&mut self) {
-        for _ in self {}
+        self.for_each(drop);
     }
 }
 
index 3c209928d432aa38a9b5c92995b96cc13fbc4367..749b8ccc13da642c1efca75057f2baa136494e17 100644 (file)
@@ -233,7 +233,7 @@ fn from(err: Cow<'a, str>) -> Box<Error> {
     }
 }
 
-#[stable(feature = "never_type", since = "1.26.0")]
+#[unstable(feature = "never_type", issue = "35121")]
 impl Error for ! {
     fn description(&self) -> &str { *self }
 }
@@ -284,14 +284,14 @@ fn description(&self) -> &str {
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl Error for num::TryFromIntError {
     fn description(&self) -> &str {
         self.__description()
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl Error for array::TryFromSliceError {
     fn description(&self) -> &str {
         self.__description()
@@ -365,7 +365,7 @@ fn description(&self) -> &str {
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl Error for char::CharTryFromError {
     fn description(&self) -> &str {
         "converted integer out of range for `char`"
index ca39089a9583acf553e6a164e20b71207e34290f..26644c769575c9bde37dd88e9af0a9077e2f54a9 100644 (file)
 #![allow(missing_docs)]
 
 #[cfg(not(test))]
-use core::num;
+#[cfg(stage0)]
+use core::num::Float;
 #[cfg(not(test))]
 use intrinsics;
 #[cfg(not(test))]
+#[cfg(stage0)]
 use num::FpCategory;
 #[cfg(not(test))]
 use sys::cmath;
 pub use core::f32::consts;
 
 #[cfg(not(test))]
-#[lang = "f32"]
+#[cfg_attr(stage0, lang = "f32")]
+#[cfg_attr(not(stage0), lang = "f32_runtime")]
 impl f32 {
-    /// Returns `true` if this value is `NaN` and false otherwise.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
-    /// let f = 7.0_f32;
-    ///
-    /// assert!(nan.is_nan());
-    /// assert!(!f.is_nan());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let f = 7.0f32;
-    /// let inf = f32::INFINITY;
-    /// let neg_inf = f32::NEG_INFINITY;
-    /// let nan = f32::NAN;
-    ///
-    /// assert!(!f.is_infinite());
-    /// assert!(!nan.is_infinite());
-    ///
-    /// assert!(inf.is_infinite());
-    /// assert!(neg_inf.is_infinite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
-
-    /// Returns `true` if this number is neither infinite nor `NaN`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let f = 7.0f32;
-    /// let inf = f32::INFINITY;
-    /// let neg_inf = f32::NEG_INFINITY;
-    /// let nan = f32::NAN;
-    ///
-    /// assert!(f.is_finite());
-    ///
-    /// assert!(!nan.is_finite());
-    /// assert!(!inf.is_finite());
-    /// assert!(!neg_inf.is_finite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
-
-    /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal][subnormal], or `NaN`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
-    /// let max = f32::MAX;
-    /// let lower_than_min = 1.0e-40_f32;
-    /// let zero = 0.0_f32;
-    ///
-    /// assert!(min.is_normal());
-    /// assert!(max.is_normal());
-    ///
-    /// assert!(!zero.is_normal());
-    /// assert!(!f32::NAN.is_normal());
-    /// assert!(!f32::INFINITY.is_normal());
-    /// // Values between `0` and `min` are Subnormal.
-    /// assert!(!lower_than_min.is_normal());
-    /// ```
-    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    ///
-    /// ```
-    /// use std::num::FpCategory;
-    /// use std::f32;
-    ///
-    /// let num = 12.4_f32;
-    /// let inf = f32::INFINITY;
-    ///
-    /// assert_eq!(num.classify(), FpCategory::Normal);
-    /// assert_eq!(inf.classify(), FpCategory::Infinite);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { num::Float::classify(self) }
+    #[cfg(stage0)]
+    f32_core_methods!();
 
     /// Returns the largest integer less than or equal to a number.
     ///
@@ -257,7 +164,9 @@ pub fn fract(self) -> f32 { self - self.trunc() }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn abs(self) -> f32 { num::Float::abs(self) }
+    pub fn abs(self) -> f32 {
+        unsafe { intrinsics::fabsf32(self) }
+    }
 
     /// Returns a number that represents the sign of `self`.
     ///
@@ -277,35 +186,13 @@ pub fn abs(self) -> f32 { num::Float::abs(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn signum(self) -> f32 { num::Float::signum(self) }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f32;
-    /// let g = -7.0_f32;
-    ///
-    /// assert!(f.is_sign_positive());
-    /// assert!(!g.is_sign_positive());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
-    ///
-    /// ```
-    /// let f = 7.0f32;
-    /// let g = -7.0f32;
-    ///
-    /// assert!(!f.is_sign_negative());
-    /// assert!(g.is_sign_negative());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
+    pub fn signum(self) -> f32 {
+        if self.is_nan() {
+            NAN
+        } else {
+            unsafe { intrinsics::copysignf32(1.0, self) }
+        }
+    }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error. This produces a more accurate result with better performance than
@@ -380,20 +267,6 @@ pub fn mod_euc(self, rhs: f32) -> f32 {
     }
 
 
-    /// Takes the reciprocal (inverse) of a number, `1/x`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let x = 2.0_f32;
-    /// let abs_difference = (x.recip() - (1.0/x)).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn recip(self) -> f32 { num::Float::recip(self) }
-
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
@@ -408,7 +281,9 @@ pub fn recip(self) -> f32 { num::Float::recip(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
+    pub fn powi(self, n: i32) -> f32 {
+        unsafe { intrinsics::powif32(self, n) }
+    }
 
     /// Raises a number to a floating point power.
     ///
@@ -584,68 +459,6 @@ pub fn log10(self) -> f32 {
         return unsafe { intrinsics::log10f32(self) };
     }
 
-    /// Converts radians to degrees.
-    ///
-    /// ```
-    /// use std::f32::{self, consts};
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
-    #[inline]
-    pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
-
-    /// Converts degrees to radians.
-    ///
-    /// ```
-    /// use std::f32::{self, consts};
-    ///
-    /// let angle = 180.0f32;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
-    #[inline]
-    pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
-
-    /// Returns the maximum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0f32;
-    /// let y = 2.0f32;
-    ///
-    /// assert_eq!(x.max(y), y);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn max(self, other: f32) -> f32 {
-        num::Float::max(self, other)
-    }
-
-    /// Returns the minimum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0f32;
-    /// let y = 2.0f32;
-    ///
-    /// assert_eq!(x.min(y), x);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn min(self, other: f32) -> f32 {
-        num::Float::min(self, other)
-    }
-
     /// The positive difference of two numbers.
     ///
     /// * If `self <= other`: `0:0`
@@ -1046,73 +859,6 @@ pub fn acosh(self) -> f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-
-    /// Raw transmutation to `u32`.
-    ///
-    /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
-    ///
-    /// See `from_bits` for some discussion of the portability of this operation
-    /// (there are almost no issues).
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
-    /// assert_eq!((12.5f32).to_bits(), 0x41480000);
-    ///
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn to_bits(self) -> u32 {
-        num::Float::to_bits(self)
-    }
-
-    /// Raw transmutation from `u32`.
-    ///
-    /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
-    /// It turns out this is incredibly portable, for two reasons:
-    ///
-    /// * Floats and Ints have the same endianness on all supported platforms.
-    /// * IEEE-754 very precisely specifies the bit layout of floats.
-    ///
-    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
-    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
-    /// (notably x86 and ARM) picked the interpretation that was ultimately
-    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
-    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
-    ///
-    /// Rather than trying to preserve signaling-ness cross-platform, this
-    /// implementation favours preserving the exact bits. This means that
-    /// any payloads encoded in NaNs will be preserved even if the result of
-    /// this method is sent over the network from an x86 machine to a MIPS one.
-    ///
-    /// If the results of this method are only manipulated by the same
-    /// architecture that produced them, then there is no portability concern.
-    ///
-    /// If the input isn't NaN, then there is no portability concern.
-    ///
-    /// If you don't care about signalingness (very likely), then there is no
-    /// portability concern.
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::f32;
-    /// let v = f32::from_bits(0x41480000);
-    /// let difference = (v - 12.5).abs();
-    /// assert!(difference <= 1e-5);
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn from_bits(v: u32) -> Self {
-        num::Float::from_bits(v)
-    }
 }
 
 #[cfg(test)]
index a9585670ad043d4242de60eab2f1e4071adf702b..a7e63f59b1c67369e8bb1b1009bc950c813b95d7 100644 (file)
 #![allow(missing_docs)]
 
 #[cfg(not(test))]
-use core::num;
+#[cfg(stage0)]
+use core::num::Float;
 #[cfg(not(test))]
 use intrinsics;
 #[cfg(not(test))]
+#[cfg(stage0)]
 use num::FpCategory;
 #[cfg(not(test))]
 use sys::cmath;
 pub use core::f64::consts;
 
 #[cfg(not(test))]
-#[lang = "f64"]
+#[cfg_attr(stage0, lang = "f64")]
+#[cfg_attr(not(stage0), lang = "f64_runtime")]
 impl f64 {
-    /// Returns `true` if this value is `NaN` and false otherwise.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let nan = f64::NAN;
-    /// let f = 7.0_f64;
-    ///
-    /// assert!(nan.is_nan());
-    /// assert!(!f.is_nan());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let f = 7.0f64;
-    /// let inf = f64::INFINITY;
-    /// let neg_inf = f64::NEG_INFINITY;
-    /// let nan = f64::NAN;
-    ///
-    /// assert!(!f.is_infinite());
-    /// assert!(!nan.is_infinite());
-    ///
-    /// assert!(inf.is_infinite());
-    /// assert!(neg_inf.is_infinite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
-
-    /// Returns `true` if this number is neither infinite nor `NaN`.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let f = 7.0f64;
-    /// let inf: f64 = f64::INFINITY;
-    /// let neg_inf: f64 = f64::NEG_INFINITY;
-    /// let nan: f64 = f64::NAN;
-    ///
-    /// assert!(f.is_finite());
-    ///
-    /// assert!(!nan.is_finite());
-    /// assert!(!inf.is_finite());
-    /// assert!(!neg_inf.is_finite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
-
-    /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal][subnormal], or `NaN`.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
-    /// let max = f64::MAX;
-    /// let lower_than_min = 1.0e-308_f64;
-    /// let zero = 0.0f64;
-    ///
-    /// assert!(min.is_normal());
-    /// assert!(max.is_normal());
-    ///
-    /// assert!(!zero.is_normal());
-    /// assert!(!f64::NAN.is_normal());
-    /// assert!(!f64::INFINITY.is_normal());
-    /// // Values between `0` and `min` are Subnormal.
-    /// assert!(!lower_than_min.is_normal());
-    /// ```
-    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    ///
-    /// ```
-    /// use std::num::FpCategory;
-    /// use std::f64;
-    ///
-    /// let num = 12.4_f64;
-    /// let inf = f64::INFINITY;
-    ///
-    /// assert_eq!(num.classify(), FpCategory::Normal);
-    /// assert_eq!(inf.classify(), FpCategory::Infinite);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { num::Float::classify(self) }
+    #[cfg(stage0)]
+    f64_core_methods!();
 
     /// Returns the largest integer less than or equal to a number.
     ///
@@ -235,7 +142,9 @@ pub fn fract(self) -> f64 { self - self.trunc() }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn abs(self) -> f64 { num::Float::abs(self) }
+    pub fn abs(self) -> f64 {
+        unsafe { intrinsics::fabsf64(self) }
+    }
 
     /// Returns a number that represents the sign of `self`.
     ///
@@ -255,45 +164,13 @@ pub fn abs(self) -> f64 { num::Float::abs(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn signum(self) -> f64 { num::Float::signum(self) }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f64;
-    /// let g = -7.0_f64;
-    ///
-    /// assert!(f.is_sign_positive());
-    /// assert!(!g.is_sign_positive());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
-    #[inline]
-    pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f64;
-    /// let g = -7.0_f64;
-    ///
-    /// assert!(!f.is_sign_negative());
-    /// assert!(g.is_sign_negative());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
-    #[inline]
-    pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) }
+    pub fn signum(self) -> f64 {
+        if self.is_nan() {
+            NAN
+        } else {
+            unsafe { intrinsics::copysignf64(1.0, self) }
+        }
+    }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error. This produces a more accurate result with better performance than
@@ -365,18 +242,6 @@ pub fn mod_euc(self, rhs: f64) -> f64 {
         }
     }
 
-    /// Takes the reciprocal (inverse) of a number, `1/x`.
-    ///
-    /// ```
-    /// let x = 2.0_f64;
-    /// let abs_difference = (x.recip() - (1.0/x)).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn recip(self) -> f64 { num::Float::recip(self) }
-
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
@@ -389,7 +254,9 @@ pub fn recip(self) -> f64 { num::Float::recip(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
+    pub fn powi(self, n: i32) -> f64 {
+        unsafe { intrinsics::powif64(self, n) }
+    }
 
     /// Raises a number to a floating point power.
     ///
@@ -535,68 +402,6 @@ pub fn log10(self) -> f64 {
         self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
     }
 
-    /// Converts radians to degrees.
-    ///
-    /// ```
-    /// use std::f64::consts;
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
-
-    /// Converts degrees to radians.
-    ///
-    /// ```
-    /// use std::f64::consts;
-    ///
-    /// let angle = 180.0_f64;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_radians(self) -> f64 { num::Float::to_radians(self) }
-
-    /// Returns the maximum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0_f64;
-    /// let y = 2.0_f64;
-    ///
-    /// assert_eq!(x.max(y), y);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn max(self, other: f64) -> f64 {
-        num::Float::max(self, other)
-    }
-
-    /// Returns the minimum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0_f64;
-    /// let y = 2.0_f64;
-    ///
-    /// assert_eq!(x.min(y), x);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn min(self, other: f64) -> f64 {
-        num::Float::min(self, other)
-    }
-
     /// The positive difference of two numbers.
     ///
     /// * If `self <= other`: `0:0`
@@ -1000,73 +805,6 @@ fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
             }
         }
     }
-
-    /// Raw transmutation to `u64`.
-    ///
-    /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
-    ///
-    /// See `from_bits` for some discussion of the portability of this operation
-    /// (there are almost no issues).
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
-    /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
-    ///
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn to_bits(self) -> u64 {
-        num::Float::to_bits(self)
-    }
-
-    /// Raw transmutation from `u64`.
-    ///
-    /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
-    /// It turns out this is incredibly portable, for two reasons:
-    ///
-    /// * Floats and Ints have the same endianness on all supported platforms.
-    /// * IEEE-754 very precisely specifies the bit layout of floats.
-    ///
-    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
-    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
-    /// (notably x86 and ARM) picked the interpretation that was ultimately
-    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
-    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
-    ///
-    /// Rather than trying to preserve signaling-ness cross-platform, this
-    /// implementation favours preserving the exact bits. This means that
-    /// any payloads encoded in NaNs will be preserved even if the result of
-    /// this method is sent over the network from an x86 machine to a MIPS one.
-    ///
-    /// If the results of this method are only manipulated by the same
-    /// architecture that produced them, then there is no portability concern.
-    ///
-    /// If the input isn't NaN, then there is no portability concern.
-    ///
-    /// If you don't care about signalingness (very likely), then there is no
-    /// portability concern.
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::f64;
-    /// let v = f64::from_bits(0x4029000000000000);
-    /// let difference = (v - 12.5).abs();
-    /// assert!(difference <= 1e-5);
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn from_bits(v: u64) -> Self {
-        num::Float::from_bits(v)
-    }
 }
 
 #[cfg(test)]
index 7520121a8c2900f51506920814679790e61707ff..4850ed0c5be054fac6cd5bfe4771a7520fab1430 100644 (file)
@@ -61,7 +61,7 @@
 /// # Conversions
 ///
 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
-/// the traits which `OsString` implements for conversions from/to native representations.
+/// the traits which `OsString` implements for [conversions] from/to native representations.
 ///
 /// [`OsStr`]: struct.OsStr.html
 /// [`&OsStr`]: struct.OsStr.html
@@ -74,6 +74,7 @@
 /// [`new`]: #method.new
 /// [`push`]: #method.push
 /// [`as_os_str`]: #method.as_os_str
+/// [conversions]: index.html#conversions
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OsString {
@@ -89,7 +90,7 @@ pub struct OsString {
 /// references; the latter are owned strings.
 ///
 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
-/// the traits which `OsStr` implements for conversions from/to native representations.
+/// the traits which `OsStr` implements for [conversions] from/to native representations.
 ///
 /// [`OsString`]: struct.OsString.html
 /// [`&str`]: ../primitive.str.html
index d92a45265493b939f34f08c3737fc2a5cc5a1910..419921931350906e5c9223ace3e19de4d80a63c0 100644 (file)
 //!
 //! Once you are familiar with the contents of the standard library you may
 //! begin to find the verbosity of the prose distracting. At this stage in your
-//! development you may want to press the **[-]** button near the top of the
+//! development you may want to press the `[-]` button near the top of the
 //! page to collapse it into a more skimmable view.
 //!
-//! While you are looking at that **[-]** button also notice the **[src]**
+//! While you are looking at that `[-]` button also notice the `[src]`
 //! button. Rust's API documentation comes with the source code and you are
 //! encouraged to read it. The standard library source is generally high
 //! quality and a peek behind the curtains is often enlightening.
 #![feature(collections_range)]
 #![feature(compiler_builtins_lib)]
 #![feature(const_fn)]
-#![feature(core_float)]
+#![cfg_attr(stage0, feature(core_float))]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
 #![feature(fs_read_write)]
 #![feature(fixed_size_array)]
 #![feature(float_from_str_radix)]
+#![cfg_attr(stage0, feature(float_internals))]
 #![feature(fn_traits)]
 #![feature(fnbox)]
 #![cfg_attr(stage0, feature(generic_param_attrs))]
 #![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
-#![feature(nonnull_cast)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(nonzero)]
 #![feature(num_bits_bytes)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(rustc_attrs)]
+#![feature(std_internals)]
 #![feature(stdsimd)]
 #![feature(shrink_to)]
 #![feature(slice_bytes)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
+#![feature(try_from)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(doc_spotlight)]
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
+#![feature(doc_alias)]
 
 #![default_lib_allocator]
 
 pub mod process;
 pub mod sync;
 pub mod time;
-pub mod alloc;
 
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
@@ -494,6 +497,8 @@ pub mod heap {
 mod sys_common;
 mod sys;
 
+pub mod alloc;
+
 // Private support modules
 mod panicking;
 mod memchr;
@@ -527,7 +532,7 @@ mod coresimd {
 #[unstable(feature = "stdsimd", issue = "48556")]
 #[cfg(all(not(stage0), not(test)))]
 pub use stdsimd::simd;
-#[unstable(feature = "stdsimd", issue = "48556")]
+#[stable(feature = "simd_arch", since = "1.27.0")]
 #[cfg(all(not(stage0), not(test)))]
 pub use stdsimd::arch;
 
index 5ef7c15965505df76be13fe25edf6f41eb2af87e..6902ec82047d73094259a93eccd16f401cebe179 100644 (file)
@@ -787,13 +787,13 @@ macro_rules! assert {
     }
 }
 
-/// A macro for defining #[cfg] if-else statements.
+/// A macro for defining `#[cfg]` if-else statements.
 ///
 /// This is similar to the `if/elif` C preprocessor macro by allowing definition
 /// of a cascade of `#[cfg]` cases, emitting the implementation which matches
 /// first.
 ///
-/// This allows you to conveniently provide a long list #[cfg]'d blocks of code
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
 /// without having to rewrite each clause multiple times.
 macro_rules! cfg_if {
     ($(
index a51b46559859e67a2d514ca42c2b7a8d77a3a80a..5899dc688e22563bc69dd709f0224dc696b7c9bd 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::android::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index e4f1c9432f3f08f4cc60859c5b6a968330f5f021..24caf326ab0fd2dba4b6cf69242d2f675667c296 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::bitrig::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index db672e5643531181fb59b0759274cc81d74c7e50..6aea450774ffd39d9bb48a3dc04b1386604f09fb 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::dragonfly::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 8056ce4fdc4ee4ba02365682be02ff5f5000acce..e0e197dc122a1d2aaa9f36e02b67d7a0ad30d64f 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::emscripten::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 2f17d2f7409434c568887478bbafaefc2ec702c5..5f24cd636d541ab75611244212d9f86a1ba712f3 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::freebsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index d22f9a628bd1733e7c929546f5f772d66e29cd10..16802576356d192b24d762642d10c6d1c735da52 100644 (file)
@@ -13,7 +13,9 @@
 use fs::Metadata;
 use sys_common::AsInner;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
index 54f8ea1b71b3effa9556cb0cc6672b95579831d0..453136e0ac864afe4cf42f0a875d20ec2e90fb65 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::haiku::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 275daf3d3a0ac5f842c4e6d3db52f07447e01d62..296ce69ff43620e7f0aa70b01879f01ba1362cf3 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::ios::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 2be2fbcb2dbf75900627347081d556cb9754f538..76fb10da850b16b4044cd86fdfc4284d970dea53 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::linux::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 12b44901d03d93b6bb468e205c944b310cb09d6c..0b14c05cb5519bffbaf6481ece1af64d52ae18df 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::macos::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index cd7d5fafd1c85d82afcc92a79bd13bf37d8eedcf..e9cad33fee61d7fceea55e767dff2e1f6081b832 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::netbsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index cc812fcf12cfe5f9061694ff787a871cf584810c..0f6b83b6e324b56cf8e2f68d907fd4093ac279a9 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::openbsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 5dc43d03a866347e82c556fd45723ed80ab5460c..19dce1ba34c76c98482094cec0ea0ccc117bbf22 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::solaris::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index fba3269204e90e10dbe32bab39be95c5db9d47e2..24eae6a4c821e1db50005be285519f85510a2eb3 100644 (file)
@@ -17,6 +17,8 @@
 //! * Executing a panic up to doing the actual implementation
 //! * Shims around "try"
 
+use core::panic::BoxMeUp;
+
 use io::prelude::*;
 
 use any::Any;
@@ -27,7 +29,7 @@
 use mem;
 use ptr;
 use raw;
-use sys::stdio::Stderr;
+use sys::stdio::{Stderr, stderr_prints_nothing};
 use sys_common::rwlock::RWLock;
 use sys_common::thread_info;
 use sys_common::util;
@@ -56,7 +58,7 @@ fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                 data_ptr: *mut usize,
                                 vtable_ptr: *mut usize) -> u32;
     #[unwind(allowed)]
-    fn __rust_start_panic(data: usize, vtable: usize) -> u32;
+    fn __rust_start_panic(payload: usize) -> u32;
 }
 
 #[derive(Copy, Clone)]
@@ -177,9 +179,6 @@ fn default_hook(info: &PanicInfo) {
     };
 
     let location = info.location().unwrap();  // The current implementation always returns Some
-    let file = location.file();
-    let line = location.line();
-    let col = location.column();
 
     let msg = match info.payload().downcast_ref::<&'static str>() {
         Some(s) => *s,
@@ -193,8 +192,8 @@ fn default_hook(info: &PanicInfo) {
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
     let write = |err: &mut ::io::Write| {
-        let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}:{}",
-                         name, msg, file, line, col);
+        let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
+                         name, msg, location);
 
         #[cfg(feature = "backtrace")]
         {
@@ -212,15 +211,15 @@ fn default_hook(info: &PanicInfo) {
 
     let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
     match (prev, err.as_mut()) {
-        (Some(mut stderr), _) => {
-            write(&mut *stderr);
-            let mut s = Some(stderr);
-            LOCAL_STDERR.with(|slot| {
-                *slot.borrow_mut() = s.take();
-            });
-        }
-        (None, Some(ref mut err)) => { write(err) }
-        _ => {}
+       (Some(mut stderr), _) => {
+           write(&mut *stderr);
+           let mut s = Some(stderr);
+           LOCAL_STDERR.with(|slot| {
+               *slot.borrow_mut() = s.take();
+           });
+       }
+       (None, Some(ref mut err)) => { write(err) }
+       _ => {}
     }
 }
 
@@ -342,9 +341,38 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
     // panic + OOM properly anyway (see comment in begin_panic
     // below).
 
-    let mut s = String::new();
-    let _ = s.write_fmt(*msg);
-    rust_panic_with_hook(Box::new(s), Some(msg), file_line_col)
+    rust_panic_with_hook(&mut PanicPayload::new(msg), Some(msg), file_line_col);
+
+    struct PanicPayload<'a> {
+        inner: &'a fmt::Arguments<'a>,
+        string: Option<String>,
+    }
+
+    impl<'a> PanicPayload<'a> {
+        fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
+            PanicPayload { inner, string: None }
+        }
+
+        fn fill(&mut self) -> &mut String {
+            let inner = self.inner;
+            self.string.get_or_insert_with(|| {
+                let mut s = String::new();
+                drop(s.write_fmt(*inner));
+                s
+            })
+        }
+    }
+
+    unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
+        fn box_me_up(&mut self) -> *mut (Any + Send) {
+            let contents = mem::replace(self.fill(), String::new());
+            Box::into_raw(Box::new(contents))
+        }
+
+        fn get(&mut self) -> &(Any + Send) {
+            self.fill()
+        }
+    }
 }
 
 /// This is the entry point of panicking for panic!() and assert!().
@@ -360,18 +388,42 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
     // be performed in the parent of this thread instead of the thread that's
     // panicking.
 
-    rust_panic_with_hook(Box::new(msg), None, file_line_col)
+    rust_panic_with_hook(&mut PanicPayload::new(msg), None, file_line_col);
+
+    struct PanicPayload<A> {
+        inner: Option<A>,
+    }
+
+    impl<A: Send + 'static> PanicPayload<A> {
+        fn new(inner: A) -> PanicPayload<A> {
+            PanicPayload { inner: Some(inner) }
+        }
+    }
+
+    unsafe impl<A: Send + 'static> BoxMeUp for PanicPayload<A> {
+        fn box_me_up(&mut self) -> *mut (Any + Send) {
+            let data = match self.inner.take() {
+                Some(a) => Box::new(a) as Box<Any + Send>,
+                None => Box::new(()),
+            };
+            Box::into_raw(data)
+        }
+
+        fn get(&mut self) -> &(Any + Send) {
+            match self.inner {
+                Some(ref a) => a,
+                None => &(),
+            }
+        }
+    }
 }
 
-/// Executes the primary logic for a panic, including checking for recursive
-/// panics and panic hooks.
+/// Central point for dispatching panics.
 ///
-/// This is the entry point or panics from libcore, formatted panics, and
-/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
-/// run panic hooks, and then delegate to the actual implementation of panics.
-#[inline(never)]
-#[cold]
-fn rust_panic_with_hook(payload: Box<Any + Send>,
+/// Executes the primary logic for a panic, including checking for recursive
+/// panics, panic hooks, and finally dispatching to the panic runtime to either
+/// abort or unwind.
+fn rust_panic_with_hook(payload: &mut BoxMeUp,
                         message: Option<&fmt::Arguments>,
                         file_line_col: &(&'static str, u32, u32)) -> ! {
     let (file, line, col) = *file_line_col;
@@ -390,15 +442,24 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
     }
 
     unsafe {
-        let info = PanicInfo::internal_constructor(
-            &*payload,
+        let mut info = PanicInfo::internal_constructor(
             message,
             Location::internal_constructor(file, line, col),
         );
         HOOK_LOCK.read();
         match HOOK {
-            Hook::Default => default_hook(&info),
-            Hook::Custom(ptr) => (*ptr)(&info),
+            // Some platforms know that printing to stderr won't ever actually
+            // print anything, and if that's the case we can skip the default
+            // hook.
+            Hook::Default if stderr_prints_nothing() => {}
+            Hook::Default => {
+                info.set_payload(payload.get());
+                default_hook(&info);
+            }
+            Hook::Custom(ptr) => {
+                info.set_payload(payload.get());
+                (*ptr)(&info);
+            }
         }
         HOOK_LOCK.read_unlock();
     }
@@ -419,16 +480,29 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
 /// Shim around rust_panic. Called by resume_unwind.
 pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
     update_panic_count(1);
-    rust_panic(msg)
+
+    struct RewrapBox(Box<Any + Send>);
+
+    unsafe impl BoxMeUp for RewrapBox {
+        fn box_me_up(&mut self) -> *mut (Any + Send) {
+            Box::into_raw(mem::replace(&mut self.0, Box::new(())))
+        }
+
+        fn get(&mut self) -> &(Any + Send) {
+            &*self.0
+        }
+    }
+
+    rust_panic(&mut RewrapBox(msg))
 }
 
 /// A private no-mangle function on which to slap yer breakpoints.
 #[no_mangle]
 #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
-pub fn rust_panic(msg: Box<Any + Send>) -> ! {
+pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! {
     let code = unsafe {
-        let obj = mem::transmute::<_, raw::TraitObject>(msg);
-        __rust_start_panic(obj.data as usize, obj.vtable as usize)
+        let obj = &mut msg as *mut &mut BoxMeUp;
+        __rust_start_panic(obj as usize)
     };
     rtabort!("failed to initiate panic, error {}", code)
 }
index ec96157547383daa4cbad54658beb78a602fd7bd..955a6af1ae67eaac5a78975499cf329658003667 100644 (file)
@@ -298,10 +298,9 @@ pub fn is_separator(c: char) -> bool {
 // Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
 // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
 // `iter` after having exhausted `prefix`.
-fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
-    where I: Iterator<Item = A> + Clone,
-          J: Iterator<Item = A>,
-          A: PartialEq
+fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
+    where I: Iterator<Item = Component<'a>> + Clone,
+          J: Iterator<Item = Component<'b>>,
 {
     loop {
         let mut iter_next = iter.clone();
@@ -1967,7 +1966,7 @@ pub fn file_name(&self) -> Option<&OsStr> {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
+    /// use std::path::{Path, PathBuf};
     ///
     /// let path = Path::new("/test/haha/foo.txt");
     ///
@@ -1978,17 +1977,20 @@ pub fn file_name(&self) -> Option<&OsStr> {
     /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
     /// assert_eq!(path.strip_prefix("test").is_ok(), false);
     /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
+    ///
+    /// let prefix = PathBuf::from("/test/");
+    /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
     /// ```
     #[stable(since = "1.7.0", feature = "path_strip_prefix")]
-    pub fn strip_prefix<'a, P: ?Sized>(&'a self, base: &'a P)
-                                       -> Result<&'a Path, StripPrefixError>
+    pub fn strip_prefix<P>(&self, base: P)
+                           -> Result<&Path, StripPrefixError>
         where P: AsRef<Path>
     {
         self._strip_prefix(base.as_ref())
     }
 
-    fn _strip_prefix<'a>(&'a self, base: &'a Path)
-                         -> Result<&'a Path, StripPrefixError> {
+    fn _strip_prefix(&self, base: &Path)
+                     -> Result<&Path, StripPrefixError> {
         iter_after(self.components(), base.components())
             .map(|c| c.as_path())
             .ok_or(StripPrefixError(()))
index ce4bbfffc2e47b0644c11821f7f7e41eba69c79f..919d964829718f0c0653e88086137a579bb317bf 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #[doc(primitive = "bool")]
+#[doc(alias = "true")]
+#[doc(alias = "false")]
 //
 /// The boolean type.
 ///
@@ -68,6 +70,7 @@
 mod prim_bool { }
 
 #[doc(primitive = "never")]
+#[doc(alias = "!")]
 //
 /// The `!` type, also called "never".
 ///
@@ -79,6 +82,7 @@ mod prim_bool { }
 /// write:
 ///
 /// ```
+/// #![feature(never_type)]
 /// # fn foo() -> u32 {
 /// let x: ! = {
 ///     return 123
@@ -155,6 +159,7 @@ mod prim_bool { }
 /// for example:
 ///
 /// ```
+/// #![feature(never_type)]
 /// # use std::fmt;
 /// # trait Debug {
 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
@@ -499,6 +504,9 @@ mod prim_pointer { }
 mod prim_array { }
 
 #[doc(primitive = "slice")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
 //
 /// A dynamically-sized view into a contiguous sequence, `[T]`.
 ///
@@ -597,6 +605,9 @@ mod prim_slice { }
 mod prim_str { }
 
 #[doc(primitive = "tuple")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
 //
 /// A finite heterogeneous sequence, `(T, U, ..)`.
 ///
@@ -819,6 +830,7 @@ mod prim_isize { }
 mod prim_usize { }
 
 #[doc(primitive = "reference")]
+#[doc(alias = "&")]
 //
 /// References, both shared and mutable.
 ///
index 92f0406c09bb5c752170212e06fe94effebd306a..00051d4487a214eac90bef8a089468bea345b835 100644 (file)
@@ -1121,8 +1121,13 @@ impl ExitCode {
 }
 
 impl Child {
-    /// Forces the child to exit. This is equivalent to sending a
-    /// SIGKILL on unix platforms.
+    /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
+    /// error is returned.
+    ///
+    /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function,
+    /// especially the [`Other`] kind might change to more specific kinds in the future.
+    ///
+    /// This is equivalent to sending a SIGKILL on Unix platforms.
     ///
     /// # Examples
     ///
@@ -1138,6 +1143,10 @@ impl Child {
     ///     println!("yes command didn't start");
     /// }
     /// ```
+    ///
+    /// [`ErrorKind`]: ../io/enum.ErrorKind.html
+    /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
+    /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
     #[stable(feature = "process", since = "1.0.0")]
     pub fn kill(&mut self) -> io::Result<()> {
         self.handle.kill()
index 9519a926471085f92e64217c60a6bb21c5b977e9..1d7344f921c9d564d30bac0c09f86bcf7b682995 100644 (file)
@@ -77,3 +77,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
index d59b4fc0b70b8032a961d9123da86e7b5c2276ac..cd88c8f46b3c0c6b3ef78a0342306b7b6a0642a9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extension to the primitives in the `std::ffi` module
+//! Redox-specific extension to the primitives in the `std::ffi` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -17,7 +17,9 @@
 use sys::os_str::Buf;
 use sys_common::{FromInner, IntoInner, AsInner};
 
-/// Unix-specific extensions to `OsString`.
+/// Redox-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a byte vector.
@@ -39,7 +41,9 @@ fn into_vec(self) -> Vec<u8> {
     }
 }
 
-/// Unix-specific extensions to `OsStr`.
+/// Redox-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     #[stable(feature = "rust1", since = "1.0.0")]
index 0f4762aa8810a901490f828bb4975a51e470ec91..c1dba6edda484f66e6f702555d91ce372166f826 100644 (file)
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{FromInner, AsInner, AsInnerMut};
 
-/// Redox-specific extensions to `Permissions`
+/// Redox-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `mode_t` bits that are the standard Redox
@@ -95,7 +97,9 @@ fn from_mode(mode: u32) -> Permissions {
     }
 }
 
-/// Redox-specific extensions to `OpenOptions`
+/// Redox-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -163,13 +167,9 @@ fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
     }
 }
 
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
+/// Redox-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -204,6 +204,13 @@ pub trait MetadataExt {
     fn blocks(&self) -> u64;
 }
 
+// Hm, why are there casts here to the returned type, shouldn't the types always
+// be the same? Right you are! Turns out, however, on android at least the types
+// in the raw `stat` structure are not the same as the types being returned. Who
+// knew!
+//
+// As a result to make sure this compiles for all platforms we do the manual
+// casts and rely on manual lowering to `stat` if the raw type is desired.
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 impl MetadataExt for fs::Metadata {
     fn dev(&self) -> u64 {
@@ -253,7 +260,12 @@ fn blocks(&self) -> u64 {
     }
 }
 
-/// Add special Redox types (block/char device, fifo and socket)
+/// Redox-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
@@ -307,8 +319,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
     sys::fs::symlink(src.as_ref(), dst.as_ref())
 }
 
+/// Redox-specific extensions to [`fs::DirBuilder`].
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 #[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for Redox-specific options.
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
index e68e180acf1c4cdf9a3c3dd5785c20e30af33ee3..cfb6d5fc703a614ef84e1c2b363ed8d7bb8b48c5 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extensions to primitives in the `std::process` module.
+//! Redox-specific extensions to primitives in the `std::process` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Unix-specific extensions to the `std::process::Command` builder
+/// Redox-specific extensions to the [`process::Command`] builder,
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user id. This translates to a
@@ -107,7 +109,9 @@ fn exec(&mut self) -> io::Error {
     }
 }
 
-/// Unix-specific extensions to `std::process::ExitStatus`
+/// Redox-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
index 52be2ccd9f964b43906c8e935018555cba131760..71ff0d46b91e31f8553689730f1ccc9d2a519e7b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extensions to primitives in the `std::thread` module.
+//! Redox-specific extensions to primitives in the `std::thread` module.
 
 #![stable(feature = "thread_extensions", since = "1.9.0")]
 
@@ -19,7 +19,9 @@
 #[allow(deprecated)]
 pub type RawPthread = usize;
 
-/// Unix-specific extensions to `std::thread::JoinHandle`
+/// Redox-specific extensions to [`thread::JoinHandle`].
+///
+/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 pub trait JoinHandleExt {
     /// Extracts the raw pthread_t without taking ownership
index 3abb094ac34e3d98af5855f15bbb96f7e63d0982..7a4d11b0ecb9a8c64f2845898755d6883608544e 100644 (file)
@@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
index fb9984ccbdda5f63444ead83602afbe6e3f384a3..8347145db5aaf493a9c8ad3cf379415c5897a5bd 100644 (file)
@@ -17,7 +17,9 @@
 use sys::os_str::Buf;
 use sys_common::{FromInner, IntoInner, AsInner};
 
-/// Unix-specific extensions to `OsString`.
+/// Unix-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an [`OsString`] from a byte vector.
@@ -66,7 +68,9 @@ fn into_vec(self) -> Vec<u8> {
     }
 }
 
-/// Unix-specific extensions to `OsStr`.
+/// Unix-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     #[stable(feature = "rust1", since = "1.0.0")]
index 3c5b9424fb06ea1688409166891d0356e686d406..4e981012669033ff393d85a44f1511bab82df6a0 100644 (file)
@@ -105,7 +105,9 @@ fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
     }
 }
 
-/// Unix-specific extensions to `Permissions`
+/// Unix-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `st_mode` bits that contain the standard
@@ -180,7 +182,9 @@ fn from_mode(mode: u32) -> Permissions {
     }
 }
 
-/// Unix-specific extensions to `OpenOptions`
+/// Unix-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -246,13 +250,9 @@ fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
     }
 }
 
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
+/// Unix-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Returns the ID of the device containing the file.
@@ -555,7 +555,12 @@ fn blksize(&self) -> u64 { self.st_blksize() }
     fn blocks(&self) -> u64 { self.st_blocks() }
 }
 
-/// Add support for special unix types (block/char device, fifo and socket).
+/// Unix-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
@@ -701,10 +706,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
     sys::fs::symlink(src.as_ref(), dst.as_ref())
 }
 
-#[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+/// Unix-specific extensions to [`fs::DirBuilder`].
 ///
 /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
+#[stable(feature = "dir_builder", since = "1.6.0")]
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
index 7b4ec20d91fb46e80a014cf95b25012f8c816cbf..21630ae9746fcdcca4aa3a4fe97a1e77fa551600 100644 (file)
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Unix-specific extensions to the `std::process::Command` builder
+/// Unix-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user id. This translates to a
@@ -117,7 +119,9 @@ fn exec(&mut self) -> io::Error {
     }
 }
 
-/// Unix-specific extensions to `std::process::ExitStatus`
+/// Unix-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
index fe2a48764dc3a99799373cf3f0878a8b61d6dca7..8dadf29945c1a816a217cfb12f0634bb4189acf5 100644 (file)
@@ -21,7 +21,9 @@
 #[allow(deprecated)]
 pub type RawPthread = pthread_t;
 
-/// Unix-specific extensions to `std::thread::JoinHandle`
+/// Unix-specific extensions to [`thread::JoinHandle`].
+///
+/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 pub trait JoinHandleExt {
     /// Extracts the raw pthread_t without taking ownership
index 9bdea945ea42eacf52a993f91f6912bcbb675a08..c1298e5040dbeec35b3a503c17d1aa2e4aa961c8 100644 (file)
@@ -80,11 +80,11 @@ pub fn init() {
         reset_sigpipe();
     }
 
-    #[cfg(not(any(target_os = "emscripten", target_os="fuchsia")))]
+    #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
     unsafe fn reset_sigpipe() {
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
-    #[cfg(any(target_os = "emscripten", target_os="fuchsia"))]
+    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))]
     unsafe fn reset_sigpipe() {}
 }
 
index e9b3d4affc7dd6fcb92505e96a99879529676a68..87ba2aef4f1d3dfe1e499f089b55adc4e6df5bba 100644 (file)
@@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
index 8b06f54167487dd6cd38955b5b567efa2d24ed10..6516010af475940f0d2f6cc0c8209db0a5cd4f76 100644 (file)
@@ -30,7 +30,7 @@ pub unsafe fn read(&self) {
         if *mode >= 0 {
             *mode += 1;
         } else {
-            panic!("rwlock locked for writing");
+            rtabort!("rwlock locked for writing");
         }
     }
 
@@ -51,7 +51,7 @@ pub unsafe fn write(&self) {
         if *mode == 0 {
             *mode = -1;
         } else {
-            panic!("rwlock locked for reading")
+            rtabort!("rwlock locked for reading")
         }
     }
 
index beb19c0ed2c1f62bd17b1611db911eb9a04eb7af..023f29576a27d9c4dd667b1a035d9966de5efcfe 100644 (file)
@@ -69,3 +69,7 @@ fn flush(&mut self) -> io::Result<()> {
 pub fn is_ebadf(_err: &io::Error) -> bool {
     true
 }
+
+pub fn stderr_prints_nothing() -> bool {
+    !cfg!(feature = "wasm_syscall")
+}
index d6b8896ac096d2e8caf3594a9b6459dfae69e8cb..98d4355248990a92ec748b667409e91b1e5a1f2d 100644 (file)
@@ -76,7 +76,9 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use sys_common::wtf8::EncodeWide;
 
-/// Windows-specific extensions to `OsString`.
+/// Windows-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
@@ -109,7 +111,9 @@ fn from_wide(wide: &[u16]) -> OsString {
     }
 }
 
-/// Windows-specific extensions to `OsStr`.
+/// Windows-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially
index e5cd51b6550b161a78902784aac8dc043debc39d..78c9e95a05501d0821602ab330ecc8cde75ff178 100644 (file)
@@ -103,9 +103,9 @@ fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
     }
 }
 
-/// Windows-specific extensions to [`OpenOptions`].
+/// Windows-specific extensions to [`fs::OpenOptions`].
 ///
-/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
@@ -281,13 +281,12 @@ fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
     }
 }
 
-/// Extension methods for [`fs::Metadata`] to access the raw fields contained
-/// within.
+/// Windows-specific extensions to [`fs::Metadata`].
 ///
 /// The data members that this trait exposes correspond to the members
 /// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
 ///
-/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 /// [`BY_HANDLE_FILE_INFORMATION`]:
 ///     https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -445,8 +444,11 @@ fn last_write_time(&self) -> u64 { self.as_inner().modified_u64() }
     fn file_size(&self) -> u64 { self.as_inner().size() }
 }
 
-/// Add support for the Windows specific fact that a symbolic link knows whether it is a file
-/// or directory.
+/// Windows-specific extensions to [`FileType`].
+///
+/// On Windows, a symbolic link knows whether it is a file or directory.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[unstable(feature = "windows_file_type_ext", issue = "0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a symbolic link that is also a directory.
index 759f055c4b1236e4640982e21d4be19fd15b7155..a02bcbe0c87c259ad599c2e0d2dbb2b973fe73fd 100644 (file)
@@ -82,7 +82,9 @@ fn into_raw_handle(self) -> RawHandle {
     }
 }
 
-/// Windows-specific extensions to `std::process::ExitStatus`
+/// Windows-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "exit_status_from", since = "1.12.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
@@ -98,7 +100,9 @@ fn from_raw(raw: u32) -> Self {
     }
 }
 
-/// Windows-specific extensions to the `std::process::Command` builder
+/// Windows-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
     /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
index 855603685905958de4bf5494a677bc4bc23e4497..9bf9f749d4df252c89182265ccb7fc3d80290631 100644 (file)
@@ -117,7 +117,7 @@ unsafe fn remutex(&self) -> *mut ReentrantMutex {
             0 => {}
             n => return n as *mut _,
         }
-        let mut re = Box::new(ReentrantMutex::uninitialized());
+        let mut re = box ReentrantMutex::uninitialized();
         re.init();
         let re = Box::into_raw(re);
         match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) {
index b43df20bddd087144faa8b3626de5a72efed7e67..81b89da21d3c60f0cf9d1574932e48403a12cc83 100644 (file)
@@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 // idea is that on windows we use a slightly smaller buffer that's
 // been seen to be acceptable.
 pub const STDIN_BUF_SIZE: usize = 8 * 1024;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
index 1955f3ec9a28fc98f129e9341c0289ae948bedf8..20109d2d0d5aceb5790c6d063c7c6d9b331e72eb 100644 (file)
@@ -139,10 +139,10 @@ pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
 /// Controls how the backtrace should be formatted.
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum PrintFormat {
-    /// Show all the frames with absolute path for files.
-    Full = 2,
     /// Show only relevant data from the backtrace.
-    Short = 3,
+    Short = 2,
+    /// Show all the frames with absolute path for files.
+    Full = 3,
 }
 
 // For now logging is turned off by default, and this function checks to see
@@ -150,11 +150,10 @@ pub enum PrintFormat {
 pub fn log_enabled() -> Option<PrintFormat> {
     static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
     match ENABLED.load(Ordering::SeqCst) {
-        0 => {},
+        0 => {}
         1 => return None,
-        2 => return Some(PrintFormat::Full),
-        3 => return Some(PrintFormat::Short),
-        _ => unreachable!(),
+        2 => return Some(PrintFormat::Short),
+        _ => return Some(PrintFormat::Full),
     }
 
     let val = match env::var_os("RUST_BACKTRACE") {
index 27504d374ddbfaba19cb09ea52ba382aae13919b..d0c4d6a773746e70cc175de3a0866085532d6609 100644 (file)
 use sync::Once;
 use sys;
 
+macro_rules! rtabort {
+    ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
+}
+
+macro_rules! rtassert {
+    ($e:expr) => (if !$e {
+        rtabort!(concat!("assertion failed: ", stringify!($e)));
+    })
+}
+
 pub mod at_exit_imp;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
@@ -101,10 +111,6 @@ pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
     if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
 }
 
-macro_rules! rtabort {
-    ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
-}
-
 /// One-time runtime cleanup.
 pub fn cleanup() {
     static CLEANUP: Once = Once::new();
index a4aa3d96d25c00f5c399236b2e0275b595fc6ac0..d0d6224de0a151376ab1e8407a9c68766c52399a 100644 (file)
@@ -169,7 +169,7 @@ unsafe fn lazy_init(&self) -> usize {
                 self.key.store(key, Ordering::SeqCst);
             }
             INIT_LOCK.unlock();
-            assert!(key != 0);
+            rtassert!(key != 0);
             return key
         }
 
@@ -190,7 +190,7 @@ unsafe fn lazy_init(&self) -> usize {
             imp::destroy(key1);
             key2
         };
-        assert!(key != 0);
+        rtassert!(key != 0);
         match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
             // The CAS succeeded, so we've created the actual key
             0 => key as usize,
index a391c7cc6ef0c959c2e25eaf0bddf175cbb59cec..a373e980b970d21263aa8389ddece4cb26442365 100644 (file)
 
 use fmt;
 use io::prelude::*;
-use sys::stdio::Stderr;
+use sys::stdio::{Stderr, stderr_prints_nothing};
 use thread;
 
 pub fn dumb_print(args: fmt::Arguments) {
+    if stderr_prints_nothing() {
+        return
+    }
     let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
 }
 
index dda4e1bab3b42f2b916de2ca7c2379443c2b78e4..fe7e058091ed5fe1c6cf871817f879892f5ead2d 100644 (file)
@@ -876,21 +876,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 }
 
 impl Wtf8 {
-    pub fn is_ascii(&self) -> bool {
-        self.bytes.is_ascii()
-    }
-    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
-    }
-    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
-    }
-    pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
-        self.bytes.eq_ignore_ascii_case(&other.bytes)
-    }
-
     pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
-    pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
 }
 
 #[cfg(test)]
index 99479bc56eff30ed9388c04d14168ed90174f331..40d3280baa687da385fe43d2f36b52962f67ffc7 100644 (file)
@@ -172,12 +172,16 @@ unsafe fn __getit() -> $crate::option::Option<
                 &'static $crate::cell::UnsafeCell<
                     $crate::option::Option<$t>>>
             {
+                #[cfg(target_arch = "wasm32")]
+                static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
+                    $crate::thread::__StaticLocalKeyInner::new();
+
                 #[thread_local]
-                #[cfg(target_thread_local)]
+                #[cfg(all(target_thread_local, not(target_arch = "wasm32")))]
                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
                     $crate::thread::__FastLocalKeyInner::new();
 
-                #[cfg(not(target_thread_local))]
+                #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))]
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
 
@@ -295,6 +299,39 @@ pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
     }
 }
 
+/// On some platforms like wasm32 there's no threads, so no need to generate
+/// thread locals and we can instead just use plain statics!
+#[doc(hidden)]
+#[cfg(target_arch = "wasm32")]
+pub mod statik {
+    use cell::UnsafeCell;
+    use fmt;
+
+    pub struct Key<T> {
+        inner: UnsafeCell<Option<T>>,
+    }
+
+    unsafe impl<T> ::marker::Sync for Key<T> { }
+
+    impl<T> fmt::Debug for Key<T> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            f.pad("Key { .. }")
+        }
+    }
+
+    impl<T> Key<T> {
+        pub const fn new() -> Key<T> {
+            Key {
+                inner: UnsafeCell::new(None),
+            }
+        }
+
+        pub unsafe fn get(&self) -> Option<&'static UnsafeCell<Option<T>>> {
+            Some(&*(&self.inner as *const _))
+        }
+    }
+}
+
 #[doc(hidden)]
 #[cfg(target_thread_local)]
 pub mod fast {
index 71aee673cfe3ee57e7893a54c1e1823493713693..1b976b79b4c989f8cc63f9470faec10bae0e8c30 100644 (file)
 // where fast TLS was not available; end-user code is compiled with fast TLS
 // where available, but both are needed.
 
+#[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[cfg(target_arch = "wasm32")]
+#[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[cfg(target_thread_local)]
 #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner;
index 91c9a1524e1442274235a80e90a0533abe67fa32..4e3ee24146844aeaa390c58125dc3e78f8022998 100644 (file)
@@ -1255,8 +1255,8 @@ pub enum StrStyle {
     Cooked,
     /// A raw string, like `r##"foo"##`
     ///
-    /// The uint is the number of `#` symbols used
-    Raw(usize)
+    /// The value is the number of `#` symbols used.
+    Raw(u16)
 }
 
 /// A literal
index e579fc74b42661753386440869b2bc0ac16c213d..3fc1c279f5a22ea971f55be431a2df2a0820e8b2 100644 (file)
@@ -24,20 +24,19 @@ pub enum Edition {
 
     // when adding new editions, be sure to update:
     //
-    // - the list in the `parse_edition` static in librustc::session::config
+    // - Update the `ALL_EDITIONS` const
+    // - Update the EDITION_NAME_LIST const
     // - add a `rust_####()` function to the session
     // - update the enum in Cargo's sources as well
-    //
-    // When -Zedition becomes --edition, there will
-    // also be a check for the edition being nightly-only
-    // somewhere. That will need to be updated
-    // whenever we're stabilizing/introducing a new edition
-    // as well as changing the default Cargo template.
 }
 
 // must be in order from oldest to newest
 pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
 
+pub const EDITION_NAME_LIST: &'static str = "2015|2018";
+
+pub const DEFAULT_EDITION: Edition = Edition::Edition2015;
+
 impl fmt::Display for Edition {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let s = match *self {
@@ -62,6 +61,13 @@ pub fn feature_name(&self) -> &'static str {
             Edition::Edition2018 => "rust_2018_preview",
         }
     }
+
+    pub fn is_stable(&self) -> bool {
+        match *self {
+            Edition::Edition2015 => true,
+            Edition::Edition2018 => false,
+        }
+    }
 }
 
 impl FromStr for Edition {
index 36244f0a3c43874df3b5f637be258a43ac155f0b..a9f483422434af8c3bac19d9cb06abd894779539 100644 (file)
@@ -139,6 +139,7 @@ fn expr_struct_ident(&self, span: Span, id: ast::Ident,
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr>;
     fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr>;
     fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr>;
+    fn expr_u16(&self, sp: Span, u: u16) -> P<ast::Expr>;
     fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr>;
     fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr>;
 
@@ -708,6 +709,10 @@ fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitKind::Int(u as u128,
                                             ast::LitIntType::Unsigned(ast::UintTy::U32)))
     }
+    fn expr_u16(&self, sp: Span, u: u16) -> P<ast::Expr> {
+        self.expr_lit(sp, ast::LitKind::Int(u as u128,
+                                            ast::LitIntType::Unsigned(ast::UintTy::U16)))
+    }
     fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U8)))
     }
index 678c20402d6f47aab78e99f35b0234f61d2846eb..1434e5fddeab0eb1a4ce422541fb1287d46a3198 100644 (file)
@@ -514,6 +514,7 @@ fn expand_attr_invoc(&mut self,
                 Some(kind.expect_from_annotatables(items))
             }
             AttrProcMacro(ref mac) => {
+                self.gate_proc_macro_attr_item(attr.span, &item);
                 let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                     Annotatable::Item(item) => token::NtItem(item),
                     Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
@@ -522,7 +523,8 @@ fn expand_attr_invoc(&mut self,
                     Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                     Annotatable::Expr(expr) => token::NtExpr(expr),
                 })).into();
-                let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok);
+                let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
+                let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
                 self.parse_expansion(tok_result, kind, &attr.path, attr.span)
             }
             ProcMacroDerive(..) | BuiltinDerive(..) => {
@@ -539,6 +541,49 @@ fn expand_attr_invoc(&mut self,
         }
     }
 
+    fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream {
+        let mut trees = tokens.trees();
+        match trees.next() {
+            Some(TokenTree::Delimited(_, delim)) => {
+                if trees.next().is_none() {
+                    return delim.tts.into()
+                }
+            }
+            Some(TokenTree::Token(..)) => {}
+            None => return TokenStream::empty(),
+        }
+        self.cx.span_err(span, "custom attribute invocations must be \
+            of the form #[foo] or #[foo(..)], the macro name must only be \
+            followed by a delimiter token");
+        TokenStream::empty()
+    }
+
+    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
+        let (kind, gate) = match *item {
+            Annotatable::Item(ref item) => {
+                match item.node {
+                    ItemKind::Mod(_) if self.cx.ecfg.proc_macro_mod() => return,
+                    ItemKind::Mod(_) => ("modules", "proc_macro_mod"),
+                    _ => return,
+                }
+            }
+            Annotatable::TraitItem(_) => return,
+            Annotatable::ImplItem(_) => return,
+            Annotatable::ForeignItem(_) => return,
+            Annotatable::Stmt(_) |
+            Annotatable::Expr(_) if self.cx.ecfg.proc_macro_expr() => return,
+            Annotatable::Stmt(_) => ("statements", "proc_macro_expr"),
+            Annotatable::Expr(_) => ("expressions", "proc_macro_expr"),
+        };
+        emit_feature_err(
+            self.cx.parse_sess,
+            gate,
+            span,
+            GateIssue::Language,
+            &format!("custom attributes cannot be applied to {}", kind),
+        );
+    }
+
     /// Expand a macro invocation. Returns the result of expansion.
     fn expand_bang_invoc(&mut self,
                          invoc: Invocation,
@@ -665,6 +710,7 @@ fn expand_bang_invoc(&mut self,
                     self.cx.trace_macros_diag();
                     kind.dummy(span)
                 } else {
+                    self.gate_proc_macro_expansion_kind(span, kind);
                     invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                         call_site: span,
                         callee: NameAndSpan {
@@ -695,6 +741,30 @@ fn expand_bang_invoc(&mut self,
         }
     }
 
+    fn gate_proc_macro_expansion_kind(&self, span: Span, kind: ExpansionKind) {
+        let kind = match kind {
+            ExpansionKind::Expr => "expressions",
+            ExpansionKind::OptExpr => "expressions",
+            ExpansionKind::Pat => "patterns",
+            ExpansionKind::Ty => "types",
+            ExpansionKind::Stmts => "statements",
+            ExpansionKind::Items => return,
+            ExpansionKind::TraitItems => return,
+            ExpansionKind::ImplItems => return,
+            ExpansionKind::ForeignItems => return,
+        };
+        if self.cx.ecfg.proc_macro_non_items() {
+            return
+        }
+        emit_feature_err(
+            self.cx.parse_sess,
+            "proc_macro_non_items",
+            span,
+            GateIssue::Language,
+            &format!("procedural macros cannot be expanded to {}", kind),
+        );
+    }
+
     /// Expand a derive invocation. Returns the result of expansion.
     fn expand_derive_invoc(&mut self,
                            invoc: Invocation,
@@ -1370,6 +1440,9 @@ fn enable_allow_internal_unstable = allow_internal_unstable,
         fn enable_custom_derive = custom_derive,
         fn proc_macro_enabled = proc_macro,
         fn macros_in_extern_enabled = macros_in_extern,
+        fn proc_macro_mod = proc_macro_mod,
+        fn proc_macro_expr = proc_macro_expr,
+        fn proc_macro_non_items = proc_macro_non_items,
     }
 }
 
index 3303955d398a64375035a3223ace0c1ba6347e1f..eeed291c0caaf0d3404d27595668bc9caf733930 100644 (file)
@@ -623,7 +623,7 @@ macro_rules! mk_lit {
         ($name: expr, $suffix: expr, $content: expr $(, $count: expr)*) => {{
             let name = mk_name(cx, sp, ast::Ident::with_empty_ctxt($content));
             let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![
-                name $(, cx.expr_usize(sp, $count))*
+                name $(, cx.expr_u16(sp, $count))*
             ]);
             let suffix = match $suffix {
                 Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::with_empty_ctxt(name))),
index 73ebfc20876d0679814369d4abe88883207d2570..d20e94b018b3f52a8e142105fcae1fb4b38e6fde 100644 (file)
@@ -231,9 +231,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // allow `repr(simd)`, and importing the various simd intrinsics
     (active, repr_simd, "1.4.0", Some(27731), None),
 
-    // Allows cfg(target_feature = "...").
-    (active, cfg_target_feature, "1.4.0", Some(29717), None),
-
     // allow `extern "platform-intrinsic" { ... }`
     (active, platform_intrinsics, "1.4.0", Some(27731), None),
 
@@ -275,6 +272,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Allows cfg(target_has_atomic = "...").
     (active, cfg_target_has_atomic, "1.9.0", Some(32976), None),
 
+    // The `!` type. Does not imply exhaustive_patterns (below) any more.
+    (active, never_type, "1.13.0", Some(35121), None),
+
     // Allows exhaustive pattern matching on types that contain uninhabited types.
     (active, exhaustive_patterns, "1.13.0", None, None),
 
@@ -293,9 +293,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     (active, use_extern_macros, "1.15.0", Some(35896), None),
 
-    // Allows #[target_feature(...)]
-    (active, target_feature, "1.15.0", None, None),
-
     // `extern "ptx-*" fn()`
     (active, abi_ptx, "1.15.0", None, None),
 
@@ -378,12 +375,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
     (active, non_exhaustive, "1.22.0", Some(44109), None),
 
-    // allow `'_` placeholder lifetimes
-    (active, underscore_lifetimes, "1.22.0", Some(44524), None),
-
-    // Default match binding modes (RFC 2005)
-    (active, match_default_bindings, "1.22.0", Some(42640), None),
-
     // Trait object syntax with `dyn` prefix
     (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)),
 
@@ -452,6 +443,29 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // Allows macro invocations in `extern {}` blocks
     (active, macros_in_extern, "1.27.0", Some(49476), None),
+
+    // unstable #[target_feature] directives
+    (active, arm_target_feature, "1.27.0", None, None),
+    (active, aarch64_target_feature, "1.27.0", None, None),
+    (active, hexagon_target_feature, "1.27.0", None, None),
+    (active, powerpc_target_feature, "1.27.0", None, None),
+    (active, mips_target_feature, "1.27.0", None, None),
+    (active, avx512_target_feature, "1.27.0", None, None),
+    (active, mmx_target_feature, "1.27.0", None, None),
+    (active, sse4a_target_feature, "1.27.0", None, None),
+    (active, tbm_target_feature, "1.27.0", None, None),
+
+    // Allows macro invocations of the form `#[foo::bar]`
+    (active, proc_macro_path_invoc, "1.27.0", None, None),
+
+    // Allows macro invocations on modules expressions and statements and
+    // procedural macros to expand to non-items.
+    (active, proc_macro_mod, "1.27.0", None, None),
+    (active, proc_macro_expr, "1.27.0", None, None),
+    (active, proc_macro_non_items, "1.27.0", None, None),
+
+    // #[doc(alias = "...")]
+    (active, doc_alias, "1.27.0", Some(50146), None),
 );
 
 declare_features! (
@@ -574,6 +588,10 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
     // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
     (accepted, generic_param_attrs, "1.26.0", Some(48848), None),
+    // Allows cfg(target_feature = "...").
+    (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
+    // Allows #[target_feature(...)]
+    (accepted, target_feature, "1.27.0", None, None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -918,10 +936,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                  "the `#[naked]` attribute \
                                   is an experimental feature",
                                  cfg_fn!(naked_functions))),
-    ("target_feature", Whitelisted, Gated(
-        Stability::Unstable, "target_feature",
-        "the `#[target_feature]` attribute is an experimental feature",
-        cfg_fn!(target_feature))),
+    ("target_feature", Normal, Ungated),
     ("export_name", Whitelisted, Ungated),
     ("inline", Whitelisted, Ungated),
     ("link", Whitelisted, Ungated),
@@ -1052,7 +1067,6 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
 // cfg(...)'s that are feature gated
 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
-    ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
     ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
     ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
     ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
@@ -1447,6 +1461,10 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
                     gate_feature_post!(&self, doc_spotlight, attr.span,
                         "#[doc(spotlight)] is experimental"
                     );
+                } else if content.iter().any(|c| c.check_name("alias")) {
+                    gate_feature_post!(&self, doc_alias, attr.span,
+                        "#[doc(alias = \"...\")] is experimental"
+                    );
                 }
             }
         }
@@ -1636,6 +1654,10 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
                 self.check_abi(bare_fn_ty.abi, ty.span);
             }
+            ast::TyKind::Never => {
+                gate_feature_post!(&self, never_type, ty.span,
+                                   "The `!` type is experimental");
+            }
             ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
                 gate_feature_post!(&self, dyn_trait, ty.span,
                                    "`dyn Trait` syntax is unstable");
@@ -1746,8 +1768,8 @@ fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
                 }
             }
             ast::TraitItemKind::Type(_, ref default) => {
-                // We use two if statements instead of something like match guards so that both
-                // of these errors can be emitted if both cases apply.
+                // We use three if statements instead of something like match guards so that all
+                // of these errors can be emitted if all cases apply.
                 if default.is_some() {
                     gate_feature_post!(&self, associated_type_defaults, ti.span,
                                        "associated type defaults are unstable");
@@ -1756,6 +1778,10 @@ fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
                     gate_feature_post!(&self, generic_associated_types, ti.span,
                                        "generic associated types are unstable");
                 }
+                if !ti.generics.where_clause.predicates.is_empty() {
+                    gate_feature_post!(&self, generic_associated_types, ti.span,
+                                       "where clauses on associated types are unstable");
+                }
             }
             _ => {}
         }
index cb3323c7eca4e68ab5ae40a2e8e515bc5401123f..22a0261d8c6b15fe9c05b4ce9e2634aa6f69d9b4 100644 (file)
@@ -133,12 +133,12 @@ pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
         Ok(ret_val)
     }
 
-    fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: usize) {
+    fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) {
         let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string");
         err.span_label(self.mk_sp(pos, pos), "unterminated raw string");
         if hash_count > 0 {
             err.note(&format!("this raw string should be terminated with `\"{}`",
-                              "#".repeat(hash_count)));
+                              "#".repeat(hash_count as usize)));
         }
         err.emit();
         FatalError.raise();
@@ -1439,7 +1439,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
             'r' => {
                 let start_bpos = self.pos;
                 self.bump();
-                let mut hash_count = 0;
+                let mut hash_count: u16 = 0;
                 while self.ch_is('#') {
                     self.bump();
                     hash_count += 1;
index ff63c9a5c6d539ac1614011b5096a6aff631cc53..0397c3297db0a2e832295b1369432791c9bf123f 100644 (file)
@@ -271,8 +271,16 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) {
         'u' => {
             assert_eq!(lit.as_bytes()[2], b'{');
             let idx = lit.find('}').unwrap();
-            let s = &lit[3..idx].chars().filter(|&c| c != '_').collect::<String>();
-            let v = u32::from_str_radix(&s, 16).unwrap();
+
+            // All digits and '_' are ascii, so treat each byte as a char.
+            let mut v: u32 = 0;
+            for c in lit[3..idx].bytes() {
+                let c = char::from(c);
+                if c != '_' {
+                    let x = c.to_digit(16).unwrap();
+                    v = v.checked_mul(16).unwrap().checked_add(x).unwrap();
+                }
+            }
             let c = char::from_u32(v).unwrap_or_else(|| {
                 if let Some((span, diag)) = diag {
                     let mut diag = diag.struct_span_err(span, "invalid unicode character escape");
index a7a9ce745122c36612eecdbf51ffc331cf1e16e6..9fa3952ca80ca07594dd62ee547794ce204e3cb5 100644 (file)
@@ -589,7 +589,8 @@ fn next_tok(&mut self) -> TokenAndSpan {
             self.token_cursor.next()
         };
         if next.sp == syntax_pos::DUMMY_SP {
-            next.sp = self.prev_span;
+            // Tweak the location for better diagnostics, but keep syntactic context intact.
+            next.sp = self.prev_span.with_ctxt(next.sp.ctxt());
         }
         next
     }
@@ -5758,18 +5759,33 @@ pub fn parse_single_struct_field(&mut self,
                                      vis: Visibility,
                                      attrs: Vec<Attribute> )
                                      -> PResult<'a, StructField> {
+        let mut seen_comma: bool = false;
         let a_var = self.parse_name_and_ty(lo, vis, attrs)?;
+        if self.token == token::Comma {
+            seen_comma = true;
+        }
         match self.token {
             token::Comma => {
                 self.bump();
             }
             token::CloseDelim(token::Brace) => {}
             token::DocComment(_) => {
+                let previous_span = self.prev_span;
                 let mut err = self.span_fatal_err(self.span, Error::UselessDocComment);
                 self.bump(); // consume the doc comment
-                if self.eat(&token::Comma) || self.token == token::CloseDelim(token::Brace) {
+                let comma_after_doc_seen = self.eat(&token::Comma);
+                // `seen_comma` is always false, because we are inside doc block
+                // condition is here to make code more readable
+                if seen_comma == false && comma_after_doc_seen == true {
+                    seen_comma = true;
+                }
+                if comma_after_doc_seen || self.token == token::CloseDelim(token::Brace) {
                     err.emit();
                 } else {
+                    if seen_comma == false {
+                        let sp = self.sess.codemap().next_point(previous_span);
+                        err.span_suggestion(sp, "missing comma here", ",".into());
+                    }
                     return Err(err);
                 }
             }
index 0913ed8614792b9ecc73c368bb8db6cccb934f77..44394384c7a7ebc4377261da2e82890ab995aea1 100644 (file)
@@ -26,6 +26,7 @@
 use tokenstream;
 
 use std::{cmp, fmt};
+use std::mem;
 use rustc_data_structures::sync::{Lrc, Lock};
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@@ -72,9 +73,9 @@ pub enum Lit {
     Integer(ast::Name),
     Float(ast::Name),
     Str_(ast::Name),
-    StrRaw(ast::Name, usize), /* raw str delimited by n hash symbols */
+    StrRaw(ast::Name, u16), /* raw str delimited by n hash symbols */
     ByteStr(ast::Name),
-    ByteStrRaw(ast::Name, usize), /* raw byte str delimited by n hash symbols */
+    ByteStrRaw(ast::Name, u16), /* raw byte str delimited by n hash symbols */
 }
 
 impl Lit {
@@ -88,6 +89,12 @@ pub fn short_name(&self) -> &'static str {
             ByteStr(_) | ByteStrRaw(..) => "byte string"
         }
     }
+
+    // See comments in `interpolated_to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    fn probably_equal_for_proc_macro(&self, other: &Lit) -> bool {
+        mem::discriminant(self) == mem::discriminant(other)
+    }
 }
 
 pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
@@ -530,14 +537,6 @@ pub fn interpolated_to_tokenstream(&self, sess: &ParseSess, span: Span)
         // stream they came from. Here we attempt to extract these
         // lossless token streams before we fall back to the
         // stringification.
-        //
-        // During early phases of the compiler, though, the AST could
-        // get modified directly (e.g. attributes added or removed) and
-        // the internal cache of tokens my not be invalidated or
-        // updated. Consequently if the "lossless" token stream
-        // disagrees with our actuall stringification (which has
-        // historically been much more battle-tested) then we go with
-        // the lossy stream anyway (losing span information).
         let mut tokens = None;
 
         match nt.0 {
@@ -569,13 +568,96 @@ pub fn interpolated_to_tokenstream(&self, sess: &ParseSess, span: Span)
             let source = pprust::token_to_string(self);
             parse_stream_from_source_str(FileName::MacroExpansion, source, sess, Some(span))
         });
+
+        // During early phases of the compiler the AST could get modified
+        // directly (e.g. attributes added or removed) and the internal cache
+        // of tokens my not be invalidated or updated. Consequently if the
+        // "lossless" token stream disagrees with our actual stringification
+        // (which has historically been much more battle-tested) then we go
+        // with the lossy stream anyway (losing span information).
+        //
+        // Note that the comparison isn't `==` here to avoid comparing spans,
+        // but it *also* is a "probable" equality which is a pretty weird
+        // definition. We mostly want to catch actual changes to the AST
+        // like a `#[cfg]` being processed or some weird `macro_rules!`
+        // expansion.
+        //
+        // What we *don't* want to catch is the fact that a user-defined
+        // literal like `0xf` is stringified as `15`, causing the cached token
+        // stream to not be literal `==` token-wise (ignoring spans) to the
+        // token stream we got from stringification.
+        //
+        // Instead the "probably equal" check here is "does each token
+        // recursively have the same discriminant?" We basically don't look at
+        // the token values here and assume that such fine grained modifications
+        // of token streams doesn't happen.
         if let Some(tokens) = tokens {
-            if tokens.eq_unspanned(&tokens_for_real) {
+            if tokens.probably_equal_for_proc_macro(&tokens_for_real) {
                 return tokens
             }
         }
         return tokens_for_real
     }
+
+    // See comments in `interpolated_to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    pub fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
+        if mem::discriminant(self) != mem::discriminant(other) {
+            return false
+        }
+        match (self, other) {
+            (&Eq, &Eq) |
+            (&Lt, &Lt) |
+            (&Le, &Le) |
+            (&EqEq, &EqEq) |
+            (&Ne, &Ne) |
+            (&Ge, &Ge) |
+            (&Gt, &Gt) |
+            (&AndAnd, &AndAnd) |
+            (&OrOr, &OrOr) |
+            (&Not, &Not) |
+            (&Tilde, &Tilde) |
+            (&At, &At) |
+            (&Dot, &Dot) |
+            (&DotDot, &DotDot) |
+            (&DotDotDot, &DotDotDot) |
+            (&DotDotEq, &DotDotEq) |
+            (&DotEq, &DotEq) |
+            (&Comma, &Comma) |
+            (&Semi, &Semi) |
+            (&Colon, &Colon) |
+            (&ModSep, &ModSep) |
+            (&RArrow, &RArrow) |
+            (&LArrow, &LArrow) |
+            (&FatArrow, &FatArrow) |
+            (&Pound, &Pound) |
+            (&Dollar, &Dollar) |
+            (&Question, &Question) |
+            (&Whitespace, &Whitespace) |
+            (&Comment, &Comment) |
+            (&Eof, &Eof) => true,
+
+            (&BinOp(a), &BinOp(b)) |
+            (&BinOpEq(a), &BinOpEq(b)) => a == b,
+
+            (&OpenDelim(a), &OpenDelim(b)) |
+            (&CloseDelim(a), &CloseDelim(b)) => a == b,
+
+            (&DocComment(a), &DocComment(b)) |
+            (&Shebang(a), &Shebang(b)) => a == b,
+
+            (&Lifetime(a), &Lifetime(b)) => a.name == b.name,
+            (&Ident(a, b), &Ident(c, d)) => a.name == c.name && b == d,
+
+            (&Literal(ref a, b), &Literal(ref c, d)) => {
+                b == d && a.probably_equal_for_proc_macro(c)
+            }
+
+            (&Interpolated(_), &Interpolated(_)) => false,
+
+            _ => panic!("forgot to add a token?"),
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Eq, Hash)]
index 3741850b8a974a7e78fac7583a9b94efd9d712b4..bd06ae8c1a9b947875f36e52d60c2efc9289fb35 100644 (file)
@@ -234,11 +234,11 @@ pub fn token_to_string(tok: &Token) -> String {
                 token::Integer(c)        => c.to_string(),
                 token::Str_(s)           => format!("\"{}\"", s),
                 token::StrRaw(s, n)      => format!("r{delim}\"{string}\"{delim}",
-                                                    delim=repeat("#", n),
+                                                    delim=repeat("#", n as usize),
                                                     string=s),
                 token::ByteStr(v)         => format!("b\"{}\"", v),
                 token::ByteStrRaw(s, n)   => format!("br{delim}\"{string}\"{delim}",
-                                                    delim=repeat("#", n),
+                                                    delim=repeat("#", n as usize),
                                                     string=s),
             };
 
@@ -660,7 +660,7 @@ fn print_string(&mut self, st: &str,
             }
             ast::StrStyle::Raw(n) => {
                 (format!("r{delim}\"{string}\"{delim}",
-                         delim=repeat("#", n),
+                         delim=repeat("#", n as usize),
                          string=st))
             }
         };
index bba7a2d73773646d5db9df809836d6645e811177..53dc19ba37d19775a2569023987c3bd7c9c57afd 100644 (file)
@@ -57,7 +57,8 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>
         &["std"]
     };
 
-    for name in names {
+    // .rev() to preserve ordering above in combination with insert(0, ...)
+    for name in names.iter().rev() {
         krate.module.items.insert(0, P(ast::Item {
             attrs: vec![attr::mk_attr_outer(DUMMY_SP,
                                             attr::mk_attr_id(),
index 6ac04b3cdf6c437bd4dcd67b914ef7b91e7298c8..e2b5c4e1adfdbc59c8e1247db5f7d045dc237e54 100644 (file)
@@ -124,6 +124,24 @@ pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
         }
     }
 
+    // See comments in `interpolated_to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    //
+    // This is otherwise the same as `eq_unspanned`, only recursing with a
+    // different method.
+    pub fn probably_equal_for_proc_macro(&self, other: &TokenTree) -> bool {
+        match (self, other) {
+            (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => {
+                tk.probably_equal_for_proc_macro(tk2)
+            }
+            (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => {
+                dl.delim == dl2.delim &&
+                dl.stream().probably_equal_for_proc_macro(&dl2.stream())
+            }
+            (_, _) => false,
+        }
+    }
+
     /// Retrieve the TokenTree's span.
     pub fn span(&self) -> Span {
         match *self {
@@ -250,6 +268,22 @@ pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
         t1.next().is_none() && t2.next().is_none()
     }
 
+    // See comments in `interpolated_to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    //
+    // This is otherwise the same as `eq_unspanned`, only recursing with a
+    // different method.
+    pub fn probably_equal_for_proc_macro(&self, other: &TokenStream) -> bool {
+        let mut t1 = self.trees();
+        let mut t2 = other.trees();
+        for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
+            if !t1.probably_equal_for_proc_macro(&t2) {
+                return false;
+            }
+        }
+        t1.next().is_none() && t2.next().is_none()
+    }
+
     /// Precondition: `self` consists of a single token tree.
     /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`.
     pub fn as_tree(self) -> (TokenTree, bool /* joint? */) {
index 8cb5776fdeb0167ccc3ea403fa8e8cf7d728db8c..5e96b5ce6733c8d60631458755b37ac4e6ddd32e 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Machinery for hygienic macros, inspired by the MTWT[1] paper.
+//! Machinery for hygienic macros, inspired by the `MTWT[1]` paper.
 //!
-//! [1] Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler. 2012.
+//! `[1]` Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler. 2012.
 //! *Macros that work together: Compile-time bindings, partial expansion,
 //! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216.
 //! DOI=10.1017/S0956796812000093 <http://dx.doi.org/10.1017/S0956796812000093>
index 331b0fe5481d5c0d0593626b21dcce8288b241e3..50fac600a978d21ab05dc0ae9174120f25621029 100644 (file)
@@ -336,24 +336,23 @@ pub fn fresh() -> Self {
     (46, Offsetof,           "offsetof")
     (47, Override,           "override")
     (48, Priv,               "priv")
-    (49, Proc,               "proc")
-    (50, Pure,               "pure")
-    (51, Sizeof,             "sizeof")
-    (52, Typeof,             "typeof")
-    (53, Unsized,            "unsized")
-    (54, Virtual,            "virtual")
-    (55, Yield,              "yield")
+    (49, Pure,               "pure")
+    (50, Sizeof,             "sizeof")
+    (51, Typeof,             "typeof")
+    (52, Unsized,            "unsized")
+    (53, Virtual,            "virtual")
+    (54, Yield,              "yield")
 
     // Special lifetime names
-    (56, UnderscoreLifetime, "'_")
-    (57, StaticLifetime,     "'static")
+    (55, UnderscoreLifetime, "'_")
+    (56, StaticLifetime,     "'static")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (58, Auto,               "auto")
-    (59, Catch,              "catch")
-    (60, Default,            "default")
-    (61, Dyn,                "dyn")
-    (62, Union,              "union")
+    (57, Auto,               "auto")
+    (58, Catch,              "catch")
+    (59, Default,            "default")
+    (60, Dyn,                "dyn")
+    (61, Union,              "union")
 }
 
 // If an interner exists, return it. Otherwise, prepare a fresh one.
index 9291eaa910bd744d745935eb295fc6efac275f3b..a4d1797c3ec5baa000daeebb55524950c06b63fe 100644 (file)
@@ -1288,7 +1288,6 @@ fn num_cpus() -> usize {
 
 pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
     let mut filtered = tests;
-
     // Remove tests that don't match the test filter
     filtered = match opts.filter {
         None => filtered,
index 26376a3733f4fce327c5a83902e115ee4979d1f3..a962d5fc4153740e377dd50243969c75543d0562 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// A macro for defining #[cfg] if-else statements.
+/// A macro for defining `#[cfg]` if-else statements.
 ///
 /// This is similar to the `if/elif` C preprocessor macro by allowing definition
 /// of a cascade of `#[cfg]` cases, emitting the implementation which matches
 /// first.
 ///
-/// This allows you to conveniently provide a long list #[cfg]'d blocks of code
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
 /// without having to rewrite each clause multiple times.
 macro_rules! cfg_if {
     ($(
index a888838ce432cb1fa44e8f738406961ede720674..ab5a7c3f747eb3835aae5144032639e31215db30 100644 (file)
@@ -23,4 +23,7 @@
 
 extern crate rustc_driver;
 
-fn main() { rustc_driver::main() }
+fn main() {
+    rustc_driver::set_sigpipe_handler();
+    rustc_driver::main()
+}
index bcb720e55861c38db47f2ebdf26b7198338cb39d..1ea18a5cb431e24aa838b652ac305acc5e394d6b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit bcb720e55861c38db47f2ebdf26b7198338cb39d
+Subproject commit 1ea18a5cb431e24aa838b652ac305acc5e394d6b
index 9fea907d3c884e56f1078e4b197b9dc3df38a8c9..6863b1f2792b919b41cf81b76abaed7faf597f86 100644 (file)
@@ -11,6 +11,7 @@
 // aux-build:nounwind.rs
 // compile-flags: -C no-prepopulate-passes -C panic=abort -C metadata=a
 // ignore-windows
+// ignore-android
 
 #![crate_type = "lib"]
 
index 2f65bd16bb54a1953a0422d57e1ee2c5add15a7b..749d87e37b5599d4d38356e152de48641e5427d8 100644 (file)
@@ -13,7 +13,7 @@
 
 //! Attributes producing expressions in invalid locations
 
-#![feature(proc_macro, stmt_expr_attributes)]
+#![feature(proc_macro, stmt_expr_attributes, proc_macro_expr)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{duplicate, no_output};
index d29bc00c663c8e2788a4884b47a69e5c761b693a..ce04fdfb976d4aa32306a7be25147e056c825a38 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-stmt-expr.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_expr)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
index 00a27818327f6692afb55eb9f74003319ecdba99..edfedebf870cf9d1266e796b648a3ddb5994158c 100644 (file)
@@ -21,6 +21,8 @@
 fn test1() {
     let a: i32 = "foo";
     //~^ ERROR: mismatched types
+    let b: i32 = "f'oo";
+    //~^ ERROR: mismatched types
 }
 
 fn test2() {
index 2adbee1d3fbd5b7c23bf58667d33f00e893c1c54..9947e8f66cedac251a2c01506b335b9f585cd07b 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attributes-included.rs
 // ignore-stage1
 
-#![feature(proc_macro, rustc_attrs)]
+#![feature(proc_macro, rustc_attrs, proc_macro_path_invoc)]
 #![warn(unused)]
 
 extern crate attributes_included;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs
new file mode 100644 (file)
index 0000000..25579f1
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+// force-host
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn m(a: TokenStream) -> TokenStream {
+    a
+}
+
+#[proc_macro_attribute]
+pub fn a(_a: TokenStream, b: TokenStream) -> TokenStream {
+    b
+}
index 773b16b945f072ff359804c9d5e2c46d6e2be952..c7be316794746c9f04fe63345dcfe03b6213e0a3 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:bang_proc_macro2.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 #![allow(unused_macros)]
 
 extern crate bang_proc_macro2;
index 7ecc685357ee675b0e4235f51756790b25a1c6e3..f16ca79ca9313a9c6dcb4db6c8e589feffc9982e 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:bang_proc_macro.rs
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 #[macro_use]
 extern crate bang_proc_macro;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
new file mode 100644 (file)
index 0000000..0dc1c2a
--- /dev/null
@@ -0,0 +1,54 @@
+// 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:proc-macro-gates.rs
+// gate-test-proc_macro_non_items
+// gate-test-proc_macro_path_invoc
+// gate-test-proc_macro_mod line
+// gate-test-proc_macro_expr
+// gate-test-proc_macro_mod
+
+#![feature(proc_macro, stmt_expr_attributes)]
+
+extern crate proc_macro_gates as foo;
+
+use foo::*;
+
+#[foo::a] //~ ERROR: paths of length greater than one
+fn _test() {}
+
+#[a] //~ ERROR: custom attributes cannot be applied to modules
+mod _test2 {}
+
+#[a = y] //~ ERROR: must only be followed by a delimiter token
+fn _test3() {}
+
+#[a = ] //~ ERROR: must only be followed by a delimiter token
+fn _test4() {}
+
+#[a () = ] //~ ERROR: must only be followed by a delimiter token
+fn _test5() {}
+
+fn main() {
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    let _x = 2;
+    let _x = #[a] 2;
+    //~^ ERROR: custom attributes cannot be applied to expressions
+
+    let _x: m!(u32) = 3;
+    //~^ ERROR: procedural macros cannot be expanded to types
+    if let m!(Some(_x)) = Some(3) {
+    //~^ ERROR: procedural macros cannot be expanded to patterns
+    }
+    let _x = m!(3);
+    //~^ ERROR: procedural macros cannot be expanded to expressions
+    m!(let _x = 3;);
+    //~^ ERROR: procedural macros cannot be expanded to statements
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs
new file mode 100644 (file)
index 0000000..a1a15af
--- /dev/null
@@ -0,0 +1,35 @@
+// 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:proc-macro-gates.rs
+
+#![feature(proc_macro, stmt_expr_attributes)]
+
+extern crate proc_macro_gates as foo;
+
+use foo::*;
+
+// NB. these errors aren't the best errors right now, but they're definitely
+// intended to be errors. Somehow using a custom attribute in these positions
+// should either require a feature gate or not be allowed on stable.
+
+fn _test6<#[a] T>() {}
+//~^ ERROR: unknown to the compiler
+
+fn _test7() {
+    match 1 {
+        #[a] //~ ERROR: unknown to the compiler
+        0 => {}
+        _ => {}
+    }
+}
+
+fn main() {
+}
index f7e246e8f0f41383b2e9186f3acffec03450de4b..5643e1ef09146eb1fe6b4daae607938d6c3797b1 100644 (file)
@@ -26,10 +26,12 @@ fn foo(a: &mut i32) {
         inside_closure(a)
     };
     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
-                         //[mir]~^ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
+    //[mir]~^ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
 
     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
-                         //[mir]~^ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+    //[mir]~^ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+
+    drop(bar);
 }
 
 fn main() {
index 1479d0b62642a76cc8267994d270e196ce0eade0..140cad22f34e42ae52b5b94ffe1b071fd9c3ff41 100644 (file)
@@ -16,6 +16,5 @@
 //~| the trait bound `usize:
 //~| the trait bound `usize:
 //~| the trait bound `usize:
-//~| the trait bound `usize:
 
 fn main() {}
index 9ad3a8f9fc8671e072a93e06d9fb77ccafae32f9..0b230be85ad97c2ab68d97220eb720159c6172d2 100644 (file)
@@ -14,7 +14,7 @@
 // ignore-sparc
 
 // revisions: ast mir
-//[mir]compile-flags: -Z borrowck=mir -Z nll
+//[mir]compile-flags: -Z borrowck=mir
 
 #![feature(asm)]
 
index f498d8d500e649e3562905495320f230324cb3fd..9057ba0790712f36ec808332ab3523acacdcd7c4 100644 (file)
@@ -29,7 +29,8 @@ fn a() {
     let mut x = 3;
     let c1 = || x = 4;
     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
-                       //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    drop(c1);
 }
 
 fn b() {
@@ -37,6 +38,7 @@ fn b() {
     let c1 = || set(&mut x);
     let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
                          //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    drop(c1);
 }
 
 fn c() {
@@ -44,6 +46,7 @@ fn c() {
     let c1 = || set(&mut x);
     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
                        //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    drop(c1);
 }
 
 fn d() {
@@ -51,6 +54,7 @@ fn d() {
     let c2 = || x * 5;
     x = 5; //[ast]~ ERROR cannot assign
            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+    drop(c2);
 }
 
 fn e() {
@@ -58,6 +62,7 @@ fn e() {
     let c1 = || get(&x);
     x = 5; //[ast]~ ERROR cannot assign
            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+    drop(c1);
 }
 
 fn f() {
@@ -65,6 +70,7 @@ fn f() {
     let c1 = || get(&*x);
     *x = 5; //[ast]~ ERROR cannot assign to `*x`
             //[mir]~^ ERROR cannot assign to `*x` because it is borrowed
+    drop(c1);
 }
 
 fn g() {
@@ -76,6 +82,7 @@ struct Foo {
     let c1 = || get(&*x.f);
     *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
               //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed
+    drop(c1);
 }
 
 fn h() {
@@ -87,6 +94,7 @@ struct Foo {
     let c1 = || get(&*x.f);
     let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
                           //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    drop(c1);
 }
 
 fn main() {
index fa475949b36b0e65612e92e4290e4f0686f948fc..3a7e4a13740d070ab1b4afbba2bf2a7283f52968 100644 (file)
@@ -49,83 +49,93 @@ fn main() {
     // Local and field from struct
     {
         let mut f = Foo { x: 22 };
-        let _x = f.x();
+        let x = f.x();
         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
-             //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+        //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+        drop(x);
     }
     // Local and field from tuple-struct
     {
         let mut g = Bar(22);
-        let _0 = g.x();
+        let x = g.x();
         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+        drop(x);
     }
     // Local and field from tuple
     {
         let mut h = (22, 23);
-        let _0 = &mut h.0;
+        let x = &mut h.0;
         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+        drop(x);
     }
     // Local and field from enum
     {
         let mut e = Baz::X(2);
-        let _e0 = e.x();
+        let x = e.x();
         match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
             Baz::X(value) => value
             //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
             //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed
         };
+        drop(x);
     }
     // Local and field from union
     unsafe {
         let mut u = U { b: 0 };
-        let _ra = &mut u.a;
+        let x = &mut u.a;
         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+        drop(x);
     }
     // Deref and field from struct
     {
         let mut f = Box::new(Foo { x: 22 });
-        let _x = f.x();
+        let x = f.x();
         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+        drop(x);
     }
     // Deref and field from tuple-struct
     {
         let mut g = Box::new(Bar(22));
-        let _0 = g.x();
+        let x = g.x();
         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+        drop(x);
     }
     // Deref and field from tuple
     {
         let mut h = Box::new((22, 23));
-        let _0 = &mut h.0;
+        let x = &mut h.0;
         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+        drop(x);
     }
     // Deref and field from enum
     {
         let mut e = Box::new(Baz::X(3));
-        let _e0 = e.x();
+        let x = e.x();
         match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
             Baz::X(value) => value
             //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
             //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed
         };
+        drop(x);
     }
     // Deref and field from union
     unsafe {
         let mut u = Box::new(U { b: 0 });
-        let _ra = &mut u.a;
+        let x = &mut u.a;
         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+        drop(x);
     }
     // Constant index
     {
         let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        let _v = &mut v;
+        let x = &mut v;
         match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
             &[x, _, .., _, _] => println!("{}", x),
                 //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
@@ -150,11 +160,12 @@ fn main() {
                 //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
                             _ => panic!("other case"),
         }
+        drop(x);
     }
     // Subslices
     {
         let mut v = &[1, 2, 3, 4, 5];
-        let _v = &mut v;
+        let x = &mut v;
         match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
             &[x..] => println!("{:?}", x),
                 //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
@@ -179,13 +190,14 @@ fn main() {
                 //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
             _ => panic!("other case"),
         }
+        drop(x);
     }
     // Downcasted field
     {
         enum E<X> { A(X), B { x: X } }
 
         let mut e = E::A(3);
-        let _e = &mut e;
+        let x = &mut e;
         match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
             E::A(ref ax) =>
                 //[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable
@@ -197,13 +209,14 @@ enum E<X> { A(X), B { x: X } }
                 //[mir]~^^ ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable
                 println!("e.bx: {:?}", bx),
         }
+        drop(x);
     }
     // Field in field
     {
         struct F { x: u32, y: u32 };
         struct S { x: F, y: (u32, u32), };
         let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) };
-        let _s = &mut s;
+        let x = &mut s;
         match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
             S  { y: (ref y0, _), .. } =>
                 //[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable
@@ -218,6 +231,7 @@ enum E<X> { A(X), B { x: X } }
                 println!("x0: {:?}", x0),
             _ => panic!("other case"),
         }
+        drop(x);
     }
     // Field of ref
     {
@@ -231,6 +245,7 @@ fn bump<'a>(mut block: &mut Block<'a>) {
             let p: &'a u8 = &*block.current;
             //[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
             // No errors in AST because of issue rust#38899
+            drop(x);
         }
     }
     // Field of ptr
@@ -245,29 +260,32 @@ unsafe fn bump2(mut block: *mut Block2) {
             let p : *const u8 = &*(*block).current;
             //[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
             // No errors in AST because of issue rust#38899
+            drop(x);
         }
     }
     // Field of index
     {
         struct F {x: u32, y: u32};
         let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
-        let _v = &mut v;
+        let x = &mut v;
         v[0].y;
         //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed
         //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed
         //[mir]~| ERROR cannot use `*v` because it was mutably borrowed
+        drop(x);
     }
     // Field of constant index
     {
         struct F {x: u32, y: u32};
         let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
-        let _v = &mut v;
+        let x = &mut v;
         match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
             &[_, F {x: ref xf, ..}] => println!("{}", xf),
             //[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
             // No errors in AST
             _ => panic!("other case")
         }
+        drop(x);
     }
     // Field from upvar
     {
@@ -281,13 +299,15 @@ unsafe fn bump2(mut block: *mut Block2) {
     }
     // Field from upvar nested
     {
+        // FIXME(#49824) -- the free region error below should probably not be there
         let mut x = 0;
            || {
-               || {
-                let y = &mut x;
-                &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
-                        //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
-                *y = 1;
+               || { //[mir]~ ERROR free region `` does not outlive
+                   let y = &mut x;
+                   &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+                   //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+                   *y = 1;
+                   drop(y);
                 }
            };
     }
index f09a0c7414ba901267846ed523ed10651afa8557..6f0e0f43f60885bc17c2d2c01b80b7c2ce63a3be 100644 (file)
 
 fn main() {
     let mut _a = 3;
-    let _b = &mut _a;
+    let b = &mut _a;
     {
-        let _c = &*_b;
+        let c = &*b;
         _a = 4; //[ast]~ ERROR cannot assign to `_a`
-                //[mir]~^ ERROR cannot assign to `_a` because it is borrowed
+        //[mir]~^ ERROR cannot assign to `_a` because it is borrowed
+        drop(c);
     }
+    drop(b);
 }
index 2fe764568bc82999e2b518ba87e0051b46812931..f2f3e7914227c788619e6122d3058227ee978e7d 100644 (file)
@@ -24,9 +24,10 @@ fn separate_arms() {
             // fact no outstanding loan of x!
             x = Some(0);
         }
-        Some(ref __isize) => {
+        Some(ref r) => {
             x = Some(1); //[ast]~ ERROR cannot assign
-                         //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+            drop(r);
         }
     }
     x.clone(); // just to prevent liveness warnings
index 3e57ac0ca1910a11996afa2a0b04ca796e2456a3..c2136e62a7b228afb0993055d0914953ffec9f25 100644 (file)
@@ -25,16 +25,18 @@ fn match_enum() {
         Foo::A(x) => x //[ast]~ ERROR [E0503]
                        //[mir]~^ ERROR [E0503]
     };
+    drop(p);
 }
 
 
 fn main() {
     let mut x = 1;
-    let _x = &mut x;
+    let r = &mut x;
     let _ = match x { //[mir]~ ERROR [E0503]
         x => x + 1, //[ast]~ ERROR [E0503]
                     //[mir]~^ ERROR [E0503]
         y => y + 2, //[ast]~ ERROR [E0503]
                     //[mir]~^ ERROR [E0503]
     };
+    drop(r);
 }
index 63bb04a0e4c3afd38716b3e7de834bbe298a963f..7b0a71815a5f065de4f43d43110ec81790642896 100644 (file)
 
 fn main() {
     let mut x = 1;
-    let mut addr;
+    let mut addr = vec![];
     loop {
         match 1 {
-            1 => { addr = &mut x; } //[ast]~ ERROR [E0499]
+            1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
             //[mir]~^ ERROR [E0499]
-            2 => { addr = &mut x; } //[ast]~ ERROR [E0499]
+            2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
             //[mir]~^ ERROR [E0499]
-            _ => { addr = &mut x; } //[ast]~ ERROR [E0499]
+            _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
             //[mir]~^ ERROR [E0499]
         }
     }
index 3a4c22eb1395a0f6bfb915d48a804d0543aea9a1..109fe3d1128e1990b186e36158e679b864db127d 100644 (file)
@@ -71,4 +71,5 @@ fn main() {
     s[2] = 20;
     //[ast]~^ ERROR cannot assign to immutable indexed content
     //[mir]~^^ ERROR cannot assign to immutable item
+    drop(rs);
 }
index 0f3a841821080a9748b3a12abde46e039108cde3..d917a0abb88d089a1cd20eafa558562dbe3a4dba 100644 (file)
@@ -21,7 +21,8 @@ fn main() {
       Some(ref i) => {
           // But on this branch, `i` is an outstanding borrow
           x = Some(*i+1); //[ast]~ ERROR cannot assign to `x`
-                          //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+          //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+          drop(i);
       }
     }
     x.clone(); // just to prevent liveness warnings
index 0241b3870c7e64554f8a692b5c4bc8722dc60fc5..97193bd0191237ffe735c3f904257746f4f09abe 100644 (file)
@@ -25,82 +25,98 @@ fn main() {
         {
             let ra = &u.a;
             let ra2 = &u.a; // OK
+            drop(ra);
         }
         {
             let ra = &u.a;
             let a = u.a; // OK
+            drop(ra);
         }
         {
             let ra = &u.a;
             let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
                                 //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+            drop(ra);
         }
         {
             let ra = &u.a;
             u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
                      //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
+            drop(ra);
         }
         // Imm borrow, other field
         {
             let ra = &u.a;
             let rb = &u.b; // OK
+            drop(ra);
         }
         {
             let ra = &u.a;
             let b = u.b; // OK
+            drop(ra);
         }
         {
             let ra = &u.a;
             let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
                                 //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
+            drop(ra);
         }
         {
             let ra = &u.a;
             u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
                      //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
+            drop(ra);
         }
         // Mut borrow, same field
         {
             let rma = &mut u.a;
             let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
                          //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+            drop(rma);
         }
         {
             let ra = &mut u.a;
             let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
                          //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+            drop(ra);
         }
         {
             let rma = &mut u.a;
             let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
                                  //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
+            drop(rma);
         }
         {
             let rma = &mut u.a;
             u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
                      //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
+            drop(rma);
         }
         // Mut borrow, other field
         {
             let rma = &mut u.a;
             let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
                            //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
+            drop(rma);
         }
         {
             let ra = &mut u.a;
             let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
                          //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed
 
+            drop(ra);
         }
         {
             let rma = &mut u.a;
             let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
                                  //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
+            drop(rma);
         }
         {
             let rma = &mut u.a;
             u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
                      //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
+            drop(rma);
         }
     }
 }
diff --git a/src/test/compile-fail/borrowck/two-phase-across-loop.rs b/src/test/compile-fail/borrowck/two-phase-across-loop.rs
new file mode 100644 (file)
index 0000000..e03a035
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that a borrow which starts as a 2-phase borrow and gets
+// carried around a loop winds up conflicting with itself.
+
+#![feature(nll)]
+
+struct Foo { x: String }
+
+impl Foo {
+    fn get_string(&mut self) -> &str {
+        &self.x
+    }
+}
+
+fn main() {
+    let mut foo = Foo { x: format!("Hello, world") };
+    let mut strings = vec![];
+
+    loop {
+        strings.push(foo.get_string()); //~ ERROR cannot borrow `foo` as mutable
+        if strings.len() > 2 { break; }
+    }
+
+    println!("{:?}", strings);
+}
index 90933c6b31fa868b8ce7bffe37ce552130639be9..77b237e34f2b7d0bc7c3810d5b33b67a12d83304 100644 (file)
 // revisions: nll_target
 
 // The following revisions are disabled due to missing support from two-phase beyond autorefs
-//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
-//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll
+//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
 
-//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is an important corner case pointed out by Niko: one is
 // allowed to initiate a shared borrow during a reservation, but it
index d2f4154433ab152b4c9a8eac7657d97233162788..5deabf9376482ccdcf5c1ece14710ae1c83f8f24 100644 (file)
 // revisions: nll_target
 
 // The following revisions are disabled due to missing support for two_phase_beyond_autoref
-//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref
-//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref -Z nll
+//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref
 
-
-//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is the second counter-example from Niko's blog post
 // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/
@@ -44,9 +42,8 @@ fn main() {
 
     /*3*/ *p += 1;        // (mutable borrow of `i` starts here, since `p` is used)
 
-    /*4*/ let k = i;      //[lxl_beyond]~   ERROR cannot use `i` because it was mutably borrowed [E0503]
-                          //[nll_beyond]~^  ERROR cannot use `i` because it was mutably borrowed [E0503]
-                          //[nll_target]~^^ ERROR cannot use `i` because it was mutably borrowed [E0503]
+    /*4*/ let k = i;      //[nll_beyond]~  ERROR cannot use `i` because it was mutably borrowed [E0503]
+                          //[nll_target]~^ ERROR cannot use `i` because it was mutably borrowed [E0503]
 
     /*5*/ *p += 1;
 
index 01b04708599c03a489cdfaa2ea65deb1660acd88..15700a1d61a1fa324780195ae44d4ae40fbe10aa 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lxl nll
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is the third counter-example from Niko's blog post
 // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/
@@ -26,8 +24,7 @@ fn main() {
     vec.get({
 
         vec.push(2);
-        //[lxl]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
-        //[nll]~^^   ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
+        //~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
 
         0
     });
index ef39fabda10e62f744b4eb186615c49c036f86da..4303048138d91c4bbdc49f6b01445e4097f01028 100644 (file)
@@ -8,12 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: ast lxl nll
+// revisions: ast nll
 //[ast]compile-flags:
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
-//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll -Z two-phase-beyond-autoref
+//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
 // the above revision is disabled until two-phase-beyond-autoref support is better
 
 // This is a test checking that when we limit two-phase borrows to
@@ -69,44 +68,38 @@ fn overloaded_call_traits() {
 
     fn twice_ten_sm<F: FnMut(i32) -> i32>(f: &mut F) {
         f(f(10));
-        //[lxl]~^     ERROR cannot borrow `*f` as mutable more than once at a time
-        //[nll]~^^   ERROR cannot borrow `*f` as mutable more than once at a time
-        //[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
-        //[ast]~^^^^ ERROR cannot borrow `*f` as mutable more than once at a time
+        //[nll]~^   ERROR cannot borrow `*f` as mutable more than once at a time
+        //[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
+        //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
     }
     fn twice_ten_si<F: Fn(i32) -> i32>(f: &mut F) {
         f(f(10));
     }
     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
         f(f(10));
-        //[lxl]~^    ERROR use of moved value: `*f`
-        //[nll]~^^   ERROR use of moved value: `*f`
-        //[g2p]~^^^  ERROR use of moved value: `*f`
-        //[ast]~^^^^ ERROR use of moved value: `*f`
+        //[nll]~^   ERROR use of moved value: `*f`
+        //[g2p]~^^  ERROR use of moved value: `*f`
+        //[ast]~^^^ ERROR use of moved value: `*f`
     }
 
     fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
         f(f(10));
-        //[lxl]~^    ERROR cannot borrow `*f` as mutable more than once at a time
-        //[nll]~^^   ERROR cannot borrow `*f` as mutable more than once at a time
-        //[g2p]~^^^  ERROR cannot borrow `*f` as mutable more than once at a time
-        //[ast]~^^^^ ERROR cannot borrow `*f` as mutable more than once at a time
+        //[nll]~^   ERROR cannot borrow `*f` as mutable more than once at a time
+        //[g2p]~^^  ERROR cannot borrow `*f` as mutable more than once at a time
+        //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
     }
     fn twice_ten_oi(f: &mut Fn(i32) -> i32) {
         f(f(10));
     }
     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
         f(f(10));
-        //[lxl]~^             ERROR cannot move a value of type
-        //[lxl]~^^            ERROR cannot move a value of type
-        //[lxl]~^^^           ERROR use of moved value: `*f`
-        //[nll]~^^^^          ERROR cannot move a value of type
-        //[nll]~^^^^^         ERROR cannot move a value of type
-        //[nll]~^^^^^^        ERROR use of moved value: `*f`
-        //[g2p]~^^^^^^^       ERROR cannot move a value of type
-        //[g2p]~^^^^^^^^      ERROR cannot move a value of type
-        //[g2p]~^^^^^^^^^     ERROR use of moved value: `*f`
-        //[ast]~^^^^^^^^^^    ERROR use of moved value: `*f`
+        //[nll]~^          ERROR cannot move a value of type
+        //[nll]~^^         ERROR cannot move a value of type
+        //[nll]~^^^        ERROR use of moved value: `*f`
+        //[g2p]~^^^^       ERROR cannot move a value of type
+        //[g2p]~^^^^^      ERROR cannot move a value of type
+        //[g2p]~^^^^^^     ERROR use of moved value: `*f`
+        //[ast]~^^^^^^^    ERROR use of moved value: `*f`
     }
 
     twice_ten_sm(&mut |x| x + 1);
@@ -144,10 +137,9 @@ fn coerce_unsized() {
 
     // This is not okay.
     double_access(&mut a, &a);
-    //[lxl]~^    ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
-    //[nll]~^^   ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
-    //[g2p]~^^^  ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
-    //[ast]~^^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+    //[nll]~^   ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+    //[g2p]~^^  ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+    //[ast]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
 
     // But this is okay.
     a.m(a.i(10));
@@ -173,16 +165,14 @@ fn index_mut(&mut self, _: i32) -> &mut i32 {
 fn coerce_index_op() {
     let mut i = I(10);
     i[i[3]] = 4;
-    //[lxl]~^   ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
-    //[nll]~^^  ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
-    //[ast]~^^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+    //[nll]~^  ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+    //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
 
     i[3] = i[4];
 
     i[i[3]] = i[4];
-    //[lxl]~^   ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
-    //[nll]~^^  ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
-    //[ast]~^^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+    //[nll]~^  ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+    //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
 }
 
 fn main() {
index fc9100c8a9a865f493319b2bd9444b82222e844f..f9326d944b8e4220a82896ca77c0032215700ed4 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lxl nll
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is similar to two-phase-reservation-sharing-interference.rs
 // in that it shows a reservation that overlaps with a shared borrow.
 #![feature(rustc_attrs)]
 
 #[rustc_error]
-fn main() { //[nll]~ ERROR compilation successful
+fn main() { //~ ERROR compilation successful
     let mut v = vec![0, 1, 2];
     let shared = &v;
 
     v.push(shared.len());
-    //[lxl]~^  ERROR cannot borrow `v` as mutable because it is also borrowed as immutable [E0502]
 
     assert_eq!(v, [0, 1, 2, 3]);
 }
index 058022ad588e85beb9ceae07b977a9e0bfbf0146..1333167b780a8537f714a571c602046dc4b29ebc 100644 (file)
 
 // ignore-tidy-linelength
 
-// revisions: lxl_beyond nll_beyond nll_target
+// revisions: nll_beyond nll_target
 
 // The following revisions are disabled due to missing support from two-phase beyond autorefs
-//[lxl_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
-//[lxl_beyond] should-fail
-//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll
+//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
 //[nll_beyond] should-fail
 
-//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is a corner case that the current implementation is (probably)
 // treating more conservatively than is necessary. But it also does
@@ -46,9 +44,8 @@ fn main() {
         // with the shared borrow. But in the current implementation,
         // its an error.
         delay = &mut vec;
-        //[lxl_beyond]~^   ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
-        //[nll_beyond]~^^  ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
-        //[nll_target]~^^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
+        //[nll_beyond]~^  ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
+        //[nll_target]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
 
         shared[0];
     }
index 32747407c67f0195ee6516fca8a318a4c9de89df..eec4b470d75f76d3da7418442533b80cc49e0b4f 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lxl nll
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+// cmpile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is the first counter-example from Niko's blog post
 // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/
@@ -22,8 +20,7 @@ fn main() {
     v[0].push_str({
 
         v.push(format!("foo"));
-        //[lxl]~^ ERROR cannot borrow `v` as mutable more than once at a time [E0499]
-        //[nll]~^^   ERROR cannot borrow `v` as mutable more than once at a time [E0499]
+        //~^   ERROR cannot borrow `v` as mutable more than once at a time [E0499]
 
         "World!"
     });
index c2f157cd35cce82942e077ba8dbf7f63217322a8..583befed1e8287bf8d82f23f38a71f3e24a4a71b 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that we can't pass other types for !
 
+#![feature(never_type)]
+
 fn foo(x: !) -> ! {
     x
 }
index 0487b03171adbc2abd1e57fcb155309ac0baea43..5a05f59c6f402303676de7494218b99a260c5aa0 100644 (file)
@@ -22,6 +22,7 @@ fn double_mut_borrow<T>(x: &mut Box<T>) {
     let z = borrow_mut(x);
     //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time
     //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time
+    drop((y, z));
 }
 
 fn double_imm_borrow(x: &mut Box<i32>) {
@@ -30,6 +31,7 @@ fn double_imm_borrow(x: &mut Box<i32>) {
     **x += 1;
     //[ast]~^ ERROR cannot assign to `**x` because it is borrowed
     //[mir]~^^ ERROR cannot assign to `**x` because it is borrowed
+    drop((y, z));
 }
 
 fn double_mut_borrow2<T>(x: &mut Box<T>) {
index 5efb4dadc64bdafdcf02482ad3949f5d3e521483..14a06b306d82a93a8dc71a82c5f3cf54b8f43b43 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 fn foo(x: usize, y: !, z: usize) { }
 
 fn cast_a() {
index 15049232a4d3f4450a63795a444f5be2a674b583..62ff09f4616b80c7268bcefeb6aa954c1132a6fc 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 fn foo(x: usize, y: !, z: usize) { }
 
 fn call_foo_a() {
index 2f4d82e2ef514a43868df734d9ebf23677f7d675..5db901b5ba1c202e08570b239df0412eacd73dcc 100644 (file)
@@ -17,7 +17,7 @@
 #![feature(specialization)]
 
 trait Trait<T> { type Assoc; }
-//~^ cyclic dependency detected [E0391]
+//~^ cycle detected
 
 impl<T> Trait<T> for Vec<T> {
     type Assoc = ();
index 6218dcbf5f2c54ec5f86e5cd27db7fd5c105a372..fed8e1885de8a996296b37ce83cb1affc554262f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: cyclic dependency detected
+// error-pattern: cycle detected
 
 #![feature(const_fn)]
 
index ee4722c010f1660fe8e01555649da6c38e99cfef..56ad1771e00bd0f2a7403c7c75f7c68c15942720 100644 (file)
@@ -25,7 +25,7 @@
 struct A<T>
     where T : Trait,
           T : Add<T::Item>
-    //~^ ERROR cyclic dependency detected
+    //~^ ERROR cycle detected
     //~| ERROR associated type `Item` not found for `T`
 {
     data: T
index 88672088bcb4c279eb412c6a77f9ed3c77ff7bb5..b8bae2154566e584ca15bed75a0d515b7ea96103 100644 (file)
@@ -12,7 +12,7 @@
 // again references the trait.
 
 trait Foo<X = Box<Foo>> {
-    //~^ ERROR cyclic dependency detected
+    //~^ ERROR cycle detected
 }
 
 fn main() { }
index 626567ccc0ead54616644092ad8e295411cd9153..b802463fcb036dfa47dde3e0d6a7b158210869ad 100644 (file)
@@ -11,7 +11,7 @@
 // Test a supertrait cycle where a trait extends itself.
 
 trait Chromosome: Chromosome {
-    //~^ ERROR cyclic dependency detected
+    //~^ ERROR cycle detected
 }
 
 fn main() { }
index 798544f164932a59f84baab5e8ee6fb21c8f39a1..ac8ac85824edcc34783e3d161d76cdc9280f30f2 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// We need to opt inot the `!` feature in order to trigger the
+// requirement that this is testing.
+#![feature(never_type)]
+
 #![allow(unused)]
 
 trait Deserialize: Sized {
index fdc9b4f704cd16f4c988cb87f198291b3e46d27d..b304443f63145701d2294af7713e685cb6c25fc4 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Zedition=2015 -Zunstable-options
+// compile-flags: --edition=2015 -Zunstable-options
 
 // tests that editions work with the tyvar warning-turned-error
 
index 58b34591029ba98ee18542a695e7e797e1012264..d01cac019e36c8da18b0562a66060ce81e28468c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Zedition=2018 -Zunstable-options
+// compile-flags: --edition=2018 -Zunstable-options
 
 // tests that editions work with the tyvar warning-turned-error
 
index 4267103ab9a3aacae556f5a919e5f9bab8e449af..08269ce5c7ecf0d2083fb483d46868a69915ab7a 100644 (file)
@@ -10,7 +10,7 @@
 
 // #41719
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 fn main() {
     enum Foo {}
index 5f5b70dda5e8170fbe4e18035272a3ee95c102c9..e98cf4eb2abd92f3e09021c1860ef100d40b096c 100644 (file)
@@ -33,6 +33,7 @@ fn call_repeatedly<F>(f: F)
     f.call(&x);
     f.call(&x);
     x = 5;
+    drop(y);
 }
 
 fn main() {
index 25d0590db1b75dbd296bf1e91bf61692346a6639..42c80b54313d0f45217b849e5c91a38bcf4841e6 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 type x = Vec<x>;
-//~^ ERROR cyclic dependency detected
+//~^ ERROR cycle detected
 
 fn main() { let b: x = Vec::new(); }
index b9741e0add61ce17ea6325257bd474b37121a592..d11aacec1963169919de344b7bd762004d5d3058 100644 (file)
@@ -10,6 +10,7 @@
 
 // error-pattern:reached recursion limit
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 struct Foo<'a, T: 'a> {
index 88395e5f1eafa1240f99b1bf099a20829fa82538..d67c76a1525d51b55d280e4483fc43e5bf54d9d3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 trait T : Iterator<Item=Self::Item>
-//~^ ERROR cyclic dependency detected
+//~^ ERROR cycle detected
 //~| ERROR associated type `Item` not found for `Self`
 {}
 
index aeb798b382875a5a740297723b9160282a405498..cbb987cd512afb65ce78941a2d793d70cefeb230 100644 (file)
@@ -13,7 +13,7 @@ pub trait Subscriber {
 }
 
 pub trait Processor: Subscriber<Input = Self::Input> {
-    //~^ ERROR cyclic dependency detected [E0391]
+    //~^ ERROR cycle detected
     type Input;
 }
 
index 40c95b98f1264d4f9311cf5364a414c8e8b72a89..9da57877a09dcdfff59837ed46bed958ca682861 100644 (file)
@@ -14,7 +14,7 @@ trait Trait {
 }
 
 fn foo<T: Trait<A = T::B>>() { }
-//~^ ERROR cyclic dependency detected
+//~^ ERROR cycle detected
 //~| ERROR associated type `B` not found for `T`
 
 fn main() { }
index fde2d001542b84a1eda160b7fb62488440189fdb..2396007c3df3ed06ffe717f9132d77ed4ecf701e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 trait Expr : PartialEq<Self::Item> {
-    //~^ ERROR: cyclic dependency detected
+    //~^ ERROR: cycle detected
     type Item;
 }
 
index 16a650cc6d88632ed57d1c809377e756036f8773..aab674fbb1a44e11635b4a0adcc6035894164722 100644 (file)
@@ -8,11 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: cyclic dependency detected
-// note-pattern: the cycle begins when computing layout of
-// note-pattern: ...which then requires computing layout of
-// note-pattern: ...which then again requires computing layout of
-
+// error-pattern: cycle detected when computing layout of
+// note-pattern: ...which requires computing layout of
+// note-pattern: ...which again requires computing layout of
 
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
index b18e05af47c97266521065b5711c08e234b64aee..4d7238ad76f75acee3743086feb6639682c8c212 100644 (file)
@@ -14,8 +14,8 @@ trait Trait<T> {
     fn foo(_: T) {}
 }
 
-pub struct Foo<T = Box<Trait<DefaultFoo>>>;
-type DefaultFoo = Foo; //~ ERROR cyclic dependency detected
+pub struct Foo<T = Box<Trait<DefaultFoo>>>;  //~ ERROR cycle detected
+type DefaultFoo = Foo;
 
 fn main() {
 }
index fc3e0633750d8c29ddd7c86092fca49fccbed399..ed6a2f85fbe23a8bb963bf61732b64239649e2d9 100644 (file)
@@ -11,6 +11,8 @@
 // revisions: ast mir
 //[mir]compile-flags: -Z borrowck=mir
 
+// FIXME(#49821) -- No tip about using a let binding
+
 use std::cell::RefCell;
 
 fn main() {
@@ -24,10 +26,9 @@ fn main() {
     //[ast]~| NOTE temporary value does not live long enough
     //[ast]~| NOTE consider using a `let` binding to increase its lifetime
     //[mir]~^^^^^ ERROR borrowed value does not live long enough [E0597]
-    //[mir]~| NOTE temporary value dropped here while still borrowed
     //[mir]~| NOTE temporary value does not live long enough
-    //[mir]~| NOTE consider using a `let` binding to increase its lifetime
+    //[mir]~| NOTE temporary value only lives until here
     println!("{}", val);
+    //[mir]~^ borrow later used here
 }
 //[ast]~^ NOTE temporary value needs to live until here
-//[mir]~^^ NOTE temporary value needs to live until here
index c0af3b4b9e695a97289c42b5990af0cbf991c070..6fa65a541b39bdcc5a356df13cbb607564a970c4 100644 (file)
@@ -11,7 +11,7 @@
 fn xyz() -> u8 { 42 }
 
 const NUM: u8 = xyz();
-//~^ ERROR calls in constants are limited to constant functions, struct and enum constructors
+//~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants
 //~| ERROR constant evaluation error
 
 fn main() {
index 930a427e9a5e0ec7c58261bfb7516de5bb442b23..ecaf326b0504dde984f16c7f627a6074eb99d108 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// error-pattern: cycle detected when computing layout of
+
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 
@@ -15,7 +17,6 @@
 
 struct Foo {
     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-    //~^ ERROR cyclic dependency detected
     x: usize,
 }
 
diff --git a/src/test/compile-fail/issue-44578.rs b/src/test/compile-fail/issue-44578.rs
deleted file mode 100644 (file)
index 18cfb35..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo {
-    const AMT: usize;
-}
-
-enum Bar<A, B> {
-    First(A),
-    Second(B),
-}
-
-impl<A: Foo, B: Foo> Foo for Bar<A, B> {
-    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
-}
-
-impl Foo for u8 {
-    const AMT: usize = 1;
-}
-
-impl Foo for u16 {
-    const AMT: usize = 2;
-}
-
-fn main() {
-    println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ E0080
-}
index e0b847fc99470a68f8aefb78395a807db51f3c87..9a84322ad063b37a6927a3b665bc1e13f091a126 100644 (file)
@@ -7,6 +7,9 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
+// ignore-tidy-linelength
+
 #![feature(const_fn)]
 
 const bad : u32 = {
@@ -20,7 +23,7 @@
     {
         invalid();
         //~^ ERROR: blocks in constants are limited to items and tail expressions
-        //~^^ ERROR: calls in constants are limited to constant functions, struct and enum
+        //~^^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
         0
     }
 };
@@ -44,7 +47,7 @@
     {
         invalid();
         //~^ ERROR: blocks in statics are limited to items and tail expressions
-        //~^^ ERROR: calls in statics are limited to constant functions, struct and enum
+        //~^^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
         0
     }
 };
@@ -68,7 +71,7 @@
     {
         invalid();
         //~^ ERROR: blocks in statics are limited to items and tail expressions
-        //~^^ ERROR: calls in statics are limited to constant functions, struct and enum
+        //~^^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
         0
     }
 };
index 5ef46bb27fd60a4a772978a3abeee3e9e85adc14..938f7fba2a0324320b3616e4b68e8acc66ec5ce9 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 fn main() {
     let val: ! = loop { break break; };
     //~^ ERROR mismatched types
index 0f123997ca1d975560de09c9bcb3cd72f7c19686..6567a100d8c0664caedda024cc8b097dd9489514 100644 (file)
@@ -10,6 +10,8 @@
 
 // gate-test-use_extern_macros
 
+#![feature(proc_macro_path_invoc)]
+
 fn main() {
     globnar::brotz!(); //~ ERROR non-ident macro paths are experimental
     #[derive(foo::Bar)] struct T; //~ ERROR non-ident macro paths are experimental
index 7046ee12b50e563de83d718f08bf88486667e51a..40412087cef97b0e76e8a8f03774a8bc4295269e 100644 (file)
@@ -13,6 +13,7 @@
 
 #![feature(asm)]
 #![feature(trace_macros, concat_idents)]
+#![feature(proc_macro_path_invoc)]
 
 #[derive(Default)] //~ ERROR
 enum OrDeriveThis {}
index e18c7d77ce366ce974dd48046a07e8ed458ac010..8777ef2ffe33c9e5a774024438c9f4262373a56c 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 mod private {
index 6562efeb6d893a628b9ad646a2f001ccad2c21b2..d8f5956b585303847cde55e450d7aa96b1835070 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z borrowck=mir -Z nll
+// compile-flags: -Z borrowck=mir
 
 #![allow(dead_code)]
 
@@ -16,7 +16,7 @@ fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
     let g: fn(_, _) -> _ = |_x, y| y;
     //~^ ERROR free region `'b` does not outlive free region `'a`
     g
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
 }
 
 fn main() {}
index f6ad2820d17ce4d6e651eb1a88198e277767a61e..1f9174b3574a7bb57d0c5177eff5cc12067da4d7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z borrowck=mir -Z nll
+// compile-flags: -Zborrowck=mir
 
 #![allow(dead_code)]
 
@@ -44,7 +44,7 @@ fn bar<'a>(x: &'a u32) -> &'static u32 {
     // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2`
     // as part of checking the `ReifyFnPointer`.
     let f: fn(_) -> _ = foo;
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR free region `'a` does not outlive free region `'static`
     f(x)
 }
index c9b378dacd540cb7bfd283efbe2d895a1f5f780c..27ca2728ddfd623a5bb74f2b2710d3531206bba4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z borrowck=mir -Z nll
+// compile-flags: -Zborrowck=mir
 
 #![allow(dead_code)]
 
@@ -16,7 +16,7 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
     // Here the NLL checker must relate the types in `f` to the types
     // in `g`. These are related via the `UnsafeFnPointer` cast.
     let g: unsafe fn(_) -> _ = f;
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR free region `'a` does not outlive free region `'static`
     unsafe { g(input) }
 }
index 1df56793f73bdab5d5c30c07d6b40f56e4253639..e30bed610581503d7bcb0910eb5d539d0e596488 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z borrowck=mir -Z nll
+// compile-flags: -Z borrowck=mir
 
 #![allow(dead_code)]
 #![feature(dyn_trait)]
@@ -18,7 +18,7 @@
 fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
     //~^ ERROR free region `'a` does not outlive free region `'static`
     x
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
 }
 
 fn main() {}
index 72727cdfe54d2f56b7a9331b8436ef559b3588d7..a05ee64937eb7ede999fa221e564dcb18ce8dd21 100644 (file)
@@ -25,5 +25,6 @@ fn main() {
     // check borrowing is detected successfully
     let &mut ref x = foo;
     *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
-               //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed
+    //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed
+    drop(x);
 }
index 4e987d1ddce577a9c7548a76d16cf5e72b6d3c7c..0fb75b535c6bcd5df32de572ee474ba824089747 100644 (file)
@@ -10,6 +10,7 @@
 
 // Test that an assignment of type ! makes the rest of the block dead code.
 
+#![feature(never_type)]
 #![feature(rustc_attrs)]
 #![warn(unused)]
 
index 8c2de7d68d3de334dc849d08b1f0bdc07d0c955a..c0dd2cab749f4a24cf0753689a842b4bd33d9742 100644 (file)
@@ -10,6 +10,7 @@
 
 // Test that we can't use another type in place of !
 
+#![feature(never_type)]
 #![deny(warnings)]
 
 fn main() {
index fdc650a072131c4e4f1a46b34b1acab76ee3bec7..97126e98cbf3ad3ab09efb5401d057d15990ad68 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-// compile-flags:-Zborrowck=compare -Znll
+// compile-flags:-Zborrowck=compare
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
index f22d2fc23e0579eb691d73167a5967797206fa63..b5357d0ee827c100fbb1ebdaf9b2541036dad9a8 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-// compile-flags:-Zborrowck=compare -Znll
+// compile-flags:-Zborrowck=compare
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
index efa6cc273b6f4a66e32623fbcef67d1f92b73f5c..589a3daa38d853dc344b8bf2faa6602353ee9d33 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 //revisions: ast mir
-//[mir] compile-flags: -Z borrowck=mir -Z nll
+//[mir] compile-flags: -Z borrowck=mir
 
 #![allow(unused_assignments)]
 
index 1128d65af95c5832139ca934347dff5b4ef226e4..e1c47a6bbff2cea9b0bf3f20c7a16a7a590ab692 100644 (file)
@@ -12,7 +12,7 @@
 // in the type of `p` includes the points after `&v[0]` up to (but not
 // including) the call to `use_x`. The `else` branch is not included.
 
-// compile-flags:-Zborrowck=compare -Znll
+// compile-flags:-Zborrowck=compare
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
index 7ed59ef2a879b9fdb96fda2292d84a609e96da1f..13f1ca6431b3d8e4adf793ec5310cd16c3494040 100644 (file)
@@ -12,7 +12,7 @@
 // in the type of `p` includes the points after `&v[0]` up to (but not
 // including) the call to `use_x`. The `else` branch is not included.
 
-// compile-flags:-Zborrowck=compare -Znll
+// compile-flags:-Zborrowck=compare
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
index ecea8756903aeb9f694ef3830f3a1fa7ab20e2ef..1a3dc76005db4629f86595c575aef3e1e5641b04 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z borrowck=mir -Z nll
+// compile-flags: -Zborrowck=mir
 
 #![allow(dead_code)]
 
@@ -22,7 +22,7 @@ fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32)
 fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
     foo(x, y)
     //~^ ERROR lifetime mismatch [E0623]
-    //~| WARNING not reporting region error due to -Znll
+    //~| WARNING not reporting region error due to nll
 }
 
 fn main() {}
index f1a6dc48e13b80ed809652e7cb18c8042626dfcb..69f0f43af13425af0d5942286d4cefc3d1806a51 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z borrowck=mir -Z nll
+// compile-flags: -Z borrowck=mir
 
 #![allow(dead_code)]
 
@@ -22,7 +22,7 @@ struct Foo<'a: 'b, 'b> {
 fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
     Foo { x, y };
     //~^ ERROR lifetime mismatch [E0623]
-    //~| WARNING not reporting region error due to -Znll
+    //~| WARNING not reporting region error due to nll
 }
 
 fn main() {}
index 63cb6e82c259e0a88488b432b4d425db229bf041..b64829edaa218772d5f9f0404890a60387cbf368 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
+#![feature(proc_macro_path_invoc)]
 
 mod priv_nominal {
     pub struct Pub;
index bdc0c680a92bc161117743a3bd78179bb3219d33..062dc53361703741fcc8287430f2c097ec8ec6a6 100644 (file)
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 
+#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
index c25616c54354d9f0d856927e915e1f383f5c83ba..0dfa61a18ab8299a601cd0ef9d7bb6bbdef321c3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
index 0c393f02323ec04a3757f16aa641798c773227bb..97d6b470d33bb88be183cfb8b785eb3c6eec94a9 100644 (file)
@@ -18,6 +18,7 @@
 // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
 // error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
 
+#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro)]
 
 extern crate private_inferred_type as ext;
index 5af8b063c1629f12e0fb6c3f348337b1bef51357..dfc0107e07565635686f9562838d427d9bad3e90 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(associated_consts)]
 #![feature(decl_macro)]
 #![allow(private_in_public)]
+#![feature(proc_macro_path_invoc)]
 
 mod m {
     fn priv_fn() {}
index 6fbc65ce6a71f3a01729e240dab2abb9b1b27cbd..1f23dcbb72523baaeb6689d55fd7a144cfde4d58 100644 (file)
@@ -18,7 +18,8 @@ fn main() {
     match (&a1,) {
         (&ref b0,) => {
             a1 = &f; //[ast]~ ERROR cannot assign
-                     //[mir]~^ ERROR cannot assign to `a1` because it is borrowed
+            //[mir]~^ ERROR cannot assign to `a1` because it is borrowed
+            drop(b0);
         }
     }
 }
index 13f93090fbbb4fae5260fe6296d19cca0a8ca8bb..a0097b9f6d7df84ae0e3ce2e8e59cabc5bec13e0 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // revisions: ll nll
-//[nll] compile-flags: -Znll -Zborrowck=mir
+//[nll] compile-flags:-Zborrowck=mir
 
 fn static_id<'a,'b>(t: &'a ()) -> &'static ()
     where 'a: 'static { t }
@@ -17,16 +17,16 @@ fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
     where 'a: 'b, 'b: 'static { t }
 fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
     t //[ll]~ ERROR E0312
-        //[nll]~^ WARNING not reporting region error due to -Znll
+        //[nll]~^ WARNING not reporting region error due to nll
         //[nll]~| ERROR free region `'a` does not outlive free region `'static`
 }
 
 fn error(u: &(), v: &()) {
     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
-    //[nll]~^ WARNING not reporting region error due to -Znll
+    //[nll]~^ WARNING not reporting region error due to nll
     //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621]
     static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
-    //[nll]~^ WARNING not reporting region error due to -Znll
+    //[nll]~^ WARNING not reporting region error due to nll
     //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621]
 }
 
index 7210c857125d6d9e026acdc9273fed733dc26d95..2a894c57b8df19c5a83d9b131f7d0de6ffb90d06 100644 (file)
@@ -21,10 +21,10 @@ impl Tr for S where Self: Copy {} // OK
 impl Tr for S where S<Self>: Copy {} // OK
 impl Tr for S where Self::A: Copy {} // OK
 
-impl Tr for Self {} //~ ERROR cyclic dependency detected
-impl Tr for S<Self> {} //~ ERROR cyclic dependency detected
-impl Self {} //~ ERROR cyclic dependency detected
-impl S<Self> {} //~ ERROR cyclic dependency detected
-impl Tr<Self::A> for S {} //~ ERROR cyclic dependency detected
+impl Tr for Self {} //~ ERROR cycle detected
+impl Tr for S<Self> {} //~ ERROR cycle detected
+impl Self {} //~ ERROR cycle detected
+impl S<Self> {} //~ ERROR cycle detected
+impl Tr<Self::A> for S {} //~ ERROR cycle detected
 
 fn main() {}
index 365387c3e5e2759a51be7fe972a55d1a5fdb6253..0a0f9ce4bd10eb878a4b4a82dafdd4eea0085735 100644 (file)
@@ -15,7 +15,7 @@
 #![no_std]
 
 // OK
-#[lang = "str"]
+#[lang = "str_alloc"]
 impl str {}
 
 impl str {
index 72b0afa6bd3eea8bc04ddc24b49bdaad4c406f79..05a97b855e703e5fcd50b2b6c2567d3aaadb688e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 mod foo {
index e130df5c845b58fc309e50e3f2b0208e59427f53..2cf4b78bdffe40927b446c817e93fe903bc657c5 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
index dca79bdfb87f755e5d8490b5a23baba83e50776a..cfd829e416e5b6f4cef4c51e30ad6b026521685f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![deny(unreachable_patterns)]
 
index 0caf7d51234918b7c25eb1b148448b1d4ddd2cb6..df340095bb433477cbe3ddef4476a5decc89e70f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns, rustc_attrs)]
 #![warn(unreachable_code)]
 #![warn(unreachable_patterns)]
index 09288cf69ff586064efc7116894ccf6d5257dc89..f41b39845a579681bf5811aa2e9fcebc4deac32b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll
+// compile-flags:-Zborrowck=mir
 
 fn can_panic() -> Box<usize> {
     Box::new(44)
index 64ffc7446062cb171b7ced9ca4e792e0e16ce304..073b44d6e338763ef9a8a5d63d289469b7012d8f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll
+// compile-flags:-Zborrowck=mir
 
 #![allow(warnings)]
 
index 671f5e5292aa439029b6e98221ed7e51bb9da502..6a8749084068a30fa6afcd518b5a2b0cb1f14a44 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll
+// compile-flags:-Zborrowck=mir
 
 fn cond() -> bool { false }
 
index 8feac15d69a82a484b442589d047b18fb95c003b..5cca3e55259d0f874ff7b81fdd0af9a401a64b69 100644 (file)
@@ -13,8 +13,8 @@
 // suitable variables and that we setup the outlives relationship
 // between R0 and R1 properly.
 
-// compile-flags:-Znll -Zverbose
-//                     ^^^^^^^^^ force compiler to dump more region information
+// compile-flags:-Zborrowck=mir -Zverbose
+//                              ^^^^^^^^^ force compiler to dump more region information
 // ignore-tidy-linelength
 
 #![allow(warnings)]
index 92e42a73bbb6a9679fe764e804cf55d30acb6928..b7c8d81b77fdbaf91b0caeefda1d9c578731ebcb 100644 (file)
@@ -12,8 +12,8 @@
 // in the type of `r_a` must outlive the region (`R7`) that appears in
 // the type of `r_b`
 
-// compile-flags:-Znll -Zverbose
-//                     ^^^^^^^^^ force compiler to dump more region information
+// compile-flags:-Zborrowck=mir -Zverbose
+//                              ^^^^^^^^^ force compiler to dump more region information
 
 #![allow(warnings)]
 
index 19d733d4f6b6a8931bdc0a4d2b5617b970b7b85c..75d8a6a4f6ac55ca3b830ecf4a58b3e79a9bade7 100644 (file)
@@ -12,8 +12,8 @@
 // in the type of `p` includes the points after `&v[0]` up to (but not
 // including) the call to `use_x`. The `else` branch is not included.
 
-// compile-flags:-Znll -Zverbose
-//                     ^^^^^^^^^ force compiler to dump more region information
+// compile-flags:-Zborrowck=mir -Zverbose
+//                              ^^^^^^^^^ force compiler to dump more region information
 
 #![allow(warnings)]
 
index 821cd73667193afb145773501869b5755a5ab314..153739133ac82900258866451e2cdf16a1be753d 100644 (file)
@@ -14,8 +14,8 @@
 // but only at a particular point, and hence they wind up including
 // distinct regions.
 
-// compile-flags:-Znll -Zverbose
-//                     ^^^^^^^^^ force compiler to dump more region information
+// compile-flags:-Zborrowck=mir -Zverbose
+//                              ^^^^^^^^^ force compiler to dump more region information
 
 #![allow(warnings)]
 
index a3f68ed5ebf5eecd7f7f17d8bafb2bced9318296..16952143d0a5bc6a294682f139da8c89adbf6795 100644 (file)
@@ -12,8 +12,8 @@
 // in the type of `p` includes the points after `&v[0]` up to (but not
 // including) the call to `use_x`. The `else` branch is not included.
 
-// compile-flags:-Znll -Zverbose
-//                     ^^^^^^^^^ force compiler to dump more region information
+// compile-flags:-Zborrowck=mir -Zverbose
+//                              ^^^^^^^^^ force compiler to dump more region information
 
 #![allow(warnings)]
 
diff --git a/src/test/parse-fail/obsolete-proc.rs b/src/test/parse-fail/obsolete-proc.rs
deleted file mode 100644 (file)
index 648c46d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-// Test that we generate obsolete syntax errors around usages of `proc`.
-
-fn foo(p: proc()) { } //~ ERROR expected type, found reserved keyword `proc`
-
-fn bar() { proc() 1; } //~ ERROR expected expression, found reserved keyword `proc`
-
-fn main() { }
index 7a4b5e59eeb75ddad5474202c4af1d1fee0b9fc5..da68dc39f85d752f3273baa6bc6cbe787d37f8d0 100644 (file)
@@ -11,6 +11,9 @@
 // Test that a variable of type ! can coerce to another type.
 
 // error-pattern:explicit
+
+#![feature(never_type)]
+
 fn main() {
     let x: ! = panic!();
     let y: u32 = x;
index 56454586bb95773ef21bd88a848894c0d9812031..95101e70db95192aae510e6593b4a6175cbfa902 100644 (file)
@@ -12,6 +12,7 @@
 
 // error-pattern:wowzers!
 
+#![feature(never_type)]
 #![allow(unreachable_code)]
 
 fn foo(x: !) -> ! {
index 0155332c51d1b374676376aedf87b16de7b94b9c..8f7b0c40538f9dbd1c2a1e0080b28177cb85186b 100644 (file)
@@ -11,6 +11,9 @@
 // Test that we can explicitly cast ! to another type
 
 // error-pattern:explicit
+
+#![feature(never_type)]
+
 fn main() {
     let x: ! = panic!();
     let y: u32 = x as u32;
index d9b8461a1d07c4b2239daf7607d88bf14245dd73..fdd21e08c20f9ac0b3f5fda8935ac2326f37df0f 100644 (file)
@@ -12,6 +12,8 @@
 
 // error-pattern:kapow!
 
+#![feature(never_type)]
+
 trait Foo {
     type Wow;
 
index 0fe10d43910bfbf961e2dd8db234279bc5d114e8..826ca3a08c0e1dc5e67c30aa80b2c30fef3c33ac 100644 (file)
@@ -12,6 +12,8 @@
 
 // error-pattern:oh no!
 
+#![feature(never_type)]
+
 struct Wub;
 
 impl PartialEq<!> for Wub {
diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile
new file mode 100644 (file)
index 0000000..330ae30
--- /dev/null
@@ -0,0 +1,17 @@
+-include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(TARGET),wasm32-unknown-unknown)
+all:
+       $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg a
+       wc -c < $(TMPDIR)/foo.wasm
+       [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ]
+       $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg b
+       wc -c < $(TMPDIR)/foo.wasm
+       [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
+       $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c
+       wc -c < $(TMPDIR)/foo.wasm
+       [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
+else
+all:
+endif
+
diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs
new file mode 100644 (file)
index 0000000..1ea724c
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+#[cfg(a)]
+pub fn foo() {
+    panic!("test");
+}
+
+#[no_mangle]
+#[cfg(b)]
+pub fn foo() {
+    panic!("{}", 1);
+}
+
+#[no_mangle]
+#[cfg(c)]
+pub fn foo() {
+    panic!("{}", "a");
+}
index 281ee70815e11c80442dfce57c8735435ef49c9a..9e1ae59c01bc0f5006d21ca85e609a59ce0f11cf 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate proc_macro;
 
index cf6584e961a67a5997525be85d3488dc6dfbe628..a680698df9a2a11cd23b3d637665793ea3f06eac 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib)]
+#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)]
 
 extern crate proc_macro;
 
index d3670ae66feedf01ba43f5870b6b5131d3375afd..a280b3d87c68508262ba481fec353dfed4fc03d3 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib)]
+#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)]
 
 extern crate proc_macro;
 
index cff743bdae6cd485c756a145d2f5ad903a93b9da..52e8e75f2628e2297c238ab48468fc6a7aa98eee 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:cond_plugin.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate cond_plugin;
 
index eb77895e2d7ad6da63429583b983ee4321f19173..9bb8f691915c74fef5bda9d96d22f71e0cf38455 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:hello_macro.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc, proc_macro_non_items)]
 
 extern crate hello_macro;
 
index 2968cc7871d7e1ac04691b19e98401ec3772ada4..bf7ac507ea5705553ae396f63134a101eacd02b1 100644 (file)
@@ -12,7 +12,7 @@
 // ignore-stage1
 
 #![allow(warnings)]
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc)]
 
 extern crate attr_args;
 use attr_args::attr_with_args;
@@ -20,6 +20,6 @@
 #[attr_with_args(text = "Hello, world!")]
 fn foo() {}
 
-#[::attr_args::identity
-  fn main() { assert_eq!(foo(), "Hello, world!"); }]
+#[::attr_args::identity(
+  fn main() { assert_eq!(foo(), "Hello, world!"); })]
 struct Dummy;
index 52a8652e65bcf1158e556ba7dc8e28e5ae1f70b8..95e4f2211c63769f015b97f88ae45f7fdabb238a 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-on-trait.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc)]
 
 extern crate attr_on_trait;
 
index 98316c62ef135a0bf5dc4c8f4b429b5c230f0bc3..d928f8e557303747cc6f4322a9020acef65b54c4 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-stmt-expr.rs
 // ignore-stage1
 
-#![feature(proc_macro, stmt_expr_attributes)]
+#![feature(proc_macro, stmt_expr_attributes, proc_macro_stmt, proc_macro_expr)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr,
index 93815d16837d30fa40cda8ae9ee2f387ed41e44a..5f12cc96e9fb38ada53013ec5879df46516f7932 100644 (file)
@@ -20,7 +20,7 @@
 pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream {
     let args = args.to_string();
 
-    assert_eq!(args, r#"( text = "Hello, world!" )"#);
+    assert_eq!(args, r#"text = "Hello, world!""#);
 
     let input = input.to_string();
 
index 063d8dc40536dc5a737ca96020bafc1d8af0e2a9..5376d2740452fb1ae053f21a5162340312c5dcfb 100644 (file)
@@ -10,7 +10,7 @@
 
 // no-prefer-dynamic
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro;
index 055e4e2fad7af52c84f2fc5850ea6fc6969a2b79..b8562ffc344de8f62af03653f0d67f78ad9ef43e 100644 (file)
@@ -10,7 +10,7 @@
 
 // no-prefer-dynamic
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro as proc_macro_renamed; // This does not break `quote!`
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs
new file mode 100644 (file)
index 0000000..b3cd375
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn check(_a: TokenStream, b: TokenStream) -> TokenStream {
+    b.into_iter().collect()
+}
index ffa4731f1e6371b0153a9929298a8aebc8cdab89..82337022ac3bf4ddf910e92f293b0a21e656b175 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:bang-macro.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate bang_macro;
 use bang_macro::rewrite;
index 00ad0e76ed014c10c2bf8bcf2f1bf9b538d2fcfe..3fbe5366b6a1b839b88656176ed19b9a85c3099f 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:count_compound_ops.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate count_compound_ops;
 use count_compound_ops::count_compound_ops;
index 995dc65729a5059f8719c88ee9b3f7380886cc02..d4176c0efbf104bad6b9424356db2b30152fb658 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:derive-b.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc)]
 
 extern crate derive_b;
 
index 4cac7d19b4de8f2472d9fd78d4359bfbce414d61..48de15b934d23d679a2573bf0ca148c9760a87fe 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:hygiene_example.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate hygiene_example;
 use hygiene_example::hello;
index e53e94ae475b25f44dc378bfbf667da7315f9c99..a6b7d93c279d93db2037e3d7d18cca424a823dd2 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-42708.rs
 // ignore-stage1
 
-#![feature(decl_macro, proc_macro)]
+#![feature(decl_macro, proc_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 extern crate issue_42708;
diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs
new file mode 100644 (file)
index 0000000..03f69c0
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-50061.rs
+// ignore-stage1
+
+#![feature(proc_macro, proc_macro_path_invoc, decl_macro)]
+
+extern crate issue_50061;
+
+macro inner(any_token $v: tt) {
+    $v
+}
+
+macro outer($v: tt) {
+    inner!(any_token $v)
+}
+
+#[issue_50061::check]
+fn main() {
+    //! this doc comment forces roundtrip through a string
+    let checkit = 0;
+    outer!(checkit);
+}
index 418e692fa24ad18105ea64607509766c3e372f74..1cdf1daf560835af0b9775feaeee6a981421619c 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:negative-token.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate negative_token;
 
index cdda723585b7a850bb23de640358c26919ffb8b1..aad94c89f2ae3615c711bc632dd96272c497cb74 100644 (file)
@@ -12,7 +12,7 @@
 // ignore-stage1
 // ignore-cross-compile
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate proc_macro_def;
 
index d4fcdcf743bc676d6f20fa25a9acbea5fda8daed..12b115d09380e3f8a3dd1b0ffdb044dde8668d5d 100644 (file)
 
 #![feature(allocator_api, nonnull)]
 
-use std::alloc::{Alloc, Global};
+use std::alloc::{Alloc, Global, oom};
 
 fn main() {
     unsafe {
-        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| {
-            Global.oom()
-        });
+        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| oom());
         *ptr.as_ptr() = 4;
         assert_eq!(*ptr.as_ptr(), 4);
         Global.dealloc_one(ptr);
index 66234449263982ad635838fecdbb1da69df100e8..ca15591a10192deee48078ca565dca0c2691d391 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lxl nll
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // This is the "goto example" for why we want two phase borrows.
 
index a96f98b9efda96bed1c5d770d9e0f8c04a091345..723a98bcdfa0d85a894e7aea8d20739afdc0aff0 100644 (file)
@@ -14,6 +14,8 @@
 // These represent current behavior, but are pretty dubious.  I would
 // like to revisit these and potentially change them. --nmatsakis
 
+#![feature(never_type)]
+
 trait BadDefault {
     fn default() -> Self;
 }
index 87db440192984d3ea55709c771a8b0027c9eaf09..86cf9b5ec4783146db47f9b89b1fa0cf8cb15a18 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(slice_patterns)]
 #![allow(unreachable_patterns)]
index 3b6890cdce63bf1a1cec52841d502cbfb6453cbf..c4391ad05778a2a539445accf73a28cb53f07c57 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 macro m($S:ident, $x:ident) {
index 5e83f3808d8ccd9699eafa8da0b9f35f55ea248d..0cda0e7c7cce74cacac44747987a2a81a1c7e7fb 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 mod foo {
index 683a15b99aebea3116acb55803ee22c192ff0b8d..5395ef35882827b22c2c8a60c592f9e009f182f5 100644 (file)
@@ -12,7 +12,7 @@
 
 // aux-build:legacy_interaction.rs
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #[allow(unused)]
 
 extern crate legacy_interaction;
index cb02a17fec38a00298c6664ff864019f7f4d1308..73deda0777e50414984e7c89a5310409bba13d3d 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod bar {
     mod baz {
index 5520695021438a8d7f10ff24e7e840fc27bbe8ac..66e83eb7cacd57958205adde7a97365de0f98f39 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:my_crate.rs
 // aux-build:unhygienic_example.rs
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 extern crate unhygienic_example;
 extern crate my_crate; // (b)
index 6df3a34d3c87f0dd619081ca70db90d84ed63ead..95d7ae6db60ff165f7b91d9d4b95923a8f1281a9 100644 (file)
@@ -12,7 +12,7 @@
 
 // aux-build:xcrate.rs
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 extern crate xcrate;
 
index cf54e1c3bd598d6b4346c92dcc3a4c624b240412..794f5969bff507fbc04b2821e399522a5de85966 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that we can call static methods on ! both directly and when it appears in a generic
 
+#![feature(never_type)]
+
 trait StringifyType {
     fn stringify_type() -> &'static str;
 }
index b1db203071788cce72e3acf9e271c41897cdea06..e3b7322e48b6b93ac2b05050dc98417cdb818982 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // revisions: normal nll
-//[nll] compile-flags: -Znll -Zborrowck=mir
+//[nll] compile-flags:-Zborrowck=mir
 
 #![feature(fn_traits,
            step_trait,
index fb35ce33157d6ffcbbca6016373c1d839be0434f..ecd8a3390b75316cd47561651694b48acc78f94b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//`#[cfg]` on struct field permits empty unusable struct
+// `#[cfg]` on struct field permits empty unusable struct
 
 struct S {
     #[cfg(untrue)]
index a5a0a5a57944782c423033944f566f426ee28166..5cbd3446d9b6fe186bf6198b6f6d708cf7de94f0 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 // Regression test for inhabitedness check. The old
diff --git a/src/test/run-pass/issue-49973.rs b/src/test/run-pass/issue-49973.rs
new file mode 100644 (file)
index 0000000..641e923
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+#[derive(Debug)]
+#[repr(i32)]
+enum E {
+    Min = -2147483648i32,
+    _Max = 2147483647i32,
+}
+
+fn main() {
+    assert_eq!(Some(E::Min).unwrap() as i32, -2147483648i32);
+}
index ffdd99ebf6e5cf6688fea86109dd2c5d280866a6..39053769b24b59d9aff3ffb37128675726c760f0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 #[allow(unused)]
 fn never_returns() {
     loop {
index dda7a46f325850fb1e863f5b59e86cf609d14fc8..9641ed282936fafcbb6f178728a2b0a64b58f2d3 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(fn_traits)]
+#![feature(never_type)]
 
 use std::panic;
 
index 8aa2a13ed8c8d810b6a3cdb6ca405de69513cea7..5c0af392f44df27c659d6cebedccf666c1c4dee7 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that we can extract a ! through pattern matching then use it as several different types.
 
+#![feature(never_type)]
+
 fn main() {
     let x: Result<u32, !> = Ok(123);
     match x {
index 69f8906778a1694875313023aaf40e2896aadb57..2e87809a84ec5a9c82d806fb7baaa19383aeba6a 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 extern crate two_macros;
 
index 38cc23c16a9766a39ba4e979c14c55531ce30771..308792e5d8924782a13a8f812a9ce34465af4616 100644 (file)
@@ -13,9 +13,9 @@
 // Ideally this would be revised to use no_std, but for now it serves
 // well enough to reproduce (and illustrate) the bug from #16687.
 
-#![feature(heap_api, allocator_api, nonnull_cast)]
+#![feature(heap_api, allocator_api)]
 
-use std::alloc::{Global, Alloc, Layout};
+use std::alloc::{Global, Alloc, Layout, oom};
 use std::ptr::{self, NonNull};
 
 fn main() {
@@ -50,7 +50,7 @@ unsafe fn allocate(layout: Layout) -> *mut u8 {
             println!("allocate({:?})", layout);
         }
 
-        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| Global.oom());
+        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| oom());
 
         if PRINT {
             println!("allocate({:?}) = {:?}", layout, ret);
@@ -73,7 +73,7 @@ unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 {
         }
 
         let ret = Global.realloc(NonNull::new_unchecked(ptr).as_opaque(), old.clone(), new.size())
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
index 44be59f5c5b1a9ea39d3d4bedb21179021e05c4c..60a7f70931d48baf6bd17232fee5c4003d2f80aa 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(allocator_api)]
 
-use std::alloc::{Alloc, Global, Layout};
+use std::alloc::{Alloc, Global, Layout, oom};
 use std::ptr::NonNull;
 
 struct arena(());
@@ -33,7 +33,7 @@ struct Ccx {
 fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
     unsafe {
         let ptr = Global.alloc(Layout::new::<Bcx>())
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
         &*(ptr.as_ptr() as *const _)
     }
 }
index 3c54921ac6e02409d3811f65650dacd5e20453e1..139da046452646b77c1193c8f18691b3ae084a6d 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-emscripten
 
 #![feature(repr_simd, target_feature, cfg_target_feature)]
+#![feature(avx512_target_feature)]
 
 use std::process::{Command, ExitStatus};
 use std::env;
index 0bb18d8729a97d048bdce4fae8fba6cebb851f45..7bd9a1703ee9413710160c1b8529b64ddda505b9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 
 use std::mem::size_of;
 
diff --git a/src/test/rustdoc-js/alias-1.js b/src/test/rustdoc-js/alias-1.js
new file mode 100644 (file)
index 0000000..496bd55
--- /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.
+
+const QUERY = '&';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'reference' },
+    ],
+};
diff --git a/src/test/rustdoc-js/alias-2.js b/src/test/rustdoc-js/alias-2.js
new file mode 100644 (file)
index 0000000..f31786d
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = '+';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::ops::AddAssign', 'name': 'AddAssign' },
+        { 'path': 'std::ops::Add', 'name': 'Add' },
+    ],
+};
diff --git a/src/test/rustdoc-js/alias-3.js b/src/test/rustdoc-js/alias-3.js
new file mode 100644 (file)
index 0000000..d9e1ca5
--- /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.
+
+const QUERY = '!';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'never' },
+    ],
+};
diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js/alias.js
new file mode 100644 (file)
index 0000000..a0500f2
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = '[';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'slice' },
+        { 'path': 'std::ops::IndexMut', 'name': 'IndexMut' },
+        { 'path': 'std::ops::Index', 'name': 'Index' },
+    ],
+};
diff --git a/src/test/rustdoc-js/multi-query.js b/src/test/rustdoc-js/multi-query.js
new file mode 100644 (file)
index 0000000..3793ca6
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = 'str,u8';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'str' },
+        { 'path': 'std', 'name': 'u8' },
+        { 'path': 'std::ffi', 'name': 'CStr' },
+        { 'path': 'std::simd', 'name': 'u8x2' },
+    ],
+};
diff --git a/src/test/rustdoc-js/never.js b/src/test/rustdoc-js/never.js
new file mode 100644 (file)
index 0000000..d9e1ca5
--- /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.
+
+const QUERY = '!';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'never' },
+    ],
+};
diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs
new file mode 100644 (file)
index 0000000..2a00d31
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+//! Test with [Foo::baz], [Bar::foo], [Uniooon::X]
+
+pub struct Foo {
+    pub bar: usize,
+}
diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr
new file mode 100644 (file)
index 0000000..67d7bdd
--- /dev/null
@@ -0,0 +1,6 @@
+warning: [Foo::baz] cannot be resolved, ignoring it...
+
+warning: [Bar::foo] cannot be resolved, ignoring it...
+
+warning: [Uniooon::X] cannot be resolved, ignoring it...
+
index ec391319b183ce48475f7dd1d885e418bf3b9a3f..1969cf859eee4c8e9a50f89b0ea78c5152e341c1 100644 (file)
@@ -28,3 +28,11 @@ pub union Union {
 pub const CONST: u32 = 0;
 pub static STATIC: &str = "baguette";
 pub fn function() {}
+
+mod private_module {
+    pub struct ReexportedStruct;
+}
+
+// @has foo/all.html '//a[@href="struct.ReexportedStruct.html"]' 'ReexportedStruct'
+// @!has foo/all.html 'private_module'
+pub use private_module::ReexportedStruct;
index 50c31d309eec1fab7193039b0b27d610fd18630f..ee0a5c1aa1b5eb88e1ee810e56ffbf9f1f9d24cb 100644 (file)
@@ -14,7 +14,7 @@
 pub mod str {
     #![doc(primitive = "str")]
 
-    #[lang = "str"]
+    #[lang = "str_alloc"]
     impl str {
         // @has search-index.js foo
         pub fn foo(&self) {}
index 4c71afbac4df100a84f3ae0bea7ad28920ae4018..f938700e5157a282bf8950612845b07895a24981 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:parent-source-spans.rs
 // ignore-stage1
 
-#![feature(proc_macro, decl_macro)]
+#![feature(proc_macro, decl_macro, proc_macro_non_items)]
 
 extern crate parent_source_spans;
 
index ef2d160529068b76899f850a7d5083961adda5f3..66e34afcb13f92220644a8885f310021369ac1df 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:three-equals.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate three_equals;
 
index 052575de4c267944372854ee0be5b0d2943aa1d6..75b60aa8d10b7b392033577ec1c78cb197b1969f 100644 (file)
@@ -31,5 +31,5 @@ trait Add<RHS=Self> {
 fn ice<A>(a: A) {
     let r = loop {};
     r = r + a;
-    //~^ ERROR the trait bound `!: Add<A>` is not satisfied
+    //~^ ERROR the trait bound `(): Add<A>` is not satisfied
 }
index c22a645385adede474544b3b89c35359a6c50684..7924ab74444065190b82382e7bf4a606ea90853e 100644 (file)
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `!: Add<A>` is not satisfied
+error[E0277]: the trait bound `(): Add<A>` is not satisfied
   --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:33:11
    |
 LL |     r = r + a;
-   |           ^ the trait `Add<A>` is not implemented for `!`
+   |           ^ the trait `Add<A>` is not implemented for `()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr
deleted file mode 100644 (file)
index a21a6e3..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:24:24
-   |
-LL |     let c1 = to_fn_mut(|| x = 4);
-   |                        -- - previous borrow occurs due to use of `x` in closure
-   |                        |
-   |                        first mutable borrow occurs here
-LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
-   |                        ^^ - borrow occurs due to use of `x` in closure
-   |                        |
-   |                        second mutable borrow occurs here
-LL |     //~| ERROR cannot borrow `x` as mutable more than once
-LL | }
-   | - first borrow ends here
-
-error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:35:24
-   |
-LL |     let c1 = to_fn_mut(|| set(&mut x));
-   |                        --          - previous borrow occurs due to use of `x` in closure
-   |                        |
-   |                        first mutable borrow occurs here
-LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
-   |                        ^^          - borrow occurs due to use of `x` in closure
-   |                        |
-   |                        second mutable borrow occurs here
-LL |     //~| ERROR cannot borrow `x` as mutable more than once
-LL | }
-   | - first borrow ends here
-
-error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:42:24
-   |
-LL |     let c1 = to_fn_mut(|| x = 5);
-   |                        -- - previous borrow occurs due to use of `x` in closure
-   |                        |
-   |                        first mutable borrow occurs here
-LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
-   |                        ^^          - borrow occurs due to use of `x` in closure
-   |                        |
-   |                        second mutable borrow occurs here
-LL |     //~| ERROR cannot borrow `x` as mutable more than once
-LL | }
-   | - first borrow ends here
-
-error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:49:24
-   |
-LL |     let c1 = to_fn_mut(|| x = 5);
-   |                        -- - previous borrow occurs due to use of `x` in closure
-   |                        |
-   |                        first mutable borrow occurs here
-LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
-   |                        ^^                                  - borrow occurs due to use of `x` in closure
-   |                        |
-   |                        second mutable borrow occurs here
-...
-LL | }
-   | - first borrow ends here
-
-error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:61:24
-   |
-LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
-   |                        --           - previous borrow occurs due to use of `x` in closure
-   |                        |
-   |                        first mutable borrow occurs here
-LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
-   |                        ^^           - borrow occurs due to use of `x` in closure
-   |                        |
-   |                        second mutable borrow occurs here
-...
-LL | }
-   | - first borrow ends here
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0499`.
index b6946154fa00a0a5870c495b172305b8cf2657fd..55e73af9e6a1ba06f1a6616b76e5a46ad547d5ec 100644 (file)
@@ -23,6 +23,7 @@ fn a() {
     let c1 = to_fn_mut(|| x = 4);
     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
     //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
 }
 
 fn set(x: &mut isize) {
@@ -34,6 +35,7 @@ fn b() {
     let c1 = to_fn_mut(|| set(&mut x));
     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
     //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
 }
 
 fn c() {
@@ -41,6 +43,7 @@ fn c() {
     let c1 = to_fn_mut(|| x = 5);
     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
     //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
 }
 
 fn d() {
@@ -49,6 +52,7 @@ fn d() {
     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
     //~^ ERROR cannot borrow `x` as mutable more than once
     //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
 }
 
 fn g() {
@@ -61,6 +65,7 @@ struct Foo {
     let c2 = to_fn_mut(|| set(&mut *x.f));
     //~^ ERROR cannot borrow `x` as mutable more than once
     //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
 }
 
 fn main() {
index c739165ddbd3734568b45d54d6170a06531abc81..a4f8e8b408ba501b15e6783764e00a01b8e309f0 100644 (file)
@@ -9,12 +9,12 @@ LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo
    |                        ^^ - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
-LL |     //~| ERROR cannot borrow `x` as mutable more than once
+...
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:35:24
+  --> $DIR/borrowck-closures-two-mut.rs:36:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut x));
    |                        --          - previous borrow occurs due to use of `x` in closure
@@ -24,12 +24,12 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        ^^          - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
-LL |     //~| ERROR cannot borrow `x` as mutable more than once
+...
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:42:24
+  --> $DIR/borrowck-closures-two-mut.rs:44:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
    |                        -- - previous borrow occurs due to use of `x` in closure
@@ -39,12 +39,12 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        ^^          - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
-LL |     //~| ERROR cannot borrow `x` as mutable more than once
+...
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:49:24
+  --> $DIR/borrowck-closures-two-mut.rs:52:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
    |                        -- - previous borrow occurs due to use of `x` in closure
@@ -59,7 +59,7 @@ LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
-  --> $DIR/borrowck-closures-two-mut.rs:61:24
+  --> $DIR/borrowck-closures-two-mut.rs:65:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
    |                        --           - previous borrow occurs due to use of `x` in closure
@@ -85,11 +85,11 @@ LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo
    |                        |
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
-LL | }
-   | - first borrow ends here
+LL |     drop((c1, c2));
+   |           -- borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
-  --> $DIR/borrowck-closures-two-mut.rs:35:24
+  --> $DIR/borrowck-closures-two-mut.rs:36:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut x));
    |                        --          - previous borrow occurs due to use of `x` in closure
@@ -100,11 +100,11 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        |
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
-LL | }
-   | - first borrow ends here
+LL |     drop((c1, c2));
+   |           -- borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
-  --> $DIR/borrowck-closures-two-mut.rs:42:24
+  --> $DIR/borrowck-closures-two-mut.rs:44:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
    |                        -- - previous borrow occurs due to use of `x` in closure
@@ -115,11 +115,11 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        |
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
-LL | }
-   | - first borrow ends here
+LL |     drop((c1, c2));
+   |           -- borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
-  --> $DIR/borrowck-closures-two-mut.rs:49:24
+  --> $DIR/borrowck-closures-two-mut.rs:52:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
    |                        -- - previous borrow occurs due to use of `x` in closure
@@ -130,11 +130,11 @@ LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nes
    |                        |
    |                        second mutable borrow occurs here
 ...
-LL | }
-   | - first borrow ends here
+LL |     drop((c1, c2));
+   |           -- borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
-  --> $DIR/borrowck-closures-two-mut.rs:61:24
+  --> $DIR/borrowck-closures-two-mut.rs:65:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
    |                        --           - previous borrow occurs due to use of `x` in closure
@@ -145,8 +145,8 @@ LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
    |                        |
    |                        second mutable borrow occurs here
 ...
-LL | }
-   | - first borrow ends here
+LL |     drop((c1, c2));
+   |           -- borrow later used here
 
 error: aborting due to 10 previous errors
 
index ecd17edb079f13afdc0a3cab6eb59b38e163a0be..1aec71fee347b397665b502ffb44f1d9d6238eb6 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/issue-45983.rs:17:27
    |
 LL |     give_any(|y| x = Some(y));
@@ -16,7 +16,7 @@ error[E0594]: cannot assign to immutable item `x`
 LL |     give_any(|y| x = Some(y));
    |                  ^^^^^^^^^^^ cannot mutate
    |
-   = note: Value not mutable causing this error: `x`
+   = note: the value which is causing this path not to be mutable is...: `x`
 
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/issue-45983.rs:17:14
index c55c49604d0083a4012a68edb7343ea0831d89cf..84c6236eb0ae87c0e7c4f53cac0c8d45af014fd2 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/issue-7573.rs:27:31
    |
 LL |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
index d34a716bb2b306bf7bf861de382470d609cd7062..ee3970aa8fd8f09425b01ea1c46d043d462f2c94 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/regions-escape-bound-fn-2.rs:18:27
    |
 LL |     with_int(|y| x = Some(y));
index b69c172bcdc2320f51f89bee55e3dd7ddfd880ec..07a4ab1dbb1abc5f16f25fcc207c315af7fd5125 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/regions-escape-bound-fn.rs:18:22
    |
 LL |     with_int(|y| x = Some(y));
index 788654a2ecc033e81996a05478e4fc38bfa50d29..14c255ef52778f249b5b46a470fad71beac3852e 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/regions-escape-unboxed-closure.rs:16:27
    |
 LL |     with_int(&mut |y| x = Some(y));
index e690263a916f3cf5f42750f229a1fb8f424b25eb..6d7ed61bdd8b550073f324894a7912a07c700e22 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lxl nll
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // run-pass
 
index e1ed41bfb2c64cb97e9fd3bf92ed672e3cc518ca..9ea9696511b7194ba0e330dfc8e9e69137ad4535 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lxl nll
-//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
-//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
 
 // run-pass
 
index 2083ada6d2de5481b7177e8f246ffceadcdc9cad..671d77efbea3aac7f50850cdfef324cbdb481415 100644 (file)
@@ -15,6 +15,15 @@ trait Foo { }
 #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
 impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
 
+trait Bar {
+    type Assoc;
+}
+
+impl<T> Bar for T where T: Iterator<Item = i32> {
+    #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :-
+    type Assoc = Vec<T>;
+}
+
 fn main() {
     println!("hello");
 }
index b5d791d640ada9dcd79a4c07aff37b2e845f90fa..f253f9847d16294bc9fe39e55bb6c68e9351ee51 100644 (file)
@@ -4,5 +4,11 @@ error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i
 LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
+  --> $DIR/lower_impl.rs:23:5
+   |
+LL |     #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :-
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
index 18edf2addc53d4cf8d6ac16f10778007a27c08af..bbae80e16abde58b1914acc0b9fea094c062561c 100644 (file)
@@ -1,22 +1,22 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/expect-region-supply-region.rs:28:13
    |
 LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
    |             ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/expect-region-supply-region.rs:38:13
    |
 LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
    |             ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/expect-region-supply-region.rs:47:33
    |
 LL |     closure_expecting_bound(|x: &'x u32| {
    |                                 ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/expect-region-supply-region.rs:52:13
    |
 LL |         f = Some(x);
index 324bcf60e8ff60d1c2c117b779712af6ce3db47d..e059c354d65a73151a3d06d8d9b57077cc1e59dd 100644 (file)
@@ -8,11 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-pass
+
 const X: u32 = 5;
 const Y: u32 = 6;
 const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
 //~^ WARN attempt to subtract with overflow
 
 fn main() {
-    println!("{}", FOO); //~ E0080
+    println!("{}", FOO);
+    //~^ WARN constant evaluation error
 }
index 9270dafbe651a4cd6d72220a42cd43cfacf5a841..fd29990fec295abd5c0d807b663020bec0c72a26 100644 (file)
@@ -1,17 +1,14 @@
 warning: attempt to subtract with overflow
-  --> $DIR/conditional_array_execution.rs:13:19
+  --> $DIR/conditional_array_execution.rs:15:19
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ^^^^^
    |
    = note: #[warn(const_err)] on by default
 
-error[E0080]: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:17:20
+warning: constant evaluation error
+  --> $DIR/conditional_array_execution.rs:19:20
    |
-LL |     println!("{}", FOO); //~ E0080
+LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/const_signed_pat.rs b/src/test/ui/const-eval/const_signed_pat.rs
new file mode 100644 (file)
index 0000000..f53d6f3
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+fn main() {
+    const MIN: i8 = -5;
+    match 5i8 {
+        MIN...-1 => {},
+        _ => {},
+    }
+}
index d5c4796d0b497f86d8f98b545291b0e94e2cc2a4..b27791ef5337b7c7039d1005e2464e5b452521d5 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-pass
+
 #![feature(const_fn)]
 
 const fn foo(x: u32) -> u32 {
@@ -20,6 +22,6 @@ fn main() {
     const Y: u32 = foo(0-1);
     //~^ WARN attempt to subtract with overflow
     println!("{} {}", X, Y);
-    //~^ ERROR constant evaluation error
-    //~| ERROR constant evaluation error
+    //~^ WARN constant evaluation error
+    //~| WARN constant evaluation error
 }
index 2d51e6603b59bc335caf86bced103ed26ef44e3c..5da47a85eb803f3b1b79e8179d72b93856dfa020 100644 (file)
@@ -1,29 +1,26 @@
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:18:20
+  --> $DIR/issue-43197.rs:20:20
    |
 LL |     const X: u32 = 0-1;
    |                    ^^^
    |
    = note: #[warn(const_err)] on by default
 
-error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:22:23
+warning: constant evaluation error
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:20:24
+  --> $DIR/issue-43197.rs:22:24
    |
 LL |     const Y: u32 = foo(0-1);
    |                        ^^^
 
-error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:22:26
+warning: constant evaluation error
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-44578.rs b/src/test/ui/const-eval/issue-44578.rs
new file mode 100644 (file)
index 0000000..765113c
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+trait Foo {
+    const AMT: usize;
+}
+
+enum Bar<A, B> {
+    First(A),
+    Second(B),
+}
+
+impl<A: Foo, B: Foo> Foo for Bar<A, B> {
+    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+}
+
+impl Foo for u8 {
+    const AMT: usize = 1;
+}
+
+impl Foo for u16 {
+    const AMT: usize = 2;
+}
+
+fn main() {
+    println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+    //~^ WARN const_err
+}
diff --git a/src/test/ui/const-eval/issue-44578.stderr b/src/test/ui/const-eval/issue-44578.stderr
new file mode 100644 (file)
index 0000000..01c6fa3
--- /dev/null
@@ -0,0 +1,14 @@
+warning: constant evaluation error
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: constant evaluation error
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
diff --git a/src/test/ui/const-eval/promoted_errors.rs b/src/test/ui/const-eval/promoted_errors.rs
new file mode 100644 (file)
index 0000000..dc30c7f
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// compile-flags: -O
+fn main() {
+    println!("{}", 0u32 - 1);
+    //~^ WARN const_err
+    //~| WARN const_err
+    let _x = 0u32 - 1;
+    //~^ WARN const_err
+    println!("{}", 1/(1-1));
+    //~^ WARN const_err
+    //~| WARN const_err
+    let _x = 1/(1-1);
+    //~^ WARN const_err
+    //~| WARN const_err
+    println!("{}", 1/(false as u32));
+    //~^ WARN const_err
+    let _x = 1/(false as u32);
+}
diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr
new file mode 100644 (file)
index 0000000..a5db8cc
--- /dev/null
@@ -0,0 +1,50 @@
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:14:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^ attempted to do overflowing math
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:14:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^ attempted to do overflowing math
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:17:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^ attempted to do overflowing math
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:19:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:19:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^ attempted to do overflowing math
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:22:14
+   |
+LL |     let _x = 1/(1-1);
+   |              ^^^^^^^
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:22:14
+   |
+LL |     let _x = 1/(1-1);
+   |              ^^^^^^^ attempted to do overflowing math
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:25:20
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^ attempted to do overflowing math
+
index 077c4d60e649c3cd4240111035520355abbe49ad..767f28ff7b190e283426d7b214dc049c0b11d274 100644 (file)
@@ -4,7 +4,7 @@ error[E0016]: blocks in constant functions are limited to items and tail express
 LL |     let mut sum = 0;
    |                   ^
 
-error[E0015]: calls in constant functions are limited to constant functions, struct and enum constructors
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
   --> $DIR/const-fn-error.rs:18:14
    |
 LL |     for i in 0..x {
index 447505e886f81ef07a4684d351d78167fa6f9686..f240a34817db5ff8c20e1247ffd182695fadb78c 100644 (file)
@@ -15,10 +15,9 @@ trait A: B {
 }
 
 trait B: C {
+    //~^ ERROR cycle detected
 }
 
 trait C: B { }
-    //~^ ERROR cyclic dependency detected
-    //~| cyclic reference
 
 fn main() { }
index 68c20df5f72179f8e8dbde89c9f1555c4e6761db..85681b478e21df537afe9fade5f8fe5594836be0 100644 (file)
@@ -1,20 +1,20 @@
-error[E0391]: cyclic dependency detected
-  --> $DIR/cycle-trait-supertrait-indirect.rs:20:1
+error[E0391]: cycle detected when computing the supertraits of `B`
+  --> $DIR/cycle-trait-supertrait-indirect.rs:17:1
    |
-LL | trait C: B { }
-   | ^^^^^^^^^^ cyclic reference
+LL | trait B: C {
+   | ^^^^^^^^^^
    |
-note: the cycle begins when computing the supertraits of `B`...
-  --> $DIR/cycle-trait-supertrait-indirect.rs:14:1
+note: ...which requires computing the supertraits of `C`...
+  --> $DIR/cycle-trait-supertrait-indirect.rs:21:1
    |
-LL | trait A: B {
+LL | trait C: B { }
    | ^^^^^^^^^^
-note: ...which then requires computing the supertraits of `C`...
-  --> $DIR/cycle-trait-supertrait-indirect.rs:17:1
+   = note: ...which again requires computing the supertraits of `B`, completing the cycle
+note: cycle used when computing the supertraits of `A`
+  --> $DIR/cycle-trait-supertrait-indirect.rs:14:1
    |
-LL | trait B: C {
+LL | trait A: B {
    | ^^^^^^^^^^
-   = note: ...which then again requires computing the supertraits of `B`, completing the cycle.
 
 error: aborting due to previous error
 
index afdc26a75c73f6471f593c92d125f5549a704eee..81f858f6bfcb007096c57418768bc0445c02971f 100644 (file)
@@ -1,3 +1,9 @@
+error[E0596]: cannot borrow immutable item `self` as mutable
+  --> $DIR/issue-34126.rs:16:18
+   |
+LL |         self.run(&mut self); //~ ERROR cannot borrow
+   |                  ^^^^^^^^^ cannot borrow as mutable
+
 error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
   --> $DIR/issue-34126.rs:16:18
    |
@@ -8,6 +14,7 @@ LL |         self.run(&mut self); //~ ERROR cannot borrow
    |         immutable borrow occurs here
    |         borrow later used here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0502`.
+Some errors occurred: E0502, E0596.
+For more information about an error, try `rustc --explain E0502`.
index 7b5f452d32217ebab437c510b33ffb38eabb456f..40b640b63cf32deee09ec1d4e3e8ac8b6f899fd9 100644 (file)
@@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `f.v` as mutable
 LL |     f.v.push("cat".to_string()); //~ ERROR cannot borrow
    |     ^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `f`
+   = note: the value which is causing this path not to be mutable is...: `f`
 
 error[E0384]: cannot assign twice to immutable variable `s.x`
   --> $DIR/issue-35937.rs:26:5
index 099479eaf2b6b22e43c2e3766260a6173c56066d..8e4426779517c74782bc6e05eb38901e3138f18b 100644 (file)
@@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `*self.s` as mutable
 LL |         self.s.push('x'); //~ ERROR cannot borrow data mutably
    |         ^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*self`
+   = note: the value which is causing this path not to be mutable is...: `*self`
 
 error: aborting due to previous error
 
index 5649fc903a07884c0dad7defd1457f3609eb6fc1..6808222cc3241356a46583ebf4b159b772cd84d7 100644 (file)
@@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `*f.s` as mutable
 LL |     f.s.push('x'); //~ ERROR cannot borrow data mutably
    |     ^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*f`
+   = note: the value which is causing this path not to be mutable is...: `*f`
 
 error: aborting due to previous error
 
index 6e57796aa45c75f97c1f80b5104ef08584b783a0..f5f5b675e7727b53d90096a75084975ed066da0b 100644 (file)
@@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `z.x` as mutable
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `z`
+   = note: the value which is causing this path not to be mutable is...: `z`
 
 error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:26:17
@@ -12,7 +12,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*self`
+   = note: the value which is causing this path not to be mutable is...: `*self`
 
 error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:30:17
@@ -20,7 +20,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*self`
+   = note: the value which is causing this path not to be mutable is...: `*self`
 
 error[E0596]: cannot borrow immutable item `other.x` as mutable
   --> $DIR/issue-39544.rs:31:17
@@ -28,7 +28,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*other`
+   = note: the value which is causing this path not to be mutable is...: `*other`
 
 error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:35:17
@@ -36,7 +36,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*self`
+   = note: the value which is causing this path not to be mutable is...: `*self`
 
 error[E0596]: cannot borrow immutable item `other.x` as mutable
   --> $DIR/issue-39544.rs:36:17
@@ -44,7 +44,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*other`
+   = note: the value which is causing this path not to be mutable is...: `*other`
 
 error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:40:17
@@ -52,7 +52,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*self`
+   = note: the value which is causing this path not to be mutable is...: `*self`
 
 error[E0596]: cannot borrow immutable item `other.x` as mutable
   --> $DIR/issue-39544.rs:41:17
@@ -60,7 +60,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*other`
+   = note: the value which is causing this path not to be mutable is...: `*other`
 
 error[E0596]: cannot borrow immutable item `other.x` as mutable
   --> $DIR/issue-39544.rs:45:17
@@ -68,7 +68,7 @@ error[E0596]: cannot borrow immutable item `other.x` as mutable
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*other`
+   = note: the value which is causing this path not to be mutable is...: `*other`
 
 error[E0596]: cannot borrow immutable item `z.x` as mutable
   --> $DIR/issue-39544.rs:51:13
@@ -76,7 +76,7 @@ error[E0596]: cannot borrow immutable item `z.x` as mutable
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `z`
+   = note: the value which is causing this path not to be mutable is...: `z`
 
 error[E0596]: cannot borrow immutable item `w.x` as mutable
   --> $DIR/issue-39544.rs:52:13
@@ -84,7 +84,7 @@ error[E0596]: cannot borrow immutable item `w.x` as mutable
 LL |     let _ = &mut w.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*w`
+   = note: the value which is causing this path not to be mutable is...: `*w`
 
 error[E0594]: cannot assign to immutable item `*x.0`
   --> $DIR/issue-39544.rs:58:5
index a9f747d09ec2dd7b4cb15ae8a184ccda312b383d..ed9033ad53d565f0314f1d714004c60226a7da02 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(try_from)]
+
 use std::marker::PhantomData;
 use std::convert::{TryFrom, AsRef};
 
index 417ff1de3f8173ff958459981f405225f673dafa..e8b2c84c0df0bbd11f7db7a7da0e8365168ce2ff 100644 (file)
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `std::convert::AsRef<Q>` for type `std::boxed::Box<Q>`:
-  --> $DIR/conflict-with-std.rs:15:1
+  --> $DIR/conflict-with-std.rs:17:1
    |
 LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
              where T: ?Sized;
 
 error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`:
-  --> $DIR/conflict-with-std.rs:22:1
+  --> $DIR/conflict-with-std.rs:24:1
    |
 LL | impl From<S> for S { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | impl From<S> for S { //~ ERROR conflicting implementations
            - impl<T> std::convert::From<T> for T;
 
 error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X`:
-  --> $DIR/conflict-with-std.rs:29:1
+  --> $DIR/conflict-with-std.rs:31:1
    |
 LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^^^^
index 13ba653a5cad85ca6519d9f9535d32d2dd2768a5..0525e16239d2cb606f8fa29442cb7dc30895bcd1 100644 (file)
@@ -1,10 +1,10 @@
-error[E0594]: cannot assign to immutable item `fancy_ref.num`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/E0389.rs:18:5
    |
+LL |     let fancy_ref = &(&mut fancy);
+   |                     ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)`
 LL |     fancy_ref.num = 6; //~ ERROR E0389
-   |     ^^^^^^^^^^^^^^^^^ cannot mutate
-   |
-   = note: Value not mutable causing this error: `*fancy_ref`
+   |     ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written
 
 error: aborting due to previous error
 
index e9f0979569176d1629b0cd261348da844395fadd..5ae6afa7b17e274255daa5e811637a9c99fb7236 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5
    |
 LL |     invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
diff --git a/src/test/ui/feature-gate-cfg-target-feature.rs b/src/test/ui/feature-gate-cfg-target-feature.rs
deleted file mode 100644 (file)
index 7832e1c..0000000
+++ /dev/null
@@ -1,21 +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.
-
-#[cfg(target_feature = "x")] //~ ERROR `cfg(target_feature)` is experimental
-#[cfg_attr(target_feature = "x", x)] //~ ERROR `cfg(target_feature)` is experimental
-struct Foo(u64, u64);
-
-#[cfg(not(any(all(target_feature = "x"))))] //~ ERROR `cfg(target_feature)` is experimental
-fn foo() {}
-
-fn main() {
-    cfg!(target_feature = "x");
-    //~^ ERROR `cfg(target_feature)` is experimental and subject to change
-}
diff --git a/src/test/ui/feature-gate-cfg-target-feature.stderr b/src/test/ui/feature-gate-cfg-target-feature.stderr
deleted file mode 100644 (file)
index bf9e596..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
-  --> $DIR/feature-gate-cfg-target-feature.rs:12:12
-   |
-LL | #[cfg_attr(target_feature = "x", x)] //~ ERROR `cfg(target_feature)` is experimental
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-
-error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
-  --> $DIR/feature-gate-cfg-target-feature.rs:11:7
-   |
-LL | #[cfg(target_feature = "x")] //~ ERROR `cfg(target_feature)` is experimental
-   |       ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-
-error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
-  --> $DIR/feature-gate-cfg-target-feature.rs:15:19
-   |
-LL | #[cfg(not(any(all(target_feature = "x"))))] //~ ERROR `cfg(target_feature)` is experimental
-   |                   ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-
-error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
-  --> $DIR/feature-gate-cfg-target-feature.rs:19:10
-   |
-LL |     cfg!(target_feature = "x");
-   |          ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-doc_alias.rs b/src/test/ui/feature-gate-doc_alias.rs
new file mode 100644 (file)
index 0000000..1503dfe
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental
+pub struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-doc_alias.stderr b/src/test/ui/feature-gate-doc_alias.stderr
new file mode 100644 (file)
index 0000000..a987e03
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(alias = "...")] is experimental (see issue #50146)
+  --> $DIR/feature-gate-doc_alias.rs:11:1
+   |
+LL | #[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_alias)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index 477dd1b38eb0d7c6e4ca29150935d32f44a4da77..c83d9b56bc39f029a36ab189d9b53c4ae0fce9af 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
+#![feature(never_type)]
 fn foo() -> Result<u32, !> {
     Ok(123)
 }
index 724ec2496f24cdc6a342f903b786e68caa392969..347066268664324aebffcbf3f6c254a96fa60e15 100644 (file)
@@ -15,6 +15,7 @@ trait PointerFamily<U> {
     //~^ ERROR generic associated types are unstable
     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
     //~^ ERROR generic associated types are unstable
+    //~| ERROR where clauses on associated types are unstable
 }
 
 struct Foo;
@@ -25,4 +26,10 @@ impl PointerFamily<u32> for Foo {
     //~^ ERROR generic associated types are unstable
 }
 
+trait Bar {
+    type Assoc where Self: Sized;
+    //~^ ERROR where clauses on associated types are unstable
+}
+
+
 fn main() {}
index 5f23def88eb0633f6b4505e9f75ebd012883b125..d7891f13c6b4d9f6f283ecdb16ea2cc69e725502 100644 (file)
@@ -14,8 +14,16 @@ LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:16:5
+   |
+LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
 error[E0658]: generic associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:22:5
+  --> $DIR/feature-gate-generic_associated_types.rs:23:5
    |
 LL |     type Pointer<usize> = Box<usize>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,13 +31,21 @@ LL |     type Pointer<usize> = Box<usize>;
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:24:5
+  --> $DIR/feature-gate-generic_associated_types.rs:25:5
    |
 LL |     type Pointer2<u32> = Box<u32>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error: aborting due to 4 previous errors
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:30:5
+   |
+LL |     type Assoc where Self: Sized;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-never_type.rs b/src/test/ui/feature-gate-never_type.rs
new file mode 100644 (file)
index 0000000..ebbe17a
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+// Test that ! errors when used in illegal positions with feature(never_type) disabled
+
+trait Foo {
+    type Wub;
+}
+
+type Ma = (u32, !, i32); //~ ERROR type is experimental
+type Meeshka = Vec<!>; //~ ERROR type is experimental
+type Mow = &fn(!) -> !; //~ ERROR type is experimental
+type Skwoz = &mut !; //~ ERROR type is experimental
+
+impl Foo for Meeshka {
+    type Wub = !; //~ ERROR type is experimental
+}
+
+fn main() {
+}
diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr
new file mode 100644 (file)
index 0000000..187be6d
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:17:17
+   |
+LL | type Ma = (u32, !, i32); //~ ERROR type is experimental
+   |                 ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:18:20
+   |
+LL | type Meeshka = Vec<!>; //~ ERROR type is experimental
+   |                    ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:19:16
+   |
+LL | type Mow = &fn(!) -> !; //~ ERROR type is experimental
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:20:19
+   |
+LL | type Skwoz = &mut !; //~ ERROR type is experimental
+   |                   ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:23:16
+   |
+LL |     type Wub = !; //~ ERROR type is experimental
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-target_feature.rs b/src/test/ui/feature-gate-target_feature.rs
deleted file mode 100644 (file)
index da2e41a..0000000
+++ /dev/null
@@ -1,13 +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.
-
-#[target_feature = "+sse2"]
-//~^ the `#[target_feature]` attribute is an experimental feature
-fn foo() {}
diff --git a/src/test/ui/feature-gate-target_feature.stderr b/src/test/ui/feature-gate-target_feature.stderr
deleted file mode 100644 (file)
index 0f31abf..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: the `#[target_feature]` attribute is an experimental feature
-  --> $DIR/feature-gate-target_feature.rs:11:1
-   |
-LL | #[target_feature = "+sse2"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(target_feature)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/hygiene/fields-move.nll.stderr b/src/test/ui/hygiene/fields-move.nll.stderr
new file mode 100644 (file)
index 0000000..51f8067
--- /dev/null
@@ -0,0 +1,46 @@
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:38:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:28:9
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |         $foo.x //~ ERROR use of moved value: `foo.x`
+   |         ^^^^^^ value used here after move
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                                          ----- value moved here
+LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                       ----------------- in this macro invocation
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:39:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |         $foo.x //~ ERROR use of moved value: `foo.x`
+   |         ------ value moved here
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                                          ----- value moved here
+LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr b/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr
new file mode 100644 (file)
index 0000000..3a0a6f6
--- /dev/null
@@ -0,0 +1,13 @@
+error: compilation successful
+  --> $DIR/fields-numeric-borrowck.rs:13:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut s = S(0);
+LL | |     let borrow1 = &mut s.0;
+LL | |     let S { 0: ref mut borrow2 } = s;
+LL | |     //~^ ERROR cannot borrow `s.0` as mutable more than once at a time
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index 50ace39e70939cf88c222c4a00e0bfbec33dbf07..975684fbd41bbb7734fe53af27196d59aa979390 100644 (file)
@@ -7,10 +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.
-
+#![feature(rustc_attrs)]
 struct S(u8);
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut s = S(0);
     let borrow1 = &mut s.0;
     let S { 0: ref mut borrow2 } = s;
index 64217770b13c9ad278b1381f4697ba86dde7e3ec..ed155b28037a03e5a1558bc5d024e03f6e91b3ee 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     struct S { x: u32 }
index 7ba217061c66ee986911556a844bc7a0a52b94a0..f3f400aafeb2bfae7fd950555a83fd21e8866a12 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     pub fn f() {}
index cdba559445d195be1a4636a496ed0b57fa8467b0..4f997a790e688b058701cc918b90fb8f9895d77b 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     struct S;
index 50fc985ba34faea982f93aa51efb5f468af4f073..20ca918f026f362e19ea70ff24eb3f96293624f0 100644 (file)
@@ -14,7 +14,7 @@
 
 // error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 extern crate intercrate;
 
index c90c7b3093c9f0e5d04a15371b082d4cf05dbf38..ea6a45fba6ac7edb59a15c418b0a99aa24eba513 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     pub macro m() { Vec::new(); ().clone() }
index 987cad187d428c7dcf719df625bc4ec736a3f755..8a392db92f96062f802c74c1edb063f39035803b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     fn f() {}
index 3bd19cbc0ac67cbf48b4138d0118a906bc799d05..d0da6254b9bd01e26162241e4b12c35267c3b65e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     pub trait T {
index 99a7dd5e7852b22caa618ac8a78e3ec1a79faee6..54d548757643320c57c973f1359202c5eceaaba7 100644 (file)
@@ -40,8 +40,7 @@ fn after() -> impl Fn(i32) {
 // independently resolved and only require the concrete
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
-    //~^ ERROR cyclic dependency detected
-    //~| cyclic reference
+    //~^ ERROR cycle detected
     send(cycle2().clone());
 
     Rc::new(Cell::new(5))
index ca639f1076d3c814ff082ff765d47e81e38c1390..3b20451b10215afd4495b47b8ac21bf110a96e0c 100644 (file)
@@ -28,33 +28,29 @@ note: required by `send`
 LL | fn send<T: Send>(_: T) {}
    | ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0391]: cyclic dependency detected
-  --> $DIR/auto-trait-leak.rs:42:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic reference
-   |
-note: the cycle begins when processing `cycle1`...
+error[E0391]: cycle detected when processing `cycle1`
   --> $DIR/auto-trait-leak.rs:42:1
    |
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which then requires processing `cycle2::{{impl-Trait}}`...
-  --> $DIR/auto-trait-leak.rs:50:16
+   |
+note: ...which requires processing `cycle2::{{impl-Trait}}`...
+  --> $DIR/auto-trait-leak.rs:49:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
-note: ...which then requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:50:1
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:49:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which then requires processing `cycle1::{{impl-Trait}}`...
+note: ...which requires processing `cycle1::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:42:16
    |
 LL | fn cycle1() -> impl Clone {
    |                ^^^^^^^^^^
-   = note: ...which then again requires processing `cycle1`, completing the cycle.
+   = note: ...which again requires processing `cycle1`, completing the cycle
+note: cycle used when type-checking all item bodies
 
 error: aborting due to 3 previous errors
 
index 438d29f0535363fe1437dee28d4754a3ef62947c..f7aaab4242c0fab7bb6faf104d08cdd58f387df1 100644 (file)
@@ -8,10 +8,8 @@ LL |     foo(|s| s.is_empty());
    |               ^^^^^^^^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the following traits define an item `is_empty`, perhaps you need to implement one of them:
+   = note: the following trait defines an item `is_empty`, perhaps you need to implement it:
            candidate #1: `std::iter::ExactSizeIterator`
-           candidate #2: `core::slice::SliceExt`
-           candidate #3: `core::str::StrExt`
 
 error: aborting due to previous error
 
index e709eeee14a8452e4852ae322a16d7f380210bc0..51e5257be1bc22e65a6cf2b81100e85332cd1ffd 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 extern crate two_macros;
 
index 93de136c4051d6875345c8e420cd38e9048961d7..aad0a43be2696cac6fdae453ba5ccc71c433f761 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 mod foo {
     extern crate two_macros;
index 34ee39c7164023454d71638e5453ceb8b3efa384..ec8c4ecf102469b032e0d44a36069474b4866de2 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/dyn-trait.rs:33:16
    |
 LL |     static_val(x); //~ ERROR cannot infer
index 0930583a7ee33d7b250d17d977c6a3270c52afa2..cd2ebc341ead136a8f265704f73999b99b8d0257 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/mismatched.rs:14:42
    |
 LL | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y } //~ ERROR explicit lifetime required
    |                                          ^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/mismatched.rs:16:46
    |
 LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatch
index 5e42cab9974dab9aef5336602d2c3a2813878d57..886e3834d1dcaee2e30e5e00aec4cf7c0c1639e6 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/mismatched_trait.rs:16:9
    |
 LL |         y //~ ERROR explicit lifetime required
index e4d6076868717f0678b6b31924327cae4b2a0e50..83359bf1675d94bd362955044bc416da1fc75342 100644 (file)
@@ -9,11 +9,10 @@
 // except according to those terms.
 
 trait t1 : t2 {
+//~^ ERROR cycle detected
 }
 
 trait t2 : t1 {
-//~^ ERROR cyclic dependency detected
-//~| cyclic reference
 }
 
 fn main() { }
index c1612b8cb67861e169ff37c891bd6c170912281c..1a48e6a6de1c6a8f2d56219f84be9578a9650949 100644 (file)
@@ -1,20 +1,15 @@
-error[E0391]: cyclic dependency detected
-  --> $DIR/issue-12511.rs:14:1
-   |
-LL | trait t2 : t1 {
-   | ^^^^^^^^^^^^^ cyclic reference
-   |
-note: the cycle begins when computing the supertraits of `t1`...
+error[E0391]: cycle detected when computing the supertraits of `t1`
   --> $DIR/issue-12511.rs:11:1
    |
 LL | trait t1 : t2 {
    | ^^^^^^^^^^^^^
-note: ...which then requires computing the supertraits of `t2`...
-  --> $DIR/issue-12511.rs:11:1
    |
-LL | trait t1 : t2 {
+note: ...which requires computing the supertraits of `t2`...
+  --> $DIR/issue-12511.rs:15:1
+   |
+LL | trait t2 : t1 {
    | ^^^^^^^^^^^^^
-   = note: ...which then again requires computing the supertraits of `t1`, completing the cycle.
+   = note: ...which again requires computing the supertraits of `t1`, completing the cycle
 
 error: aborting due to previous error
 
index 604ad38ad2340eb12afe338058be6f55ccfe7313..146385f3de2d82070add89283c4bcbf3c4d34611 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/issue-13058.rs:24:21
    |
 LL |     let cont_iter = cont.iter();
    |                     ^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/issue-13058.rs:24:26
    |
 LL |     let cont_iter = cont.iter();
index c587c00279bde4f6634456cb7b412e3c9099b0a9..0fbe2f7a41177a5458b02e45d63c09009e01ee12 100644 (file)
@@ -1,20 +1,11 @@
-error[E0391]: cyclic dependency detected
-  --> $DIR/issue-23302-1.rs:14:9
-   |
-LL |     A = X::A as isize, //~ ERROR E0391
-   |         ^^^^^^^^^^^^^ cyclic reference
-   |
-note: the cycle begins when const-evaluating `X::A::{{initializer}}`...
-  --> $DIR/issue-23302-1.rs:14:9
-   |
-LL |     A = X::A as isize, //~ ERROR E0391
-   |         ^^^^^^^^^^^^^
-note: ...which then requires computing layout of `X`...
+error[E0391]: cycle detected when const-evaluating `X::A::{{initializer}}`
   --> $DIR/issue-23302-1.rs:14:9
    |
 LL |     A = X::A as isize, //~ ERROR E0391
    |         ^^^^
-   = note: ...which then again requires const-evaluating `X::A::{{initializer}}`, completing the cycle.
+   |
+note: ...which requires computing layout of `X`...
+   = note: ...which again requires const-evaluating `X::A::{{initializer}}`, completing the cycle
 
 error: aborting due to previous error
 
index 553ddaa1a8104d9d0429db0e1575e29958feeb2a..313cfa0c16260af9f2a46b6c8125a29c01b3d91d 100644 (file)
@@ -1,20 +1,11 @@
-error[E0391]: cyclic dependency detected
-  --> $DIR/issue-23302-2.rs:14:9
-   |
-LL |     A = Y::B as isize, //~ ERROR E0391
-   |         ^^^^^^^^^^^^^ cyclic reference
-   |
-note: the cycle begins when const-evaluating `Y::A::{{initializer}}`...
-  --> $DIR/issue-23302-2.rs:14:9
-   |
-LL |     A = Y::B as isize, //~ ERROR E0391
-   |         ^^^^^^^^^^^^^
-note: ...which then requires computing layout of `Y`...
+error[E0391]: cycle detected when const-evaluating `Y::A::{{initializer}}`
   --> $DIR/issue-23302-2.rs:14:9
    |
 LL |     A = Y::B as isize, //~ ERROR E0391
    |         ^^^^
-   = note: ...which then again requires const-evaluating `Y::A::{{initializer}}`, completing the cycle.
+   |
+note: ...which requires computing layout of `Y`...
+   = note: ...which again requires const-evaluating `Y::A::{{initializer}}`, completing the cycle
 
 error: aborting due to previous error
 
index 5903acc8b7a6d51c58079b71af97ebed169818eb..c3664e0abe1149664d979e7ac07571a4ef6eafd7 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-const A: i32 = B;
+const A: i32 = B; //~ ERROR cycle detected
 
-const B: i32 = A; //~ ERROR cyclic dependency detected
+const B: i32 = A;
 
 fn main() { }
index 8cf296bc6db6c82f4335e716d258b3b78bc05778..54edf42679aeff372be1589bebb10761135f1738 100644 (file)
@@ -1,30 +1,25 @@
-error[E0391]: cyclic dependency detected
-  --> $DIR/issue-23302-3.rs:13:16
-   |
-LL | const B: i32 = A; //~ ERROR cyclic dependency detected
-   |                ^ cyclic reference
-   |
-note: the cycle begins when const checking if rvalue is promotable to static `A`...
+error[E0391]: cycle detected when const checking if rvalue is promotable to static `A`
   --> $DIR/issue-23302-3.rs:11:1
    |
-LL | const A: i32 = B;
+LL | const A: i32 = B; //~ ERROR cycle detected
    | ^^^^^^^^^^^^^^^^^
-note: ...which then requires checking which parts of `A` are promotable to static...
-  --> $DIR/issue-23302-3.rs:11:1
    |
-LL | const A: i32 = B;
-   | ^^^^^^^^^^^^^^^^^
-note: ...which then requires const checking if rvalue is promotable to static `B`...
+note: ...which requires checking which parts of `A` are promotable to static...
   --> $DIR/issue-23302-3.rs:11:16
    |
-LL | const A: i32 = B;
+LL | const A: i32 = B; //~ ERROR cycle detected
    |                ^
-note: ...which then requires checking which parts of `B` are promotable to static...
+note: ...which requires const checking if rvalue is promotable to static `B`...
   --> $DIR/issue-23302-3.rs:13:1
    |
-LL | const B: i32 = A; //~ ERROR cyclic dependency detected
+LL | const B: i32 = A;
    | ^^^^^^^^^^^^^^^^^
-   = note: ...which then again requires const checking if rvalue is promotable to static `A`, completing the cycle.
+note: ...which requires checking which parts of `B` are promotable to static...
+  --> $DIR/issue-23302-3.rs:13:16
+   |
+LL | const B: i32 = A;
+   |                ^
+   = note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle
 
 error: aborting due to previous error
 
index 7ab4bd46ebf46d486b1b9c041107c559e68bf076..541f54ca7689148a1d4dcec6219b3e4583da68db 100644 (file)
@@ -1,30 +1,21 @@
-error[E0391]: cyclic dependency detected
-  --> $DIR/issue-36163.rs:14:9
-   |
-LL |     B = A, //~ ERROR E0391
-   |         ^ cyclic reference
-   |
-note: the cycle begins when const-evaluating `Foo::B::{{initializer}}`...
+error[E0391]: cycle detected when const-evaluating `Foo::B::{{initializer}}`
   --> $DIR/issue-36163.rs:14:9
    |
 LL |     B = A, //~ ERROR E0391
    |         ^
-note: ...which then requires processing `Foo::B::{{initializer}}`...
+   |
+note: ...which requires processing `Foo::B::{{initializer}}`...
   --> $DIR/issue-36163.rs:14:9
    |
 LL |     B = A, //~ ERROR E0391
    |         ^
-note: ...which then requires const-evaluating `A`...
-  --> $DIR/issue-36163.rs:11:1
-   |
-LL | const A: isize = Foo::B as isize;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which then requires computing layout of `Foo`...
+note: ...which requires const-evaluating `A`...
   --> $DIR/issue-36163.rs:11:18
    |
 LL | const A: isize = Foo::B as isize;
    |                  ^^^^^^
-   = note: ...which then again requires const-evaluating `Foo::B::{{initializer}}`, completing the cycle.
+note: ...which requires computing layout of `Foo`...
+   = note: ...which again requires const-evaluating `Foo::B::{{initializer}}`, completing the cycle
 
 error: aborting due to previous error
 
index 040e6300af60a48162f76b05c27da0e03feb400e..8045993747934a09c8bad37c719df935f877fa3b 100644 (file)
@@ -4,7 +4,7 @@ error[E0596]: cannot borrow immutable item `*x` as mutable
 LL |     f(&mut *x); //~ ERROR cannot borrow immutable
    |       ^^^^^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `x`
+   = note: the value which is causing this path not to be mutable is...: `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-45697-1.nll.stderr b/src/test/ui/issue-45697-1.nll.stderr
deleted file mode 100644 (file)
index cf10869..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
-  --> $DIR/issue-45697-1.rs:30:9
-   |
-LL |         let z = copy_borrowed_ptr(&mut y);
-   |                                        - borrow of `*y.pointer` occurs here
-LL |         *y.pointer += 1;
-   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
-
-error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
-  --> $DIR/issue-45697-1.rs:30:9
-   |
-LL |         let z = copy_borrowed_ptr(&mut y);
-   |                                   ------ borrow of `y` occurs here
-LL |         *y.pointer += 1;
-   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
-...
-LL |         *z.pointer += 1;
-   |         --------------- borrow later used here
-
-error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
-  --> $DIR/issue-45697-1.rs:30:9
-   |
-LL |         let z = copy_borrowed_ptr(&mut y);
-   |                                   ------ borrow of `*y.pointer` occurs here
-LL |         *y.pointer += 1;
-   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
-...
-LL |         *z.pointer += 1;
-   |         --------------- borrow later used here
-
-error: aborting due to 3 previous errors
-
-Some errors occurred: E0503, E0506.
-For more information about an error, try `rustc --explain E0503`.
index 7734b14b2ab7b008f3a10d5469f5538dae8389c7..b8be209833a6e15a3c3f1dd5cda254080c6913e0 100644 (file)
@@ -30,6 +30,7 @@ fn main() {
         *y.pointer += 1;
         //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506]
         //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503]
+        //~| ERROR cannot assign to `*y.pointer` because it is borrowed (Mir) [E0506]
         *z.pointer += 1;
     }
 }
index aa899c5aee9eb429ba4ad2ca36df1193bcac2f3b..cf108691a0e4f65a2034c7ca927a1a79450e00b4 100644 (file)
@@ -13,8 +13,22 @@ LL |         let z = copy_borrowed_ptr(&mut y);
    |                                   ------ borrow of `y` occurs here
 LL |         *y.pointer += 1;
    |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
 
-error: aborting due to 2 previous errors
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
+  --> $DIR/issue-45697-1.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 3 previous errors
 
 Some errors occurred: E0503, E0506.
 For more information about an error, try `rustc --explain E0503`.
index 4e93eccd6f6496ee1f4fde63302ed376073117cc..27acc2c89f75d435060f6baa2a32e40abe7b5744 100644 (file)
@@ -30,6 +30,7 @@ fn main() {
         *y.pointer += 1;
         //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506]
         //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503]
+        //~| ERROR cannot assign to `*y.pointer` because it is borrowed (Mir) [E0506]
         *z.pointer += 1;
     }
 }
index babfc33b94582b7254e834f8e583295b8be1dabc..a85972fcd7a1c05b6e24577a7352cf3ba92a7ca4 100644 (file)
@@ -13,8 +13,22 @@ LL |         let z = copy_borrowed_ptr(&mut y);
    |                                   ------ borrow of `y` occurs here
 LL |         *y.pointer += 1;
    |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
 
-error: aborting due to 2 previous errors
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
+  --> $DIR/issue-45697.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 3 previous errors
 
 Some errors occurred: E0503, E0506.
 For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issue-46471-1.nll.stderr b/src/test/ui/issue-46471-1.nll.stderr
deleted file mode 100644 (file)
index 0108056..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0597]: `z` does not live long enough (Ast)
-  --> $DIR/issue-46471-1.rs:16:14
-   |
-LL |         &mut z
-   |              ^ borrowed value does not live long enough
-LL |     };
-   |     - `z` dropped here while still borrowed
-...
-LL | }
-   | - borrowed value needs to live until here
-
-error[E0597]: `z` does not live long enough (Mir)
-  --> $DIR/issue-46471-1.rs:16:9
-   |
-LL |       let y = {
-   |  _____________-
-LL | |         let mut z = 0;
-LL | |         &mut z
-   | |         ^^^^^^ borrowed value does not live long enough
-LL | |     };
-   | |     -
-   | |     |
-   | |_____borrowed value only lives until here
-   |       borrow later used here
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0597`.
index bfd5bfa9f7274e5185504f7ae9b7bf913807a074..0108056bc7278265ae61aba0d7c536908bfcd6d8 100644 (file)
@@ -12,13 +12,16 @@ LL | }
 error[E0597]: `z` does not live long enough (Mir)
   --> $DIR/issue-46471-1.rs:16:9
    |
-LL |         &mut z
-   |         ^^^^^^ borrowed value does not live long enough
-LL |     };
-   |     - `z` dropped here while still borrowed
-...
-LL | }
-   | - borrowed value needs to live until here
+LL |       let y = {
+   |  _____________-
+LL | |         let mut z = 0;
+LL | |         &mut z
+   | |         ^^^^^^ borrowed value does not live long enough
+LL | |     };
+   | |     -
+   | |     |
+   | |_____borrowed value only lives until here
+   |       borrow later used here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-48636.rs b/src/test/ui/issue-48636.rs
new file mode 100644 (file)
index 0000000..03e45d8
--- /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.
+
+struct S {
+    x: u8
+    /// The id of the parent core
+    y: u8,
+}
+//~^^^ ERROR found a documentation comment that doesn't document anything
+fn main() {}
diff --git a/src/test/ui/issue-48636.stderr b/src/test/ui/issue-48636.stderr
new file mode 100644 (file)
index 0000000..4e014a5
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/issue-48636.rs:13:5
+   |
+LL |     x: u8
+   |          - help: missing comma here: `,`
+LL |     /// The id of the parent core
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/issue-49851/compiler-builtins-error.rs b/src/test/ui/issue-49851/compiler-builtins-error.rs
new file mode 100644 (file)
index 0000000..db82f22
--- /dev/null
@@ -0,0 +1,18 @@
+//~ ERROR 1:1: 1:1: can't find crate for `core` [E0463]
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --target thumbv7em-none-eabihf
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_std]
+
+extern crate cortex_m;
+
diff --git a/src/test/ui/issue-49851/compiler-builtins-error.stderr b/src/test/ui/issue-49851/compiler-builtins-error.stderr
new file mode 100644 (file)
index 0000000..7e23e0f
--- /dev/null
@@ -0,0 +1,7 @@
+error[E0463]: can't find crate for `core`
+   |
+   = note: the `thumbv7em-none-eabihf` target may not be installed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
index 62ccea36bd344a9ec5d9c178a871a44187d439a2..d422a63bcad3957942af48d087fd65df878370ad 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/42701_one_named_and_one_anonymous.rs:20:9
    |
 LL |         &*x //~ ERROR explicit lifetime
index 78546594ef0dc95a228f8ae96a81186715bd1faf..5451562cdfb4071406643684d5a83ebdc8d550ab 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21
    |
 LL |                     other //~ ERROR explicit lifetime
index 11bb1df3c78aa7d81f8b4038cf74946d0fa4e1c3..e1dfeb0ac6adb555d9cf040928aad0c606a49323 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
    |
 LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
index a619e6ca964cd56ada9f7412db031bde47a87999..1e45914138de544ce03ea8678c4d16a005beec8f 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
    |
 LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
index 92245173ce85958867f33167ac83bb63911b64e4..e264b3428c95bd220bf3414ce480c3de5c0551ac 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
    |
 LL |    if x > y { x } else { y } //~ ERROR explicit lifetime
index 32ef068b8b9bba9d01e7638887628adf64b80e5c..6119f3c56053800959141dfe750c6616cc390df3 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
    |
 LL |     if true { &self.field } else { x } //~ ERROR explicit lifetime
index fd10b0d338cb362784f87a35454d16eaa338387a..71e9c34ac2b97b006a5f9ef420d83f1002bd2a21 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
    |
 LL |         if x > y { x } else { y } //~ ERROR lifetime mismatch
index f17b24a0aca9c438dedf6c010b32287f0bf65f40..5e49e4ec4a98b5c9e4f7c8e9299f4abb55e65d9f 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
    |
 LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
index b1663fe5eb65458a7aecafde1cdaa615f0bc11d5..6c16d6a608ec8a2853f2e758808d086a5d32a94b 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
    |
 LL |     x //~ ERROR lifetime mismatch
index 19b8bd2f780f0c5cefb29f3a4f039124bde2e2f4..6dc96ace4d0d31cafe9470196047fdf0f54c9893 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
    |
 LL |         if true { x } else { self } //~ ERROR lifetime mismatch
index 0b34e464b4b0fd0e7c23488e069af0dda157c323..a51d9307d074d0bae99eea66e0dee9d2ee5e4dc4 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2a-push-one-existing-name-2.rs:16:12
    |
 LL |     y.push(x); //~ ERROR explicit lifetime
index 212b39966aae829ed4284d9f83322a19080d1211..c5f3510fa0ed26d3b22ed886e7180f1f26d355d8 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12
    |
 LL |     x.push(y); //~ ERROR explicit lifetime required
index ad39028154ad8e14c33dd56fbb97f1dd229d6adb..e50fd74faf4badfaf240a207689c607a9d693012 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2a-push-one-existing-name.rs:16:12
    |
 LL |     x.push(y); //~ ERROR explicit lifetime
index 34daea7c9f46f6aba908319ab08db05e28c5b34d..283192c6843927cb19dd1f26563d62cf03836540 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2b-push-no-existing-names.rs:16:12
    |
 LL |     x.push(y); //~ ERROR lifetime mismatch
index 96baa5c8ad2a8c67862192a0f3c0fe74904b0e1c..2ca202b402cee0f666dbdb87fef7631b0bb2b1f5 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2c-push-inference-variable.rs:16:13
    |
 LL |     let z = Ref { data: y.data };
index e5d47689b494822f6ada534c3c44c1a0efd9d389..712c25f8929d4fcb5a43ecbcf76ef2c2adabed3d 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2d-push-inference-variable-2.rs:17:13
    |
 LL |     let b = Ref { data: y.data };
index 668752f8e0296fa461d5ec3dd614b760253d9cd6..351966902a4fba657ef3ab0a48569e12f1d0810a 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex2e-push-inference-variable-3.rs:17:13
    |
 LL |     let b = Ref { data: y.data };
index 452342497117a3c6e63d92681264ad44a1a31be3..871a0b109b4aa118e11de1a23ead2f9c8e61dd3c 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-2.rs:12:9
    |
 LL |     v = x; //~ ERROR lifetime mismatch
index 581088a9258a772009eebbe8062cc56082a9b0b0..102981977e55756eaa324db92bd8a572402a002c 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-3.rs:12:13
    |
 LL |     z.push((x,y)); //~ ERROR lifetime mismatch
    |             ^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-3.rs:12:15
    |
 LL |     z.push((x,y)); //~ ERROR lifetime mismatch
index b15f5f4a0fcafb5dcf3e24fefe84d6c2de99bf01..191389b7706e1e8f93e18533d6157472af6249e1 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
    |
 LL |     x.b = y.b; //~ ERROR lifetime mismatch
index 0ec73c2e77815089d3ae51f0e958afe2bb43ed2c..159367cc9d2a6f98cceebb48c97c3ab4ccf5c59c 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
    |
 LL |     x.a = x.b; //~ ERROR lifetime mismatch
index 727a701d3f252af9365dd3f01f81f4c4f2ccf156..3bbcbdd6681fd7aa1a5b09a9f5ada3b00f17ce77 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:11
    |
 LL |     x.a = x.b; //~ ERROR lifetime mismatch
index f010c87377ed710b12d4f03ec4353a170abff903..9d1f6a3e36f1b53d40a2faa099ee164273c1a84e 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:12
    |
 LL |     x.push(y); //~ ERROR lifetime mismatch
index 2b48b176ae898f35f4f92ec8104665d718c5c35c..5df93fd5547c7d306311893b81e38b927a757948 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:12
    |
 LL |     x.push(y); //~ ERROR lifetime mismatch
index c9ac04cb01e5f218129cf2a66f08116319303415..cd602cf950b18e3c76419e729225459e513eb360 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
    |
 LL |     x.push(y); //~ ERROR lifetime mismatch
index 9c7fc8ac45863d86a2a9d138ecc11e2e789381f0..52c90839c32af5d246964702923eabaf7a3a4481 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-latebound-regions.rs:12:12
    |
 LL |     x.push(y); //~ ERROR lifetime mismatch
index 85a0b7c134556d81c69e0a9a5d6ef5bfa316aff8..9d6d68f518d72997542dbcb959647cb68c1cabf8 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
    |
 LL |     y = x.b; //~ ERROR lifetime mismatch
index 4e160001b87392117c33d76054169794c2f3cc8f..e7fb67f117f88c5138563673e3700b83caf208b8 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
    |
 LL |     y.b = x; //~ ERROR lifetime mismatch
index 7bbc3c4084f045527a78e0b2eae1c7bd64df32f5..af9e3a42664cf6e35e0b476969534bfdc797e3c0 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:11
    |
 LL |     y.b = x; //~ ERROR lifetime mismatch
index 9fd7bbac247aac3e53c43e2feb5422314c0f0149..5437beaab65117683f4f117089ce16ea00e6f491 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
    |
 LL |     x.b = y; //~ ERROR lifetime mismatch
index 528a846991c046a425f3297a1304cf142248349a..42e1d42a32ccd32fe78817243a9610943aebe750 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
    |
 LL |     x //~ ERROR lifetime mismatch
index f8c0b5940c95b21ed573548c7244e6716a3a4652..26b0488cfdc61cf054b369c4baa21fe8e199b0fc 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
    |
 LL |         if true { x } else { self } //~ ERROR lifetime mismatch
index 284f760435cfacbf12fa3c72057cfb236e13b680..f58f33c9a9adbced2b9eca788f152104b8153b91 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:10
    |
 LL |   y.push(z); //~ ERROR lifetime mismatch
index 389549a8464b768a7f33afa5c96c06686e20fd63..4d54f6fe0375c75645f5438772219ea878854219 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
    |
 LL |         x.push(y); //~ ERROR lifetime mismatch
index 185ea89275f35b13702f2f91b5d3432496888f6a..4bfb4ac2833c8c77c36b7b516530198bc8a80c68 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:10
    |
 LL |   y.push(z); //~ ERROR lifetime mismatch
index 629a97ab5ca5cd0bbc90ac8362396d093381dfb1..c25eedc770d486942e1d4ca131f32a88388a12d8 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ex3-both-anon-regions.rs:12:12
    |
 LL |     x.push(y); //~ ERROR lifetime mismatch
index bff64ad489210a0f1fd33f55194da91921c86624..090ff817eb0f2cf89321767645756f61836cd6ab 100644 (file)
@@ -48,13 +48,13 @@ macro_rules! fake_anon_field_expr {
 
 macro_rules! real_method_stmt {
      () => {
-          2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+          2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
      }
 }
 
 macro_rules! real_method_expr {
      () => {
-          2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+          2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
      }
 }
 
index cb7d422b7f3ed73d3d82339b572cd4fc9dd2cc20..284960d2f6e154135b7fa33dcd5cce1b5a221b5c 100644 (file)
@@ -25,17 +25,17 @@ LL |           (1).0 //~ ERROR doesn't have fields
 LL |     fake_anon_field_stmt!();
    |     ------------------------ in this macro invocation
 
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/macro-backtrace-invalid-internals.rs:51:15
    |
-LL |           2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
-   |               ^^^^
+LL |           2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+   |               ^^^^^
 ...
 LL |     real_method_stmt!();
    |     -------------------- in this macro invocation
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+LL |           2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
    |           ^^^^^^^
 
 error[E0599]: no method named `fake` found for type `{integer}` in the current scope
@@ -65,17 +65,17 @@ LL |           (1).0 //~ ERROR doesn't have fields
 LL |     let _ = fake_anon_field_expr!();
    |             ----------------------- in this macro invocation
 
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/macro-backtrace-invalid-internals.rs:57:15
    |
-LL |           2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
-   |               ^^^^
+LL |           2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+   |               ^^^^^
 ...
 LL |     let _ = real_method_expr!();
    |             ------------------- in this macro invocation
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+LL |           2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
    |           ^^^^^^^
 
 error: aborting due to 8 previous errors
diff --git a/src/test/ui/mir_check_nonconst.rs b/src/test/ui/mir_check_nonconst.rs
new file mode 100644 (file)
index 0000000..898ee8b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+struct Foo { a: u8 }
+fn bar() -> Foo {
+    Foo { a: 5 }
+}
+
+static foo: Foo = bar();
+//~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
+
+fn main() {}
diff --git a/src/test/ui/mir_check_nonconst.stderr b/src/test/ui/mir_check_nonconst.stderr
new file mode 100644 (file)
index 0000000..1fddaf3
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/mir_check_nonconst.rs:18:19
+   |
+LL | static foo: Foo = bar();
+   |                   ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
index 41c744fec6e762024430a75c82cc4ed51acc1534..1e168028c7c9a9c48f2be595d7eb6026ae445ccf 100644 (file)
@@ -22,7 +22,7 @@
 // that appear free in its type (hence, we see it before the closure's
 // "external requirements" report).
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -35,7 +35,7 @@ fn test() {
         let y = 22;
         let mut closure = expect_sig(|p, y| *p = y);
         //~^ ERROR does not outlive free region
-        //~| WARNING not reporting region error due to -Znll
+        //~| WARNING not reporting region error due to nll
         closure(&mut p, &y);
     }
 
index 5f84001a8fb99163b294a5158af44e90d9ec1257..d876c751a41d2aa13e1f7c5475cacc320a39496e 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/escape-argument-callee.rs:36:50
    |
 LL |         let mut closure = expect_sig(|p, y| *p = y);
index 7e918c6431de4450e874558b91bee2001218119e..7a28cb26f3570620998ebdff319b76249e677ac9 100644 (file)
@@ -22,7 +22,7 @@
 // basically checking that the MIR type checker correctly enforces the
 // closure signature.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
index 05700ae00ad4f72900ad96f2cdec06474a528f22..598839f872e01805bc1d896c3f6755754cdc8500 100644 (file)
@@ -15,7 +15,7 @@
 //
 // except that the closure does so via a second closure.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
index 93d8bfafcbaa4ffed82d2b0be51f828a7d2b679b..49d31bbc139d73f0b88aca1551900018681a7e6c 100644 (file)
@@ -19,7 +19,7 @@
 // `'b`.  This relationship is propagated to the closure creator,
 // which reports an error.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
index 30a6dfc5b3edd05bf737f99c8b22c69a633f4427..e7ec0b9684d2c980d785f8b7a6093e6e521a6ae0 100644 (file)
@@ -11,7 +11,7 @@
 // Test where we fail to approximate due to demanding a postdom
 // relationship between our upper bounds.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -53,7 +53,7 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell
         |_outlives1, _outlives2, _outlives3, x, y| {
             // Only works if 'x: 'y:
             let p = x.get();
-            //~^ WARN not reporting region error due to -Znll
+            //~^ WARN not reporting region error due to nll
             //~| ERROR does not outlive free region
             demand_y(x, y, p)
         },
index 0c058e40a5086927d99222a31a43566385c060c0..ef5a31e40d445afa5c9c55a615607f66fbf8c075 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
    |
 LL |             let p = x.get();
@@ -16,7 +16,7 @@ note: No external requirements
 LL | /         |_outlives1, _outlives2, _outlives3, x, y| {
 LL | |             // Only works if 'x: 'y:
 LL | |             let p = x.get();
-LL | |             //~^ WARN not reporting region error due to -Znll
+LL | |             //~^ WARN not reporting region error due to nll
 LL | |             //~| ERROR does not outlive free region
 LL | |             demand_y(x, y, p)
 LL | |         },
index 91128035f3d95162d81615b188c68c3ecde35611..da8ce55162f37e706ce35dbfb4cf9f4386449389 100644 (file)
@@ -22,7 +22,7 @@
 // Note: the use of `Cell` here is to introduce invariance. One less
 // variable.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -54,7 +54,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR lifetime mismatch
 
         // Only works if 'x: 'y:
-        demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+        demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
     });
 }
 
index 947b95b1c53218887a257a4470b2153f3d91c855..3a3236fd16c49e03b90e7edb007867ec646b131b 100644 (file)
@@ -1,7 +1,7 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-approximated-ref.rs:57:9
    |
-LL |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+LL |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 note: External requirements
@@ -12,7 +12,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR lifetime mismatch
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
index f210346a82a675b1f9a5062cbd063f320a56306d..84bfd6ea4f25324cb479b77ce5b01ce333e0468a 100644 (file)
@@ -12,7 +12,7 @@
 // where `'x` is bound in closure type but `'a` is free. This forces
 // us to approximate `'x` one way or the other.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -29,7 +29,7 @@ fn case1() {
     let a = 0;
     let cell = Cell::new(&a);
     foo(cell, |cell_a, cell_x| {
-        //~^ WARNING not reporting region error due to -Znll
+        //~^ WARNING not reporting region error due to nll
         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
         //~^ ERROR does not outlive free region
     })
index d39cdc34471abcf3615064c0614af3d88f117c85..6480cbe44312785885070fecd8df69f1e508e829 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:5
    |
 LL |     foo(cell, |cell_a, cell_x| {
@@ -15,7 +15,7 @@ note: No external requirements
    |
 LL |       foo(cell, |cell_a, cell_x| {
    |  _______________^
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
 LL | |         //~^ ERROR does not outlive free region
 LL | |     })
index c66472d5ce9b1ec1060843ca0532457e56e61e1c..df715c52921a0de5033f0303daa4bb37b1dc33d6 100644 (file)
@@ -16,7 +16,7 @@
 // FIXME(#45827) Because of shortcomings in the MIR type checker,
 // these errors are not (yet) reported.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -46,7 +46,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR does not outlive free region
 
         // Only works if 'x: 'y:
-        demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+        demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
     });
 }
 
index 3131142ec73bfcda7e0ff840d3ff691c66117d50..6dcc8421177d9cf37cd3b06b2ecc02e984597379 100644 (file)
@@ -1,7 +1,7 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:49:9
    |
-LL |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+LL |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 note: External requirements
@@ -12,7 +12,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR does not outlive free region
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
@@ -31,7 +31,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR does not outlive free region
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll
+LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
 
index f4011a0e5335e8fdee25a809af6ef98ef133a545..fdbb312572f894dd3085ffe80490844f864b868e 100644 (file)
@@ -17,7 +17,7 @@
 // FIXME(#45827) Because of shortcomings in the MIR type checker,
 // these errors are not (yet) reported.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -49,7 +49,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR does not outlive free region
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ WARNING not reporting region error due to -Znll
+        //~^ WARNING not reporting region error due to nll
     });
 }
 
index 5b038653b606837d4cabf8afeb8be70ebd11bd42..1291f2e9901b0e75880cc4245891dd2c5f8e2332 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:51:9
    |
 LL |         demand_y(x, y, x.get())
@@ -12,7 +12,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR does not outlive free region
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
@@ -31,7 +31,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR does not outlive free region
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
 
index d163f304ae5b17f2509448dd3f1404e8b2aec70c..0449dc1d1a75c2846134f95c52c21993c79f43c1 100644 (file)
@@ -15,7 +15,7 @@
 // relationships. In the 'main' variant, there are a number of
 // anonymous regions as well.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -47,7 +47,7 @@ fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR lifetime mismatch
 
         // Only works if 'x: 'y:
-        demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to -Znll
+        demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
     });
 }
 
index 475fdd947817e4e3e7162deee01c68923799c72f..d1824a941510266033b5750f0fe6f39f4b7cfbdc 100644 (file)
@@ -1,7 +1,7 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-approximated-val.rs:50:9
    |
-LL |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to -Znll
+LL |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: External requirements
@@ -12,7 +12,7 @@ LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y|
 LL | |         //~^ ERROR lifetime mismatch
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to -Znll
+LL | |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
index 1ccfa61f4ce4665b86869b19b0ab57b3476ed096..c21c824b22c3bb093bf74f2c5fda51bcd94cfc73 100644 (file)
@@ -13,7 +13,7 @@
 // need to propagate; but in fact we do because identity of free
 // regions is erased.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 // compile-pass
 
 #![feature(rustc_attrs)]
index ab4faaca756331c8f472a1c8ee271b6f18ae26a5..d6eeda881daf26b91920981ded1076cda25aadd9 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-despite-same-free-region.rs:54:21
    |
 LL |             let p = x.get();
index eb512a3b9b1fb13eded1a71570b5c7510a9b82ac..7699d101734958122ee2eca1d296521de81ddeae 100644 (file)
@@ -17,7 +17,7 @@
 // as it knows of no relationships between `'x` and any
 // non-higher-ranked regions.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -45,7 +45,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ WARN not reporting region error due to -Znll
+        //~^ WARN not reporting region error due to nll
         //~| ERROR does not outlive free region
     });
 }
index ce808f56b42974ee4bf4b8827ead3fe005adea46..ffae47bd081c33119a0ab55ab012ab22e6c2f188 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
    |
 LL |         demand_y(x, y, x.get())
@@ -17,7 +17,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |  _______________________________________________^
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARN not reporting region error due to -Znll
+LL | |         //~^ WARN not reporting region error due to nll
 LL | |         //~| ERROR does not outlive free region
 LL | |     });
    | |_____^
index 930742464297202f9abd7f651fa9189c11935d01..afb61b221be942394a2e011734a7a0ae1fda1bda 100644 (file)
@@ -17,7 +17,7 @@
 // as it only knows of regions that `'x` is outlived by, and none that
 // `'x` outlives.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
@@ -49,7 +49,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ WARN not reporting region error due to -Znll
+        //~^ WARN not reporting region error due to nll
         //~| ERROR does not outlive free region
     });
 }
index 547ff75bac62c5d363add30ef27f30262c2da0f0..01af756b8332c639632b9047d6083bcc0162e3e3 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
    |
 LL |         demand_y(x, y, x.get())
@@ -17,7 +17,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
    |  _______________________________________________^
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARN not reporting region error due to -Znll
+LL | |         //~^ WARN not reporting region error due to nll
 LL | |         //~| ERROR does not outlive free region
 LL | |     });
    | |_____^
index 91796355752a5eb00af3da727479fae8bfbf5bf0..7baf24f88f8fa419b35643e9304b973decd1039e 100644 (file)
@@ -14,7 +14,7 @@
 // the same `'a` for which it implements `Trait`, which can only be the `'a`
 // from the function definition.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
@@ -53,7 +53,7 @@ fn supply<'a, T>(value: T)
         // The latter does not hold.
 
         require(value);
-        //~^ WARNING not reporting region error due to -Znll
+        //~^ WARNING not reporting region error due to nll
     });
 }
 
index 5bdfc7e935fea99557e50fece0c83efe90ddb6fc..a8b4ed528015fbf3c9e26a92ce0c6429d51cfd8d 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/propagate-from-trait-match.rs:55:9
    |
 LL |         require(value);
@@ -13,7 +13,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |
 LL | |         // This function call requires that
 ...  |
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
@@ -35,7 +35,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |
 LL | |         // This function call requires that
 ...  |
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
index ac21fe25bd112e5a9183bb737012f15b9d06704c..a6b2e531ac28fcf9cb0e4d75a41cef1d921aafa5 100644 (file)
 // a variety of errors from the older, AST-based machinery (notably
 // borrowck), and then we get the NLL error at the end.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 fn foo(x: &u32) -> &'static u32 {
     &*x
-        //~^ WARN not reporting region error due to -Znll
+        //~^ WARN not reporting region error due to nll
         //~| ERROR explicit lifetime required in the type of `x`
 }
 
index 1e93ae1ee07c6f828810d8cd9c26d9ac68656e15..a823e62d3b843f76b5184a2eeb305dfd46664a7a 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
    |
 LL |     &*x
index a1be8e851851599161c10f5e79b868bede8f43d3..dedbd8df41b130ca8d771fcd71418e092cffa38e 100644 (file)
 // a variety of errors from the older, AST-based machinery (notably
 // borrowck), and then we get the NLL error at the end.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 fn foo<'a>(x: &'a u32) -> &'static u32 {
     &*x
-        //~^ WARN not reporting region error due to -Znll
+        //~^ WARN not reporting region error due to nll
         //~| ERROR does not outlive free region
 }
 
index ac3bf4b459fec119d7744fed078ec6f147d3e1e2..9520b446303c3fc8c06cef12e97ebb099734f082 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
    |
 LL |     &*x
index 00b09e2ab21ada08e8600b54eb510271993ea1c1..8598668bef50ea59002d5466e6d895976a97d7bc 100644 (file)
 // a variety of errors from the older, AST-based machinery (notably
 // borrowck), and then we get the NLL error at the end.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
     &*x
-        //~^ WARN not reporting region error due to -Znll
+        //~^ WARN not reporting region error due to nll
         //~| ERROR lifetime mismatch
 }
 
index 3af6d7d21f75310c484546931587dd004ac63acf..415aefdeee947a97b91f71c667aa57cc82a78f64 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
    |
 LL |     &*x
index 7454a8e71f2708c7b1a1a46b8f1bc011e4b1e93a..6d2bb30980236dd42a6655a3bfdbede99de99f4b 100644 (file)
@@ -11,7 +11,7 @@
 // Basic test for free regions in the NLL code. This test does not
 // report an error because of the (implied) bound that `'b: 'a`.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 // compile-pass
 
 #![allow(warnings)]
index 754df4f2c5db624b95f6dfdab3b49da248635869..60f82ca0eefb9a9a5add36cfb845cdb9739a6bd5 100644 (file)
 // the first, but actually returns the second. This should fail within
 // the closure.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![feature(rustc_attrs)]
 
 #[rustc_regions]
 fn test() {
     expect_sig(|a, b| b); // ought to return `a`
-    //~^ WARN not reporting region error due to -Znll
+    //~^ WARN not reporting region error due to nll
     //~| ERROR does not outlive free region
 }
 
index b34f4c470df49da99fef7a622cfcc0797619d964..4d021fb545494c9a6ccb7798d7b8a64cab817fcd 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/return-wrong-bound-region.rs:21:23
    |
 LL |     expect_sig(|a, b| b); // ought to return `a`
@@ -26,7 +26,7 @@ note: No external requirements
    |
 LL | / fn test() {
 LL | |     expect_sig(|a, b| b); // ought to return `a`
-LL | |     //~^ WARN not reporting region error due to -Znll
+LL | |     //~^ WARN not reporting region error due to nll
 LL | |     //~| ERROR does not outlive free region
 LL | | }
    | |_^
index 589d8ffd28f0b3aeeff8b301f2a36270635ec596..10ce0652d43c2f6df54b6b698ff4220d7c9c74ca 100644 (file)
@@ -11,7 +11,7 @@
 // Test that MIR borrowck and NLL analysis can handle constants of
 // arbitrary types without ICEs.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 // compile-pass
 
 const HI: &str = "hi";
index 6dcbe0a528d90a3a522defa96ea87a305a3a42f0..b357b3facf9bb4ab46070d7751cbad28cb58f517 100644 (file)
@@ -12,7 +12,7 @@
 // in the type of `p` includes the points after `&v[0]` up to (but not
 // including) the call to `use_x`. The `else` branch is not included.
 
-// compile-flags:-Znll -Zborrowck=mir
+// compile-flags:-Zborrowck=mir
 // compile-pass
 
 #![allow(warnings)]
index e5478e39fecca9e3dddf2a394371d48ea55d8237..513609316311a3e567bd1e7e7b86c36638b5e1bd 100644 (file)
@@ -13,7 +13,7 @@
 // because of destructor. (Note that the stderr also identifies this
 // destructor in the error message.)
 
-// compile-flags:-Znll -Zborrowck=mir
+// compile-flags:-Zborrowck=mir
 
 #![allow(warnings)]
 #![feature(dropck_eyepatch)]
index e5944e75e424177fad5749b7c110b00e7930d19b..728c84695eacf0e3117e8246a75ebb12b18a2c19 100644 (file)
@@ -13,7 +13,7 @@
 // a variety of errors from the older, AST-based machinery (notably
 // borrowck), and then we get the NLL error at the end.
 
-// compile-flags:-Znll -Zborrowck=compare
+// compile-flags:-Zborrowck=compare
 
 struct Map {
 }
index 272cb6510aa3ddc02ab27cf11444b502696ffb74..f3952c49a2a36fecd13ff84996782ed83cff5d39 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/issue-47388.rs:18:5
    |
 LL |     let fancy_ref = &(&mut fancy);
-   |                     ------------- help: consider changing this to be a mutable reference: `&mut`
+   |                     ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)`
 LL |     fancy_ref.num = 6; //~ ERROR E0594
    |     ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written
 
index d4df2a01c8143e97a6c4a30df74c8d30be74e158..5538eca362974acc261c0e35fee9d53e8a0297ce 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir
 
 
 #![allow(warnings)]
index 7e8a4e0ec95fc9e313f225da4128c1b6065c868f..ae815a5efe97c7f528ed287d9255156aabc68baf 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll
+// compile-flags: -Z emit-end-regions -Zborrowck=mir
 // compile-pass
 
 #![allow(warnings)]
index 2eb90dca7026ec2182d728b9d2c6e8ed7c2f0970..00d146e0f02d6b672099fe1a164e6a378d140586 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir
 
 #![allow(warnings)]
 
index f639d8f243f1423cfeb124a4bdd3267cd6f49b50..cd46014a7f5ca45dfbd2c1ee533f41c9c43ac9ef 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir
 
 #![allow(warnings)]
 
index c2cc479d28e3e78a12a69a2c098ad34449d71378..9a3aca346208d72d4b330b4f40f6b51c60abca63 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir
 
 #![allow(warnings)]
 
index 1515911fe870eb777a47e635fb7ee90e59f4f955..c1abcb434e68f8486cfdcd8742316265ec94266c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir
+// compile-flags:-Zborrowck=mir
 // compile-pass
 
 #![feature(rustc_attrs)]
index 571bd9fd76e86eb011759b94af1a452c73105a34..f21127064d4c2ee1880b2e22300242ea85d55fa8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 
@@ -19,7 +19,7 @@ impl<'a, T> Foo<'a> for T { }
 
 fn foo<'a, T>(x: &T) -> impl Foo<'a> {
     x
-        //~^ WARNING not reporting region error due to -Znll
+        //~^ WARNING not reporting region error due to nll
         //~| ERROR explicit lifetime required in the type of `x` [E0621]
 }
 
index 92e4f72da3a10ddb0b0ae837cce397de916c10ef..f836960a28cf372d4b492945dd41ab6fcdb1deb7 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/impl-trait-captures.rs:21:5
    |
 LL |     x
index 2e0671f1a51e84a0b1dec72ef66f33d20164b24c..182e11da082f8d367afccd1b33a8e7784caf196a 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 
 use std::fmt::Debug;
 
 fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
 where
     T: Debug,
 {
@@ -31,7 +31,7 @@ fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
 }
 
 fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
 where
     T: 'b + Debug,
 {
index 2b90d53774e6515df02bb16b962063ead42c0a6c..50b80282e6241daae24f6a5e1093ab0344359f4f 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/impl-trait-outlives.rs:17:35
    |
 LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
    |                                   ^^^^^^^^^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/impl-trait-outlives.rs:33:42
    |
 LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
index 0ec6d7b74ad5add6c7f9948d3d2babe23347e9c2..d8f077467d9fcfca2bb4f030aa91974c7a8ec8df 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 // Test that we can deduce when projections like `T::Item` outlive the
 // function body. Test that this does not imply that `T: 'a` holds.
@@ -43,7 +43,7 @@ fn invoke1<'a, T>(x: Cell<&'a Option<T>>)
 #[rustc_errors]
 fn generic2<T: Iterator>(value: T) {
     twice(value, |value_ref, item| invoke2(value_ref, item));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
 }
 
index fa53967ed3aca652e207e6b04112f3380d4a9000..0a2bd3247655ae019783391c7b618567e64ffd21 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-implied-bounds.rs:45:36
    |
 LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
index 0493bd1ea0d9cce01b3602e5332330e275f8cdaf..7b3ed6a94fcbb642951a69d156517a304f03c3fd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 // Tests closures that propagate an outlives relationship to their
 // creator where the subject is a projection with no regions (`<T as
@@ -34,7 +34,7 @@ fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
     T: Iterator,
 {
     with_signature(x, |mut y| Box::new(y.next()))
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
@@ -52,7 +52,7 @@ fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
     T: 'b + Iterator,
 {
     with_signature(x, |mut y| Box::new(y.next()))
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
index bcdf984f65a8a8db6889a79cd8401da26dcb23c3..0efbbdff12a3f25627b881adbf3d6f67d8821da6 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-no-regions-closure.rs:36:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                               ^^^^^^^^^^^^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-no-regions-closure.rs:54:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
index 5f2e84e247a3c925911b708fabe438d96c73685c..32b73a51e11a527c198893dd30b74ad114270e53 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -22,7 +22,7 @@ fn no_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a>
     T: Iterator,
 {
     Box::new(x.next())
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
@@ -38,7 +38,7 @@ fn wrong_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a>
     T: 'b + Iterator,
 {
     Box::new(x.next())
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
index 95851e7edc70c62bfb2ba2c1f0c13f177f84f5cf..b2c5f28268db893382fbc78a9741a9cfe5e8c15e 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-no-regions-fn.rs:24:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-no-regions-fn.rs:40:5
    |
 LL |     Box::new(x.next())
index 9a5e04deddfc92ce5a20265c30446027c0047c49..cfe2880bfed476795ff5c84470c3f70444de5362 100644 (file)
@@ -22,7 +22,7 @@
 //
 // Ensuring that both `T: 'a` and `'b: 'a` holds does work (`elements_outlive`).
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -54,7 +54,7 @@ fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
     //~| ERROR does not outlive free region
 }
@@ -66,7 +66,7 @@ fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     'a: 'a,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
     //~| ERROR does not outlive free region
 }
@@ -88,7 +88,7 @@ fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     // can do better here with a more involved verification step.
 
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
     //~| ERROR free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
 }
index aa45cf187010625eeb1ed76697e1c560eae44054..0d5a2dc7c559855b5138e8e9f2b3767bbe0fe48b 100644 (file)
@@ -1,16 +1,16 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-one-region-closure.rs:56:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-one-region-closure.rs:68:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-one-region-closure.rs:90:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
index 232025b57355cf98f5037d52e371b6e1e1358f90..16e91f2708fe94495627d0422a670af279e32d78 100644 (file)
@@ -14,7 +14,7 @@
 // case, the best way to satisfy the trait bound is to show that `'b:
 // 'a`, which can be done in various ways.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -46,7 +46,7 @@ fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR does not outlive free region
 }
 
@@ -57,7 +57,7 @@ fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     'a: 'a,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR does not outlive free region
 }
 
@@ -78,7 +78,7 @@ fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     // can do better here with a more involved verification step.
 
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR does not outlive free region
 }
 
index 7a8010ad8e0ea94f7c2d8503df2e2a95b312f4b7..d4aca8380b469f2812d143a79db70f17cf7a4932 100644 (file)
@@ -1,16 +1,16 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-one-region-trait-bound-closure.rs:48:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-one-region-trait-bound-closure.rs:59:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-one-region-trait-bound-closure.rs:80:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
index a1bdd1b89f9a96c06e9eab8daa8e6d8a0135efce..0d42636c844a55acfbe54bc65a8394aa5b7cc3ce 100644 (file)
@@ -12,7 +12,7 @@
 // outlive `'static`. In this case, we don't get any errors, and in fact
 // we don't even propagate constraints from the closures to the callers.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 // compile-pass
 
 #![allow(warnings)]
index e3cee00ed4eb3b7539928eb4bdfb31403fa13d10..7c8ef140a29074296ec8cb6f885e12a343fd8090 100644 (file)
@@ -15,7 +15,7 @@
 // the trait bound, and hence we propagate it to the caller as a type
 // test.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -47,7 +47,7 @@ fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b, 'c>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
 }
 
@@ -58,7 +58,7 @@ fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
     'a: 'a,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
 }
 
@@ -79,7 +79,7 @@ fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
     // can do better here with a more involved verification step.
 
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
 }
 
@@ -107,7 +107,7 @@ fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b, 'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR does not outlive free region
 }
 
index c7cbdaec3395c18174a963744b5a77e2c66ee992..7e36e467e4eba32ac700b48afea06ddae3016521 100644 (file)
@@ -1,22 +1,22 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-two-region-trait-bound-closure.rs:49:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-two-region-trait-bound-closure.rs:60:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-two-region-trait-bound-closure.rs:81:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/projection-two-region-trait-bound-closure.rs:109:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
index 423747a6bd6cbb927aa271f8d9739d93607ec1c4..80b42c29563f1b5fb579a174117817032412f924 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
index 997cc57cfa28c48269ed8fc1bedd01df7c10acd1..c8feaddff9382ddf2d335c5e1954445256690ed4 100644 (file)
@@ -1,16 +1,16 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
index 95a483b3c355d00058fe1fd36f9c1cb65949c6ef..50763a1d5080808c6572da682d43073cbcf30cdf 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -35,7 +35,7 @@ fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
     // `'a` (and subsequently reports an error).
 
     with_signature(x, |y| y)
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
 }
 
@@ -51,7 +51,7 @@ fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
     T: 'b + Debug,
 {
     x
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
 }
 
index ba08bc1ff7b43c3c513d8e94fe4763bc3abac49d..500595e0c5dcaf21e32d80fe80168cd661a86e94 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:27
    |
 LL |     with_signature(x, |y| y)
    |                           ^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
    |
 LL |     x
index 1149f250a46e2f53b7deacba724f8f295033eb40..b70fc2b2ec4b40d6f0ee38e911a7e06afd4716b8 100644 (file)
@@ -12,7 +12,7 @@
 // `correct_region` for an explanation of how this test is setup; it's
 // somewhat intricate.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -43,7 +43,7 @@ fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
         // function, there is no where clause *anywhere*, and hence we
         // get an error (but reported by the closure creator).
         require(&x, &y)
-        //~^ WARNING not reporting region error due to -Znll
+        //~^ WARNING not reporting region error due to nll
     })
 }
 
@@ -77,7 +77,7 @@ fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
         //~^ ERROR the parameter type `T` may not live long enough
         // See `correct_region`
         require(&x, &y)
-        //~^ WARNING not reporting region error due to -Znll
+        //~^ WARNING not reporting region error due to nll
     })
 }
 
index fcdb0b0a4a9fea15bbf8034329a2a8220da120e7..4d8a66ba8e1c4cea182584b02fc2fda762a9383b 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:45:9
    |
 LL |         require(&x, &y)
    |         ^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:79:9
    |
 LL |         require(&x, &y)
@@ -19,7 +19,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         //
 LL | |         // See `correct_region`, which explains the point of this
 ...  |
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     })
    | |_____^
    |
@@ -40,7 +40,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         //
 LL | |         // See `correct_region`, which explains the point of this
 ...  |
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     })
    | |_____^
    |
@@ -109,7 +109,7 @@ LL |       with_signature(a, b, |x, y| {
 LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         // See `correct_region`
 LL | |         require(&x, &y)
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     })
    | |_____^
    |
@@ -130,7 +130,7 @@ LL |       with_signature(a, b, |x, y| {
 LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         // See `correct_region`
 LL | |         require(&x, &y)
-LL | |         //~^ WARNING not reporting region error due to -Znll
+LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     })
    | |_____^
    |
index e66c1853b64b9167e73a39b6e8c9f20d2c2ce0da..fb4ea63f8532cd9c24d9d63f52c3c0e40f03d6bd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir
+// compile-flags:-Zborrowck=mir
 
 // Test that we assume that universal types like `T` outlive the
 // function body.
@@ -28,7 +28,7 @@ fn region_within_body<T>(t: T) {
 // Error here, because T: 'a is not satisfied.
 fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
     outlives(cell, t)
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| ERROR the parameter type `T` may not live long enough
 }
 
index 34ed709a2730e0afae779688e78596601412e3e9..0596861e67b572b8bbf67e9b10a15d9d3c394bdf 100644 (file)
@@ -1,4 +1,4 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-fn-body.rs:30:5
    |
 LL |     outlives(cell, t)
index aa3a03afa35cdbfd2acb818366c050389ad568d0..42d662e14193ccbce257bdb8ea6da923b8bd9366 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir
+// compile-flags:-Zborrowck=mir
 
 #![allow(warnings)]
 #![feature(dyn_trait)]
@@ -20,7 +20,7 @@ fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
     T: Debug,
 {
     x
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| the parameter type `T` may not live long enough
 }
 
@@ -36,7 +36,7 @@ fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
     T: 'b + Debug,
 {
     x
-    //~^ WARNING not reporting region error due to -Znll
+    //~^ WARNING not reporting region error due to nll
     //~| the parameter type `T` may not live long enough
 }
 
index 98ccfc52029ffbe9dc00f94049978379284411dd..0d09cac8c38513da8abfeffbcdd91ffbb5a16c6a 100644 (file)
@@ -1,10 +1,10 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-fn.rs:22:5
    |
 LL |     x
    |     ^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/ty-param-fn.rs:38:5
    |
 LL |     x
index d4ae9b20e56ff21e15cc3dec621d9a7fffb742fd..51927d353ecc49ce12edd8bbabebd870ae716925 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Zborrowck=mir -Zverbose
 // compile-pass
 
 // Test that we assume that universal types like `T` outlive the
index 1908ef244cfeaec83dfab2ff8269620c995e8b6c..9ae86136a909170585b9513f41fd35d144858bc0 100644 (file)
@@ -11,6 +11,7 @@
 // compile-flags: -Z print-type-sizes
 // compile-pass
 
+#![feature(never_type)]
 #![feature(start)]
 
 #[start]
index 3e39b75d8c0f33010564f2699e87a188c5bbbba1..26760cfea4478cc1f39abde71abae7d9a1fa6416 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
+#![feature(never_type)]
 #![allow(unused_variables)]
 #![deny(unreachable_code)]
 
index 73083af34d97d3ddab8f162a42667273ab050a75..308f2483be50a95b6bc3fc90b53094e85885adff 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
+#![feature(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 2772dd429d184275d4b97c65892f4d4f4083ce56..9696bdadf87e803cddf70b12033f879f1c061f10 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
+#![feature(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 88846b638416a5a9da4ea22622003f4fb6365413..fc0041daf7c7c8635a4f433ba4f19b1dcc21c33b 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(type_ascription)]
+#![feature(never_type, type_ascription)]
 
 fn a() {
     // the cast is unreachable:
index 7dabb307097622859232eef056fb7d510dcb61ce..c91646cfa1ef119b17fa061f384897268cae6344 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
+#![feature(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 2381ea2ac7a1b0b727cb2f99e57251e8242e4f5d..ce12412ba7438a6595a64733100a5b6e8be8b0e5 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(type_ascription)]
+#![feature(never_type, type_ascription)]
 
 fn a() {
     // the cast is unreachable:
index 4096865f4c6705fb4f0f06552de80f3b3961bde2..5b7ea57b1661a01f21efe9af5ae8781fcf771a30 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
+#![feature(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 34f8a0a48431c8f36d3205dcf617ad86e36d6973..5ae4ce1f7ee302e54740282d5ec0a2cb9242e9c0 100644 (file)
@@ -13,6 +13,6 @@ pub trait ToNbt<T> {
 }
 
 impl ToNbt<Self> {}
-//~^ ERROR cyclic dependency detected
+//~^ ERROR cycle detected
 
 fn main() {}
index 63b7ab78b13e0ef9a5d6b8345180d72c832e2e63..d25a072fe0a886bdec4a57bcd6a88d655b1aef88 100644 (file)
@@ -1,15 +1,10 @@
-error[E0391]: cyclic dependency detected
+error[E0391]: cycle detected when processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`
   --> $DIR/issue-23305.rs:15:12
    |
 LL | impl ToNbt<Self> {}
-   |            ^^^^ cyclic reference
+   |            ^^^^
    |
-note: the cycle begins when processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`...
-  --> $DIR/issue-23305.rs:15:1
-   |
-LL | impl ToNbt<Self> {}
-   | ^^^^^^^^^^^^^^^^
-   = note: ...which then again requires processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`, completing the cycle.
+   = note: ...which again requires processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`, completing the cycle
 
 error: aborting due to previous error
 
index 6ae5f777a9396808df73850d8b3f129a5abe5406..b97bdeea409c6310e431d7139356b1cf6f07d246 100644 (file)
@@ -1,20 +1,26 @@
-error[E0594]: cannot assign to immutable item `*x`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/enum.rs:19:5
    |
+LL |     let Wrap(x) = &Wrap(3);
+   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |     *x += 1; //~ ERROR cannot assign to immutable
-   |     ^^^^^^^ cannot mutate
+   |     ^^^^^^^
 
-error[E0594]: cannot assign to immutable item `*x`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/enum.rs:23:9
    |
+LL |     if let Some(x) = &Some(3) {
+   |                 - help: consider changing this to be a mutable reference: `&mut`
 LL |         *x += 1; //~ ERROR cannot assign to immutable
-   |         ^^^^^^^ cannot mutate
+   |         ^^^^^^^
 
-error[E0594]: cannot assign to immutable item `*x`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/enum.rs:29:9
    |
+LL |     while let Some(x) = &Some(3) {
+   |                    - help: consider changing this to be a mutable reference: `&mut`
 LL |         *x += 1; //~ ERROR cannot assign to immutable
-   |         ^^^^^^^ cannot mutate
+   |         ^^^^^^^
 
 error: aborting due to 3 previous errors
 
index 7138c4ac06e1fb4c01b63525d0d5c04a57b3bb6f..3ee4dc07bb8bbb05bb993fcdfe2ec3bcd1341aa4 100644 (file)
@@ -1,20 +1,26 @@
-error[E0594]: cannot assign to immutable item `*n`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/explicit-mut.rs:17:13
    |
+LL |         Some(n) => {
+   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^ cannot mutate
+   |             ^^^^^^^
 
-error[E0594]: cannot assign to immutable item `*n`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/explicit-mut.rs:25:13
    |
+LL |         Some(n) => {
+   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^ cannot mutate
+   |             ^^^^^^^
 
-error[E0594]: cannot assign to immutable item `*n`
+error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/explicit-mut.rs:33:13
    |
+LL |         Some(n) => {
+   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^ cannot mutate
+   |             ^^^^^^^
 
 error: aborting due to 3 previous errors
 
index 505ee95088f559f51f8b140c172469f4e090b906..26e9ea4dc0bc86b286cf22f096acaa46dc4bd4cc 100644 (file)
@@ -24,7 +24,7 @@ error[E0596]: cannot borrow immutable item `*f.f` as mutable
 LL |     f.f.call_mut(())
    |     ^^^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `*f`
+   = note: the value which is causing this path not to be mutable is...: `*f`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
index 100b5ae150a7de9be84e3f4e87fbbcc986802215..9b5e084bd375134372d1863b936b27a527bcc498 100644 (file)
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow immutable item `*x` as mutable
 LL |     x.borrowed_mut(); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
    |
-   = note: Value not mutable causing this error: `x`
+   = note: the value which is causing this path not to be mutable is...: `x`
 
 error: aborting due to 2 previous errors
 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5de246cbb73413f78cd530aa30250ae2f567ba84 100644 (file)
@@ -0,0 +1,16 @@
+error[E0597]: `*a` does not live long enough
+  --> $DIR/destructor-restrictions.rs:18:10
+   |
+LL |         *a.borrow() + 1
+   |          ^---------
+   |          |
+   |          borrowed value does not live long enough
+   |          borrow may end up in a temporary, created here
+LL |     }; //~^ ERROR `*a` does not live long enough
+   |     -- temporary later dropped here, potentially using the reference
+   |     |
+   |     borrowed value only lives until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
index 41edd04c92e8c21a3f6df71c91dbe557aa34f0e7..b7f8b85f46cee83f7027c80e5a3178695dc00765 100644 (file)
@@ -1,5 +1,5 @@
 error[E0597]: `c1` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:118:24
+  --> $DIR/dropck_vec_cycle_checked.rs:121:24
    |
 LL |     c3.v[0].v.set(Some(&c1));
    |                        ^^^ borrowed value does not live long enough
@@ -11,7 +11,7 @@ LL | }
    | borrow later used here, when `c1` is dropped
 
 error[E0597]: `c2` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:110:24
+  --> $DIR/dropck_vec_cycle_checked.rs:113:24
    |
 LL |     c1.v[0].v.set(Some(&c2));
    |                        ^^^ borrowed value does not live long enough
@@ -23,7 +23,7 @@ LL | }
    | borrow later used here, when `c1` is dropped
 
 error[E0597]: `c3` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:112:24
+  --> $DIR/dropck_vec_cycle_checked.rs:115:24
    |
 LL |     c1.v[1].v.set(Some(&c3));
    |                        ^^^ borrowed value does not live long enough
index 0560900e85855c9c2da18f13eeb7970a31cbd52d..ece58d21ba932a2072d9b59ea8aafb0f466cac9d 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -Z nll-subminimal-causes
+// (Work around rust-lang/rust#49998 by opting into nll-subminimal-causes.)
+
 // Reject mixing cyclic structure and Drop when using Vec.
 //
 // (Compare against compile-fail/dropck_arr_cycle_checked.rs)
index 63b0ab52d395a2446c617723575566c4aa64f56f..a6bc8da6f7c0c661d8517db1c5af35fcba9a9398 100644 (file)
@@ -1,5 +1,5 @@
 error[E0597]: `c2` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:110:25
+  --> $DIR/dropck_vec_cycle_checked.rs:113:25
    |
 LL |     c1.v[0].v.set(Some(&c2));
    |                         ^^ borrowed value does not live long enough
@@ -10,7 +10,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c3` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:112:25
+  --> $DIR/dropck_vec_cycle_checked.rs:115:25
    |
 LL |     c1.v[1].v.set(Some(&c3));
    |                         ^^ borrowed value does not live long enough
@@ -21,7 +21,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c2` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:114:25
+  --> $DIR/dropck_vec_cycle_checked.rs:117:25
    |
 LL |     c2.v[0].v.set(Some(&c2));
    |                         ^^ borrowed value does not live long enough
@@ -32,7 +32,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c3` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:116:25
+  --> $DIR/dropck_vec_cycle_checked.rs:119:25
    |
 LL |     c2.v[1].v.set(Some(&c3));
    |                         ^^ borrowed value does not live long enough
@@ -43,7 +43,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c1` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:118:25
+  --> $DIR/dropck_vec_cycle_checked.rs:121:25
    |
 LL |     c3.v[0].v.set(Some(&c1));
    |                         ^^ borrowed value does not live long enough
@@ -54,7 +54,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c2` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:120:25
+  --> $DIR/dropck_vec_cycle_checked.rs:123:25
    |
 LL |     c3.v[1].v.set(Some(&c2));
    |                         ^^ borrowed value does not live long enough
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..56f2d14390ecdb5ee60001ff3214dc6c67cb9301 100644 (file)
@@ -0,0 +1,30 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:20:5
+   |
+LL |     y.borrow().clone()
+   |     ^---------
+   |     |
+   |     borrowed value does not live long enough
+   |     borrow may end up in a temporary, created here
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | temporary later dropped here, potentially using the reference
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9
+   |
+LL |         y.borrow().clone()
+   |         ^---------
+   |         |
+   |         borrowed value does not live long enough
+   |         borrow may end up in a temporary, created here
+LL |     };
+   |     -- temporary later dropped here, potentially using the reference
+   |     |
+   |     borrowed value only lives until here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
index a175cf1b38a448d1ef1168accca1c5b04fb8ffbe..063ac376b05ecc43f9e08ed87345336f6e4deeee 100644 (file)
@@ -1,14 +1,14 @@
-error: compilation successful
-  --> $DIR/wf-method-late-bound-regions.rs:25:1
+error[E0597]: `pointer` does not live long enough
+  --> $DIR/wf-method-late-bound-regions.rs:30:18
    |
-LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
-LL | |     let f = Foo(None);
-LL | |     let f2 = f;
-LL | |     let dangling = {
-...  |
-LL | |     println!("{}", dangling);
-LL | | }
-   | |_^
+LL |         f2.xmute(&pointer)
+   |                  ^^^^^^^^ borrowed value does not live long enough
+LL |     };
+   |     - borrowed value only lives until here
+LL |     //~^^ ERROR `pointer` does not live long enough
+LL |     println!("{}", dangling);
+   |                    -------- borrow later used here
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0597`.
index 317cd395d0a736f7a08654b6216421e5deecd7ac..d58c29d4a32d3bdfd307e4379b01302d6b1f7d85 100644 (file)
@@ -11,7 +11,7 @@
 // A method's receiver must be well-formed, even if it has late-bound regions.
 // Because of this, a method's substs being well-formed does not imply that
 // the method's implied bounds are met.
-#![feature(rustc_attrs)]
+
 struct Foo<'b>(Option<&'b ()>);
 
 trait Bar<'b> {
@@ -22,7 +22,7 @@ impl<'b> Bar<'b> for Foo<'b> {
     fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u }
 }
 
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
     let f = Foo(None);
     let f2 = f;
     let dangling = {
index fa5bafab8717e82bb018d1fc718cda78ea01e051..2e452f9671f380fd21b3b9e073359a80579c1ba4 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 fn main() {
-    let x = 2.0.powi(2);
-    //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+    let x = 2.0.recip();
+    //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
     let y = 2.0;
-    let x = y.powi(2);
-    //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+    let x = y.recip();
+    //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
     println!("{:?}", x);
 }
index 92ad22806156719623d06222281e96a279bbebfb..477b4c3821d51bc2f9aa5cc982a677a3919d59ee 100644 (file)
@@ -1,18 +1,18 @@
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
    |
-LL |     let x = 2.0.powi(2);
-   |                 ^^^^
+LL |     let x = 2.0.recip();
+   |                 ^^^^^
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |     let x = 2.0_f32.powi(2);
+LL |     let x = 2.0_f32.recip();
    |             ^^^^^^^
 
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
    |
-LL |     let x = y.powi(2);
-   |               ^^^^
+LL |     let x = y.recip();
+   |               ^^^^^
 help: you must specify a type for this binding, like `f32`
    |
 LL |     let y: f32 = 2.0;
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
new file mode 100644 (file)
index 0000000..69208f1
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-arm
+// ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
+// gate-test-sse4a_target_feature
+// gate-test-powerpc_target_feature
+// gate-test-avx512_target_feature
+// gate-test-tbm_target_feature
+// gate-test-arm_target_feature
+// gate-test-aarch64_target_feature
+// gate-test-hexagon_target_feature
+// gate-test-mips_target_feature
+// gate-test-mmx_target_feature
+// min-llvm-version 6.0
+
+#[target_feature(enable = "avx512bw")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {
+}
+
+fn main() {}
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
new file mode 100644 (file)
index 0000000..dc5e174
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: the target feature `avx512bw` is currently unstable
+  --> $DIR/target-feature-gate.rs:26:18
+   |
+LL | #[target_feature(enable = "avx512bw")]
+   |                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(avx512_target_feature)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index eb83ee724c785804d5f6332164ae28cdcbc57d39..0edd51ba779ac4eb0009a15ac3f3aa3a58f654fb 100644 (file)
@@ -19,7 +19,7 @@
 #![feature(target_feature)]
 
 #[target_feature = "+sse2"]
-//~^ WARN: deprecated
+//~^ ERROR: must be of the form
 #[target_feature(enable = "foo")]
 //~^ ERROR: not valid for this target
 #[target_feature(bar)]
index b5e650eaf9ac4373acd8cb2284fa1c5665ef261b..ed86687bb2fccbec23171b60c6a03989041a6a84 100644 (file)
@@ -1,4 +1,4 @@
-warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead
+error: #[target_feature] attribute must be of the form #[target_feature(..)]
   --> $DIR/target-feature-wrong.rs:21:1
    |
 LL | #[target_feature = "+sse2"]
@@ -43,5 +43,5 @@ error: cannot use #[inline(always)] with #[target_feature]
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
index f8ea891914ec676a66141d3a4214cfd0f0c03fc1..10a03786d7b1fa2a3353b8bc6fc003ae95c11df9 100644 (file)
@@ -1,22 +1,22 @@
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/dyn-trait-underscore.rs:20:14
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |              ^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/dyn-trait-underscore.rs:20:20
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |                    ^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/dyn-trait-underscore.rs:20:5
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^
 
-warning: not reporting region error due to -Znll
+warning: not reporting region error due to nll
   --> $DIR/dyn-trait-underscore.rs:20:5
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
index c2c842fcc4984bee519417c0bfea6790b53db4a8..4fc11daaa3afa0de5758d8c046f433467e571299 100755 (executable)
@@ -31,18 +31,17 @@ MYDIR=$(dirname $0)
 BUILD_DIR="$1"
 shift
 
+shopt -s nullglob
+
 while [[ "$1" != "" ]]; do
-    STDERR_NAME="${1/%.rs/.stderr}"
-    STDOUT_NAME="${1/%.rs/.stdout}"
+    for EXT in "stderr" "stdout"; do
+        for OUT_NAME in $BUILD_DIR/${1%.rs}.*$EXT; do
+            OUT_BASE=`basename "$OUT_NAME"`
+            if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then
+                echo updating $MYDIR/$OUT_BASE
+                cp $OUT_NAME $MYDIR
+            fi
+        done
+    done
     shift
-    if [ -f $BUILD_DIR/$STDOUT_NAME ] && \
-           ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then
-        echo updating $MYDIR/$STDOUT_NAME
-        cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME
-    fi
-    if [ -f $BUILD_DIR/$STDERR_NAME ] && \
-           ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then
-        echo updating $MYDIR/$STDERR_NAME
-        cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME
-    fi
 done
index 008c3690846798d678f4a0a45ee46cc9ff6dc90f..0a1add2d8689ad12a86f6c32d0a5cd0393dc5d80 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 008c3690846798d678f4a0a45ee46cc9ff6dc90f
+Subproject commit 0a1add2d8689ad12a86f6c32d0a5cd0393dc5d80
index 8ec61a613ad1278b18a4770332b6da128704fdd6..c5b39a5917ffc0f1349b6e414fa3b874fdcf8429 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8ec61a613ad1278b18a4770332b6da128704fdd6
+Subproject commit c5b39a5917ffc0f1349b6e414fa3b874fdcf8429
index 41fc67a66f47df828fd6f380c9c8e8607a78f57e..365b47447f23a92477694417feeedca494a8bd6d 100644 (file)
@@ -101,7 +101,7 @@ pub enum CompareMode {
 }
 
 impl CompareMode {
-    fn to_str(&self) -> &'static str {
+    pub(crate) fn to_str(&self) -> &'static str {
         match *self {
             CompareMode::Nll => "nll"
         }
index 80cab96434ba784fa2679228d56a0c6d390b54e0..37f7af0abe8f56e32d72a00640d59bfd365ee01a 100644 (file)
@@ -283,6 +283,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         ),
     };
 
+    let src_base = opt_path(matches, "src-base");
+    let run_ignored = matches.opt_present("ignored");
     Config {
         compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
         run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
@@ -293,7 +295,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         valgrind_path: matches.opt_str("valgrind-path"),
         force_valgrind: matches.opt_present("force-valgrind"),
         llvm_filecheck: matches.opt_str("llvm-filecheck").map(|s| PathBuf::from(&s)),
-        src_base: opt_path(matches, "src-base"),
+        src_base,
         build_base: opt_path(matches, "build-base"),
         stage_id: matches.opt_str("stage-id").unwrap(),
         mode: matches
@@ -301,7 +303,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
             .unwrap()
             .parse()
             .expect("invalid mode"),
-        run_ignored: matches.opt_present("ignored"),
+        run_ignored,
         filter: matches.free.first().cloned(),
         filter_exact: matches.opt_present("exact"),
         logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
@@ -624,7 +626,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
 
     // Debugging emscripten code doesn't make sense today
     let ignore = early_props.ignore
-        || (!up_to_date(config, testpaths, &early_props) && config.compare_mode.is_none())
+        || !up_to_date(config, testpaths, &early_props)
         || (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
             && config.target.contains("emscripten");
 
@@ -640,10 +642,15 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
 }
 
 fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf {
+    let mode_suffix = match config.compare_mode {
+        Some(ref mode) => format!("-{}", mode.to_str()),
+        None => format!(""),
+    };
     let stamp_name = format!(
-        "{}-{}.stamp",
+        "{}-{}{}.stamp",
         testpaths.file.file_name().unwrap().to_str().unwrap(),
-        config.stage_id
+        config.stage_id,
+        mode_suffix
     );
     config
         .build_base
@@ -726,7 +733,11 @@ pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName
     let path = PathBuf::from(config.src_base.file_name().unwrap())
         .join(&testpaths.relative_dir)
         .join(&testpaths.file.file_name().unwrap());
-    test::DynTestName(format!("[{}] {}", config.mode, path.display()))
+    let mode_suffix = match config.compare_mode {
+        Some(ref mode) => format!(" ({})", mode.to_str()),
+        None => format!(""),
+    };
+    test::DynTestName(format!("[{}{}] {}", config.mode, mode_suffix, path.display()))
 }
 
 pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn {
index db0ac9279046ca8403f35103e4e98471460c2c39..aabf2e6f8f0e675c2e918e7491c1cd59546c75d0 100644 (file)
@@ -26,7 +26,7 @@
 use std::collections::HashMap;
 use std::collections::HashSet;
 use std::env;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fs::{self, create_dir_all, File};
 use std::fmt;
 use std::io::prelude::*;
@@ -72,6 +72,26 @@ fn new(line_number: u32) -> Mismatch {
     }
 }
 
+trait PathBufExt {
+    /// Append an extension to the path, even if it already has one.
+    fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf;
+}
+
+impl PathBufExt for PathBuf {
+    fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
+        if extension.as_ref().len() == 0 {
+            self.clone()
+        } else {
+            let mut fname = self.file_name().unwrap().to_os_string();
+            if !extension.as_ref().to_str().unwrap().starts_with(".") {
+                fname.push(".");
+            }
+            fname.push(extension);
+            self.with_file_name(fname)
+        }
+    }
+}
+
 // Produces a diff between the expected output and actual output.
 pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
     let mut line_number = 1;
@@ -1288,7 +1308,9 @@ fn compile_test(&self) -> ProcRes {
                 // want to actually assert warnings about all this code. Instead
                 // let's just ignore unused code warnings by defaults and tests
                 // can turn it back on if needed.
-                rustc.args(&["-A", "unused"]);
+                if !self.config.src_base.ends_with("rustdoc-ui") {
+                    rustc.args(&["-A", "unused"]);
+                }
             }
             _ => {}
         }
@@ -1582,7 +1604,12 @@ fn compose_and_run(
     }
 
     fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
-        let mut rustc = Command::new(&self.config.rustc_path);
+        let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui");
+        let mut rustc = if !is_rustdoc {
+            Command::new(&self.config.rustc_path)
+        } else {
+            Command::new(&self.config.rustdoc_path.clone().expect("no rustdoc built yet"))
+        };
         rustc.arg(input_file).arg("-L").arg(&self.config.build_base);
 
         // Optionally prevent default --target if specified in test compile-flags.
@@ -1605,17 +1632,19 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
             rustc.args(&["--cfg", revision]);
         }
 
-        if let Some(ref incremental_dir) = self.props.incremental_dir {
-            rustc.args(&[
-                "-C",
-                &format!("incremental={}", incremental_dir.display()),
-            ]);
-            rustc.args(&["-Z", "incremental-verify-ich"]);
-            rustc.args(&["-Z", "incremental-queries"]);
-        }
+        if !is_rustdoc {
+            if let Some(ref incremental_dir) = self.props.incremental_dir {
+                rustc.args(&[
+                    "-C",
+                    &format!("incremental={}", incremental_dir.display()),
+                ]);
+                rustc.args(&["-Z", "incremental-verify-ich"]);
+                rustc.args(&["-Z", "incremental-queries"]);
+            }
 
-        if self.config.mode == CodegenUnits {
-            rustc.args(&["-Z", "human_readable_cgu_names"]);
+            if self.config.mode == CodegenUnits {
+                rustc.args(&["-Z", "human_readable_cgu_names"]);
+            }
         }
 
         match self.config.mode {
@@ -1668,11 +1697,12 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
             }
         }
 
-
-        if self.config.target == "wasm32-unknown-unknown" {
-            // rustc.arg("-g"); // get any backtrace at all on errors
-        } else if !self.props.no_prefer_dynamic {
-            rustc.args(&["-C", "prefer-dynamic"]);
+        if !is_rustdoc {
+            if self.config.target == "wasm32-unknown-unknown" {
+                // rustc.arg("-g"); // get any backtrace at all on errors
+            } else if !self.props.no_prefer_dynamic {
+                rustc.args(&["-C", "prefer-dynamic"]);
+            }
         }
 
         match output_file {
@@ -1686,7 +1716,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
 
         match self.config.compare_mode {
             Some(CompareMode::Nll) => {
-                rustc.args(&["-Znll", "-Zborrowck=mir", "-Ztwo-phase-borrows"]);
+                rustc.args(&["-Zborrowck=mir", "-Ztwo-phase-borrows"]);
             },
             None => {},
         }
@@ -1696,8 +1726,10 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
         } else {
             rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
         }
-        if let Some(ref linker) = self.config.linker {
-            rustc.arg(format!("-Clinker={}", linker));
+        if !is_rustdoc {
+            if let Some(ref linker) = self.config.linker {
+                rustc.arg(format!("-Clinker={}", linker));
+            }
         }
 
         rustc.args(&self.props.compile_flags);
@@ -1713,20 +1745,14 @@ fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
     }
 
     fn make_exe_name(&self) -> PathBuf {
-        let mut f = self.output_base_name();
+        let mut f = self.output_base_name_stage();
         // FIXME: This is using the host architecture exe suffix, not target!
         if self.config.target.contains("emscripten") {
-            let mut fname = f.file_name().unwrap().to_os_string();
-            fname.push(".js");
-            f.set_file_name(&fname);
+            f = f.with_extra_extension("js");
         } else if self.config.target.contains("wasm32") {
-            let mut fname = f.file_name().unwrap().to_os_string();
-            fname.push(".wasm");
-            f.set_file_name(&fname);
+            f = f.with_extra_extension("wasm");
         } else if !env::consts::EXE_SUFFIX.is_empty() {
-            let mut fname = f.file_name().unwrap().to_os_string();
-            fname.push(env::consts::EXE_SUFFIX);
-            f.set_file_name(&fname);
+            f = f.with_extra_extension(env::consts::EXE_SUFFIX);
         }
         f
     }
@@ -1834,25 +1860,28 @@ fn make_out_name(&self, extension: &str) -> PathBuf {
     }
 
     fn aux_output_dir_name(&self) -> PathBuf {
-        let f = self.output_base_name();
-        let mut fname = f.file_name().unwrap().to_os_string();
-        fname.push(&format!("{}.aux", self.config.mode.disambiguator()));
-        f.with_file_name(&fname)
+        self.output_base_name_stage()
+            .with_extra_extension(self.config.mode.disambiguator())
+            .with_extra_extension(".aux")
     }
 
     fn output_testname(&self, filepath: &Path) -> PathBuf {
         PathBuf::from(filepath.file_stem().unwrap())
     }
 
-    /// Given a test path like `compile-fail/foo/bar.rs` Returns a name like
-    ///
-    ///     <output>/foo/bar-stage1
+    /// Given a test path like `compile-fail/foo/bar.rs` returns a name like
+    /// `/path/to/build/<triple>/test/compile-fail/foo/bar`.
     fn output_base_name(&self) -> PathBuf {
         let dir = self.config.build_base.join(&self.testpaths.relative_dir);
 
         // Note: The directory `dir` is created during `collect_tests_from_dir`
         dir.join(&self.output_testname(&self.testpaths.file))
-            .with_extension(&self.config.stage_id)
+    }
+
+    /// Same as `output_base_name`, but includes the stage ID as an extension,
+    /// such as: `.../compile-fail/foo/bar.stage1-<triple>`
+    fn output_base_name_stage(&self) -> PathBuf {
+        self.output_base_name().with_extension(&self.config.stage_id)
     }
 
     fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
@@ -1977,7 +2006,7 @@ fn charset() -> &'static str {
     fn run_rustdoc_test(&self) {
         assert!(self.revision.is_none(), "revisions not relevant here");
 
-        let out_dir = self.output_base_name();
+        let out_dir = self.output_base_name_stage();
         let _ = fs::remove_dir_all(&out_dir);
         create_dir_all(&out_dir).unwrap();
 
@@ -2379,7 +2408,7 @@ fn run_rmake_test(&self) {
             .unwrap();
         let src_root = cwd.join(&src_root);
 
-        let tmpdir = cwd.join(self.output_base_name());
+        let tmpdir = cwd.join(self.output_base_name_stage());
         if tmpdir.exists() {
             self.aggressive_rm_rf(&tmpdir).unwrap();
         }
@@ -2509,7 +2538,6 @@ fn run_ui_test(&self) {
             .compile_flags
             .iter()
             .any(|s| s.contains("--error-format"));
-
         let proc_res = self.compile_test();
         self.check_if_test_should_compile(&proc_res);
 
@@ -2800,17 +2828,21 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
         normalized
     }
 
-    fn load_expected_output(&self, kind: &str) -> String {
+    fn expected_output_path(&self, kind: &str) -> PathBuf {
         let mut path = expected_output_path(&self.testpaths,
                                             self.revision,
                                             &self.config.compare_mode,
                                             kind);
-
         if !path.exists() && self.config.compare_mode.is_some() {
             // fallback!
             path = expected_output_path(&self.testpaths, self.revision, &None, kind);
         }
 
+        path
+    }
+
+    fn load_expected_output(&self, kind: &str) -> String {
+        let path = self.expected_output_path(kind);
         if path.exists() {
             match self.load_expected_output_from_path(&path) {
                 Ok(x) => x,
@@ -2864,7 +2896,12 @@ fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
             }
         }
 
-        let output_file = self.output_base_name().with_extension(kind);
+        let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str());
+        let output_file = self.output_base_name()
+            .with_extra_extension(self.revision.unwrap_or(""))
+            .with_extra_extension(mode)
+            .with_extra_extension(kind);
+
         match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
             Ok(()) => {}
             Err(e) => self.fatal(&format!(
index 554e3c0cd5f0bbd4771d57a69295829fbaba6bb5..5e11646ee4c196046d48da762e27e86b80f7133c 100644 (file)
@@ -8,6 +8,6 @@ license = "MIT/Apache-2.0"
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.1.5"
+version = "0.1.7"
 default-features = false
 features = ["search"]
index 7c9ee2a49430bee0e3d9eabf3976f743ac7a0295..6992f2ba123378d481baa367a5947e30f8f32d6d 100644 (file)
@@ -144,6 +144,7 @@ function main(argv) {
     var toolchain = argv[2];
 
     var mainJs = readFile("build/" + toolchain + "/doc/main.js");
+    var ALIASES = readFile("build/" + toolchain + "/doc/aliases.js");
     var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n");
     if (searchIndex[searchIndex.length - 1].length === 0) {
         searchIndex.pop();
@@ -157,9 +158,11 @@ function main(argv) {
     // execQuery first parameter is built in getQuery (which takes in the search input).
     // execQuery last parameter is built in buildIndex.
     // buildIndex requires the hashmap from search-index.
-    var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery"];
+    var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery",
+                           "execSearch"];
 
     finalJS += 'window = { "currentCrate": "std" };\n';
+    finalJS += ALIASES;
     finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
     finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs);
     finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs);
@@ -174,7 +177,7 @@ function main(argv) {
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
-        var results = loaded.execQuery(loaded.getQuery(query), index);
+        var results = loaded.execSearch(loaded.getQuery(query), index);
         process.stdout.write('Checking "' + file + '" ... ');
         var error_text = [];
         for (var key in expected) {
index 1415a4dc23f28644cb197b6bb69c311245c216e2..dd807e24656c91b4ad22d3cac146edd86315e633 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 1415a4dc23f28644cb197b6bb69c311245c216e2
+Subproject commit dd807e24656c91b4ad22d3cac146edd86315e633
index bda58bc09f77625714a23244b2018ebace908ddc..351005ff4b816b3038f4e6d99980f6320dd5d152 100644 (file)
 
 use std::path::Path;
 
-// See rust-lang/rust#48879: In addition to the mapping from `foo.rs`
-// to `foo.stderr`/`foo.stdout`, we also can optionally have
-// `foo.$mode.stderr`, where $mode is one of the strings on this list,
-// as an alternative to use when running under that mode.
-static COMPARE_MODE_NAMES: [&'static str; 1] = ["nll"];
-
 pub fn check(path: &Path, bad: &mut bool) {
     super::walk_many(&[&path.join("test/ui"), &path.join("test/ui-fulldeps")],
                      &mut |_| false,
                      &mut |file_path| {
         if let Some(ext) = file_path.extension() {
-            if (ext == "stderr" || ext == "stdout") && !file_path.with_extension("rs").exists() {
-
-                // rust-lang/rust#48879: this fn used to be beautful
-                // because Path API special-cases replacing
-                // extensions. That works great for ".stderr" but not
-                // so well for ".nll.stderr". To support the latter,
-                // we explicitly search backwards for mode's starting
-                // point and build corresponding source name.
-                let filename = file_path.file_name().expect("need filename")
-                    .to_str().expect("need UTF-8 filename");
-                let found_matching_prefix = COMPARE_MODE_NAMES.iter().any(|mode| {
-                    if let Some(r_idx) = filename.rfind(&format!(".{}", mode)) {
-                        let source_name = format!("{}.rs", &filename[0..r_idx]);
-                        let source_path = file_path.with_file_name(source_name);
-                        source_path.exists()
-                    } else {
-                        false
-                    }
-                });
-
-                if !found_matching_prefix {
+            if ext == "stderr" || ext == "stdout" {
+                // Test output filenames have the format:
+                // $testname.stderr
+                // $testname.$mode.stderr
+                // $testname.$revision.stderr
+                // $testname.$revision.$mode.stderr
+                //
+                // For now, just make sure that there is a corresponding
+                // $testname.rs file.
+                let testname = file_path.file_name().unwrap()
+                                        .to_str().unwrap()
+                                        .splitn(2, '.').next().unwrap();
+                if !file_path.with_file_name(testname)
+                             .with_extension("rs")
+                             .exists() {
                     println!("Stray file with UI testing output: {:?}", file_path);
                     *bad = true;
                 }