]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #45810 - SimonSapin:ac-dc, r=aturon
authorbors <bors@rust-lang.org>
Mon, 13 Nov 2017 11:46:55 +0000 (11:46 +0000)
committerbors <bors@rust-lang.org>
Mon, 13 Nov 2017 11:46:55 +0000 (11:46 +0000)
Disable LLVM assertions on Nightly, enable them in "alt" builds.

Per IRC discussion https://mozilla.logbot.info/rust-infra/20171106#c13812170-c13812204

Background: https://internals.rust-lang.org/t/disabling-llvm-assertions-in-nightly-builds/5388/14

454 files changed:
.travis.yml
src/Cargo.lock
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/dist.rs
src/bootstrap/install.rs
src/ci/docker/README.md
src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile [new file with mode: 0644]
src/ci/docker/disabled/dist-x86_64-dragonfly/build-toolchain.sh [new file with mode: 0755]
src/ci/docker/disabled/dist-x86_64-dragonfly/patch-toolchain [new file with mode: 0644]
src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
src/ci/docker/run.sh
src/doc/not_found.md
src/doc/unstable-book/src/library-features/rand.md [deleted file]
src/etc/char_private.py
src/liballoc/Cargo.toml
src/liballoc/lib.rs
src/liballoc/linked_list.rs
src/liballoc/str.rs
src/liballoc/tests/lib.rs
src/liballoc/tests/slice.rs
src/libbacktrace/configure
src/libbacktrace/configure.ac
src/libcore/Cargo.toml
src/libcore/benches/lib.rs
src/libcore/benches/slice.rs [new file with mode: 0644]
src/libcore/char_private.rs
src/libcore/fmt/mod.rs
src/libcore/hash/mod.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/option.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libcore/sync/atomic.rs
src/libcore/tests/num/flt2dec/mod.rs
src/libcore/tests/ptr.rs
src/libcore/tests/slice.rs
src/libcore/unit.rs [new file with mode: 0644]
src/libfmt_macros/lib.rs
src/libproc_macro/lib.rs
src/libproc_macro/quote.rs
src/librand/Cargo.toml [deleted file]
src/librand/chacha.rs [deleted file]
src/librand/distributions/exponential.rs [deleted file]
src/librand/distributions/gamma.rs [deleted file]
src/librand/distributions/mod.rs [deleted file]
src/librand/distributions/normal.rs [deleted file]
src/librand/distributions/range.rs [deleted file]
src/librand/distributions/ziggurat_tables.rs [deleted file]
src/librand/isaac.rs [deleted file]
src/librand/lib.rs [deleted file]
src/librand/rand_impls.rs [deleted file]
src/librand/reseeding.rs [deleted file]
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/hcx.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_mir.rs
src/librustc/infer/error_reporting/different_lifetimes.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/named_anon_conflict.rs
src/librustc/infer/error_reporting/util.rs
src/librustc/infer/region_inference/graphviz.rs
src/librustc/infer/region_inference/mod.rs
src/librustc/middle/cstore.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/free_region.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/mir/mod.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/ty/item_path.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/ty/util.rs
src/librustc/util/nodemap.rs
src/librustc_apfloat/lib.rs
src/librustc_back/Cargo.toml
src/librustc_back/lib.rs
src/librustc_back/target/mod.rs
src/librustc_back/tempdir.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_math/float.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_driver/lib.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/Cargo.toml
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/fs.rs
src/librustc_llvm/ffi.rs
src/librustc_llvm/lib.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_mir/borrow_check.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/clean_end_regions.rs
src/librustc_mir/transform/copy_prop.rs
src/librustc_mir/transform/erase_regions.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/nll/constraint_generation.rs
src/librustc_mir/transform/nll/free_regions.rs [new file with mode: 0644]
src/librustc_mir/transform/nll/mod.rs
src/librustc_mir/transform/nll/region_infer.rs
src/librustc_mir/transform/nll/renumber.rs
src/librustc_mir/transform/type_check.rs
src/librustc_mir/util/def_use.rs
src/librustc_mir/util/pretty.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/consts.rs
src/librustc_passes/diagnostics.rs
src/librustc_passes/mir_stats.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_save_analysis/span_utils.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/link.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/write.rs
src/librustc_trans/consts.rs
src/librustc_trans/context.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_trans/llvm_util.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/partitioning.rs
src/librustc_trans_utils/collector.rs
src/librustc_trans_utils/common.rs
src/librustc_trans_utils/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/diagnostics.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/test.rs
src/libstd/Cargo.toml
src/libstd/collections/hash/map.rs
src/libstd/env.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/ffi/c_str.rs
src/libstd/io/buffered.rs
src/libstd/io/stdio.rs
src/libstd/lib.rs
src/libstd/path.rs
src/libstd/rand/mod.rs [deleted file]
src/libstd/rt.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/redox/backtrace/tracing.rs
src/libstd/sys/redox/cmath.rs [new file with mode: 0644]
src/libstd/sys/redox/condvar.rs
src/libstd/sys/redox/fs.rs
src/libstd/sys/redox/mod.rs
src/libstd/sys/redox/rand.rs
src/libstd/sys/redox/stdio.rs
src/libstd/sys/unix/backtrace/printing/dladdr.rs
src/libstd/sys/unix/backtrace/printing/mod.rs
src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
src/libstd/sys/unix/cmath.rs [new file with mode: 0644]
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/rand.rs
src/libstd/sys/unix/stdio.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/windows/backtrace/mod.rs
src/libstd/sys/windows/backtrace/printing/msvc.rs
src/libstd/sys/windows/cmath.rs [new file with mode: 0644]
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys/windows/rand.rs
src/libstd/sys/windows/stdio.rs
src/libstd/sys/windows/thread.rs
src/libstd/sys_common/backtrace.rs
src/libstd/sys_common/gnu/libbacktrace.rs
src/libstd/sys_common/thread.rs
src/libstd/thread/mod.rs
src/libsyntax/feature_gate.rs
src/libsyntax/json.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/util/parser.rs
src/libsyntax_ext/format.rs
src/libsyntax_pos/symbol.rs
src/libtest/lib.rs
src/llvm
src/test/codegen-units/item-collection/unreferenced-const-fn.rs [new file with mode: 0644]
src/test/codegen-units/item-collection/unreferenced-inline-function.rs [new file with mode: 0644]
src/test/codegen-units/partitioning/extern-drop-glue.rs
src/test/codegen-units/partitioning/inlining-from-extern-crate.rs
src/test/codegen-units/partitioning/local-drop-glue.rs
src/test/codegen-units/partitioning/local-inlining-but-not-all.rs
src/test/codegen-units/partitioning/local-inlining.rs
src/test/codegen-units/partitioning/local-transitive-inlining.rs
src/test/codegen-units/partitioning/statics.rs
src/test/codegen/adjustments.rs
src/test/codegen/fastcall-inreg.rs
src/test/codegen/function-arguments.rs
src/test/codegen/mir_zst_stores.rs
src/test/codegen/naked-functions.rs
src/test/codegen/refs.rs
src/test/codegen/unchecked-float-casts.rs [new file with mode: 0644]
src/test/compile-fail/E0225.rs
src/test/compile-fail/E0259.rs
src/test/compile-fail/E0308-2.rs [deleted file]
src/test/compile-fail/E0534.rs
src/test/compile-fail/arbitrary-self-types-not-object-safe.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs
src/test/compile-fail/associated-types/cache/project-fn-ret-contravariant.rs
src/test/compile-fail/associated-types/cache/project-fn-ret-invariant.rs
src/test/compile-fail/auxiliary/deprecation-lint.rs
src/test/compile-fail/bad-intrinsic-monomorphization.rs
src/test/compile-fail/bad-sized.rs
src/test/compile-fail/blind-item-block-middle.rs
src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
src/test/compile-fail/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs
src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs
src/test/compile-fail/const-pattern-irrefutable.rs [deleted file]
src/test/compile-fail/deprecation-lint.rs
src/test/compile-fail/dupe-symbols-2.rs
src/test/compile-fail/feature-gate-arbitrary-self-types.rs [new file with mode: 0644]
src/test/compile-fail/float-int-invalid-const-cast.rs [new file with mode: 0644]
src/test/compile-fail/ifmt-bad-arg.rs
src/test/compile-fail/invalid-inline.rs
src/test/compile-fail/issue-13058.rs
src/test/compile-fail/issue-14285.rs
src/test/compile-fail/issue-15034.rs
src/test/compile-fail/issue-17728.rs
src/test/compile-fail/issue-17740.rs
src/test/compile-fail/issue-22560.rs
src/test/compile-fail/issue-22638.rs
src/test/compile-fail/issue-26194.rs
src/test/compile-fail/issue-3154.rs
src/test/compile-fail/issue-32963.rs
src/test/compile-fail/issue-33504.rs
src/test/compile-fail/issue-40288-2.rs
src/test/compile-fail/issue-45087-unreachable-unsafe.rs [new file with mode: 0644]
src/test/compile-fail/issue-45729-unsafe-in-generator.rs [new file with mode: 0644]
src/test/compile-fail/lint-output-format-2.rs
src/test/compile-fail/lint-stability-deprecated.rs
src/test/compile-fail/name-clash-nullary.rs [deleted file]
src/test/compile-fail/no-patterns-in-args-2.rs
src/test/compile-fail/no-patterns-in-args-macro.rs [new file with mode: 0644]
src/test/compile-fail/no-patterns-in-args.rs
src/test/compile-fail/non-interger-atomic.rs
src/test/compile-fail/object-lifetime-default-from-box-error.rs
src/test/compile-fail/pattern-binding-disambiguation.rs [new file with mode: 0644]
src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs
src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs
src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs
src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs
src/test/compile-fail/regions-creating-enums3.rs
src/test/compile-fail/regions-free-region-ordering-callee.rs
src/test/compile-fail/regions-glb-free-free.rs
src/test/compile-fail/regions-infer-at-fn-not-param.rs
src/test/compile-fail/regions-lifetime-bounds-on-fns.rs
src/test/compile-fail/regions-reborrow-from-shorter-mut-ref-mut-ref.rs
src/test/compile-fail/regions-reborrow-from-shorter-mut-ref.rs
src/test/compile-fail/self-vs-path-ambiguity.rs
src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs
src/test/compile-fail/task-rng-isnt-sendable.rs [deleted file]
src/test/compile-fail/ufcs-explicit-self-bad.rs
src/test/compile-fail/variance-trait-matching.rs
src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
src/test/incremental/change_add_field/struct_point.rs
src/test/incremental/change_private_fn/struct_point.rs
src/test/incremental/change_private_fn_cc/auxiliary/point.rs
src/test/incremental/change_private_fn_cc/struct_point.rs
src/test/incremental/change_private_impl_method/struct_point.rs
src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
src/test/incremental/change_private_impl_method_cc/struct_point.rs
src/test/incremental/change_pub_inherent_method_body/struct_point.rs
src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
src/test/incremental/hashes/call_expressions.rs
src/test/incremental/hashes/enum_constructors.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/panic_exprs.rs
src/test/incremental/hashes/struct_constructors.rs
src/test/incremental/ich_nested_items.rs
src/test/incremental/issue-38222.rs
src/test/incremental/krate-inherent.rs
src/test/incremental/krate-inlined.rs
src/test/incremental/remove_source_file/main.rs
src/test/incremental/spans_in_type_debuginfo.rs
src/test/incremental/string_constant.rs
src/test/mir-opt/basic_assignment.rs
src/test/mir-opt/box_expr.rs
src/test/mir-opt/copy_propagation.rs
src/test/mir-opt/copy_propagation_arg.rs [new file with mode: 0644]
src/test/mir-opt/deaggregator_test.rs
src/test/mir-opt/deaggregator_test_enum.rs
src/test/mir-opt/deaggregator_test_enum_2.rs
src/test/mir-opt/deaggregator_test_multiple.rs
src/test/mir-opt/end_region_1.rs
src/test/mir-opt/end_region_2.rs
src/test/mir-opt/end_region_3.rs
src/test/mir-opt/end_region_4.rs
src/test/mir-opt/end_region_5.rs
src/test/mir-opt/end_region_6.rs
src/test/mir-opt/end_region_7.rs
src/test/mir-opt/end_region_8.rs
src/test/mir-opt/end_region_9.rs
src/test/mir-opt/end_region_cyclic.rs
src/test/mir-opt/end_region_destruction_extents_1.rs
src/test/mir-opt/issue-38669.rs
src/test/mir-opt/issue-41110.rs
src/test/mir-opt/issue-43457.rs
src/test/mir-opt/match_false_edges.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 [new file with mode: 0644]
src/test/mir-opt/nll/reborrow-basic.rs
src/test/mir-opt/nll/region-liveness-basic.rs
src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
src/test/mir-opt/nll/region-subtyping-basic.rs
src/test/mir-opt/simplify_if.rs
src/test/mir-opt/storage_live_dead_in_statics.rs
src/test/mir-opt/storage_ranges.rs
src/test/mir-opt/validate_1.rs
src/test/mir-opt/validate_2.rs
src/test/mir-opt/validate_3.rs
src/test/mir-opt/validate_4.rs
src/test/mir-opt/validate_5.rs
src/test/parse-fail/issue-33413.rs
src/test/parse-fail/range_inclusive_dotdotdot.rs [new file with mode: 0644]
src/test/pretty/cast-lt.pp [new file with mode: 0644]
src/test/pretty/cast-lt.rs [new file with mode: 0644]
src/test/run-make/issue-7349/foo.rs
src/test/run-make/sepcomp-separate/foo.rs
src/test/run-make/symbols-are-reasonable/lib.rs
src/test/run-make/symbols-include-type-name/lib.rs
src/test/run-pass-fulldeps/binary-heap-panic-safe.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/env.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/issue-35829.rs
src/test/run-pass-fulldeps/vector-sort-panic-safe.rs [new file with mode: 0644]
src/test/run-pass/arbitrary_self_types_silly.rs [new file with mode: 0644]
src/test/run-pass/arbitrary_self_types_struct.rs [new file with mode: 0644]
src/test/run-pass/arbitrary_self_types_trait.rs [new file with mode: 0644]
src/test/run-pass/arbitrary_self_types_unsized_struct.rs [new file with mode: 0644]
src/test/run-pass/assert-eq-trailing-comma.rs [new file with mode: 0644]
src/test/run-pass/assert-ne-trailing-comma.rs [new file with mode: 0644]
src/test/run-pass/auto-traits.rs
src/test/run-pass/binary-heap-panic-safe.rs [deleted file]
src/test/run-pass/enum-non-c-like-repr-int.rs [new file with mode: 0644]
src/test/run-pass/env.rs [deleted file]
src/test/run-pass/issue-45731.rs [new file with mode: 0644]
src/test/run-pass/saturating-float-casts.rs [new file with mode: 0644]
src/test/run-pass/simd-intrinsic-generic-arithmetic.rs
src/test/run-pass/u128-as-f32.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs [new file with mode: 0644]
src/test/run-pass/vector-sort-panic-safe.rs [deleted file]
src/test/rustdoc/issue-45584.rs [new file with mode: 0644]
src/test/rustdoc/playground-arg.rs
src/test/rustdoc/playground.rs
src/test/rustdoc/sidebar-items.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-closures-two-mut.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-closures-two-mut.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-reinit.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-reinit.stderr [new file with mode: 0644]
src/test/ui/const-pattern-irrefutable.rs [new file with mode: 0644]
src/test/ui/const-pattern-irrefutable.stderr [new file with mode: 0644]
src/test/ui/cross-crate-macro-backtrace/main.stderr
src/test/ui/issue-33941.rs [new file with mode: 0644]
src/test/ui/issue-33941.stderr [new file with mode: 0644]
src/test/ui/issue-44406.stderr
src/test/ui/issue-45107-unnecessary-unsafe-in-closure.rs [new file with mode: 0644]
src/test/ui/issue-45107-unnecessary-unsafe-in-closure.stderr [new file with mode: 0644]
src/test/ui/issue-45730.rs [new file with mode: 0644]
src/test/ui/issue-45730.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs [deleted file]
src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr [deleted file]
src/test/ui/macros/assert_eq_trailing_comma.rs [deleted file]
src/test/ui/macros/assert_eq_trailing_comma.stderr [deleted file]
src/test/ui/macros/assert_ne_trailing_comma.rs [deleted file]
src/test/ui/macros/assert_ne_trailing_comma.stderr [deleted file]
src/test/ui/macros/macro-backtrace-println.stderr
src/test/ui/nll/named-region-basic.rs [new file with mode: 0644]
src/test/ui/nll/named-region-basic.stderr [new file with mode: 0644]
src/test/ui/resolve/name-clash-nullary.rs [new file with mode: 0644]
src/test/ui/resolve/name-clash-nullary.stderr [new file with mode: 0644]
src/test/ui/resolve/token-error-correct.stderr
src/test/ui/span/E0535.rs
src/test/ui/span/issue-27522.stderr
src/test/ui/span/lint-unused-unsafe.stderr
src/test/ui/static-lifetime.stderr
src/test/ui/suggestions/auxiliary/m1.rs [new file with mode: 0644]
src/test/ui/suggestions/auxiliary/m2.rs [new file with mode: 0644]
src/test/ui/suggestions/extern-crate-rename.rs [new file with mode: 0644]
src/test/ui/suggestions/extern-crate-rename.stderr [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-initializer.rs [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr [new file with mode: 0644]
src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs [new file with mode: 0644]
src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/compiletest/Cargo.toml
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/read2.rs [new file with mode: 0644]
src/tools/compiletest/src/runtest.rs
src/tools/rls
src/tools/rustfmt
src/tools/tidy/src/bins.rs
src/tools/toolstate.toml

index af418c15cdde790d59375002613ca72b3d953fe9..62336a7ff2ad58d8093111e6be8d3f6b5f388119 100644 (file)
@@ -253,7 +253,14 @@ after_failure:
 
   # Random attempt at debugging currently. Just poking around in here to see if
   # anything shows up.
-  - ls $HOME/Library/Logs/DiagnosticReports/
+  - ls -lat $HOME/Library/Logs/DiagnosticReports/
+  - find $HOME/Library/Logs/DiagnosticReports/ ! \(
+      -name '*.stage2-*.crash'
+      -name 'com.apple.CoreSimulator.CoreSimulatorService-*.crash'
+    \)
+      -exec echo -e travis_fold":start:crashlog\n\033[31;1m" {} "\033[0m" \;
+      -exec head -750 {} \;
+      -exec echo travis_fold":"end:crashlog \;
 
   # attempt to debug anything killed by the oom killer on linux, just to see if
   # it happened
@@ -286,6 +293,7 @@ before_deploy:
           rm -rf obj/build/dist/doc &&
           cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
       fi
+  - travis_retry gem update --system
 
 deploy:
   - provider: s3
index 405274c805195dfd0364518a10c6788ae7063fe2..7f532a8fef7d9fa4ef13cbb988d7b87d8bda3457 100644 (file)
@@ -28,6 +28,7 @@ name = "alloc"
 version = "0.0.0"
 dependencies = [
  "core 0.0.0",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "std_unicode 0.0.0",
 ]
 
@@ -38,7 +39,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.0.0",
 ]
@@ -72,7 +73,7 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -86,7 +87,7 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "dbghelp-sys 0.2.0 (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.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -96,8 +97,8 @@ name = "backtrace-sys"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -124,16 +125,16 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -150,8 +151,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -189,7 +190,7 @@ dependencies = [
  "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -198,16 +199,16 @@ dependencies = [
  "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (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.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -216,9 +217,9 @@ name = "cargo_metadata"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -232,9 +233,9 @@ dependencies = [
  "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -243,7 +244,7 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.1"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -253,15 +254,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "clap"
-version = "2.26.2"
+version = "2.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -278,8 +278,8 @@ dependencies = [
  "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -298,11 +298,11 @@ dependencies = [
  "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (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.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -310,7 +310,7 @@ name = "cmake"
 version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -326,14 +326,14 @@ name = "commoncrypto-sys"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -345,9 +345,11 @@ dependencies = [
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -367,7 +369,7 @@ version = "0.1.0"
 name = "core"
 version = "0.0.0"
 dependencies = [
- "rand 0.0.0",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -376,7 +378,7 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -384,7 +386,7 @@ name = "core-foundation-sys"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -393,10 +395,10 @@ version = "0.13.0"
 dependencies = [
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -451,7 +453,7 @@ version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -463,8 +465,8 @@ name = "curl-sys"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (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.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -510,8 +512,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -595,7 +597,7 @@ version = "0.1.14"
 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.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -612,7 +614,7 @@ name = "flate2"
 version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -622,7 +624,7 @@ version = "0.0.0"
 
 [[package]]
 name = "fnv"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -636,7 +638,7 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -667,7 +669,7 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.1.16"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -681,11 +683,11 @@ version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -696,7 +698,7 @@ dependencies = [
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -706,13 +708,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "globset"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -739,8 +741,8 @@ dependencies = [
  "pest 0.3.3 (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.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -801,7 +803,7 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -826,7 +828,7 @@ version = "0.1.0"
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -855,8 +857,8 @@ name = "jobserver"
 version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -864,11 +866,11 @@ name = "jsonrpc-core"
 version = "7.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -897,10 +899,10 @@ version = "0.12.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.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -923,7 +925,7 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.32"
+version = "0.2.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -931,10 +933,10 @@ name = "libgit2-sys"
 version = "0.6.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (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.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -947,7 +949,7 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (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.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -958,8 +960,8 @@ name = "libz-sys"
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (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)",
 ]
@@ -978,9 +980,9 @@ name = "lzma-sys"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1012,7 +1014,7 @@ name = "mdbook"
 version = "0.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (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.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1021,9 +1023,9 @@ dependencies = [
  "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1033,7 +1035,7 @@ name = "memchr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1041,7 +1043,15 @@ name = "memchr"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1049,8 +1059,8 @@ name = "miniz-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1075,7 +1085,7 @@ 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)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1087,7 +1097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1100,7 +1110,7 @@ dependencies = [
  "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1111,7 +1121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1143,7 +1153,7 @@ dependencies = [
 
 [[package]]
 name = "num-rational"
-version = "0.1.39"
+version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1162,7 +1172,7 @@ name = "num_cpus"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1178,7 +1188,7 @@ dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1192,8 +1202,8 @@ name = "openssl-sys"
 version = "0.9.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (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)",
 ]
@@ -1267,7 +1277,7 @@ version = "0.7.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1306,7 +1316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1354,32 +1364,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "racer"
-version = "2.0.10"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand"
-version = "0.0.0"
-dependencies = [
- "core 0.0.0",
 ]
 
 [[package]]
 name = "rand"
-version = "0.3.17"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1447,7 +1450,7 @@ version = "0.1.0"
 
 [[package]]
 name = "rls"
-version = "0.122.0"
+version = "0.123.0"
 dependencies = [
  "cargo 0.24.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1455,22 +1458,22 @@ dependencies = [
  "languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.2.13",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.2.15",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-analysis"
-version = "0.7.1"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1487,8 +1490,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.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1502,8 +1505,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.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1511,7 +1514,7 @@ name = "rls-vfs"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1519,7 +1522,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1596,6 +1599,7 @@ name = "rustc_back"
 version = "0.0.0"
 dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "syntax 0.0.0",
 ]
@@ -1703,6 +1707,7 @@ version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
@@ -1727,7 +1732,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
 ]
 
@@ -1860,7 +1865,7 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1869,6 +1874,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
+ "rustc_apfloat 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -1930,7 +1936,7 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1946,18 +1952,19 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.2.13"
+version = "0.2.15"
 dependencies = [
+ "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (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.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1991,7 +1998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (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)",
@@ -2013,7 +2020,7 @@ version = "0.8.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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2023,22 +2030,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.15"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.15"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_derive_internals"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2050,18 +2057,18 @@ name = "serde_ignored"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.4"
+version = "1.0.6"
 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.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2074,7 +2081,7 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2100,7 +2107,7 @@ 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)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2124,7 +2131,7 @@ dependencies = [
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
- "rand 0.0.0",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -2149,7 +2156,7 @@ dependencies = [
  "lazy_static 0.2.9 (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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (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)",
 ]
@@ -2239,7 +2246,7 @@ name = "syntex_errors"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2261,7 +2268,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2276,7 +2283,7 @@ version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2285,7 +2292,7 @@ name = "tempdir"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2311,16 +2318,6 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "term_size"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "termcolor"
 version = "0.3.3"
@@ -2334,7 +2331,7 @@ name = "termion"
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2349,10 +2346,9 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2362,7 +2358,7 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2399,14 +2395,9 @@ name = "toml"
 version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "typed-arena"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "unicode-bidi"
 version = "0.3.4"
@@ -2473,7 +2464,7 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "1.5.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2486,8 +2477,8 @@ name = "url_serde"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2579,7 +2570,7 @@ name = "xattr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2609,9 +2600,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
-"checksum cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c674f0870e3dbd4105184ea035acb1c32c8ae69939c9e228d2b11bbfe29efad"
+"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2"
+"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180"
 "checksum cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "357c07e7a1fc95732793c1edb5901e1a1f305cfcf63a90eb12dbd22bdb6b789d"
 "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"
@@ -2640,18 +2631,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46"
 "checksum filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "aa75ec8f7927063335a9583e7fa87b0110bb888cf766dc01b54c0ff70d760c8e"
 "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
-"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
+"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
 "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
 "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
 "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
-"checksum futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "05a23db7bd162d4e8265968602930c476f688f0c180b44bdaf55e0cb2c687558"
+"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1"
 "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9"
 "checksum git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1c0203d653f4140241da0c1375a404f0a397249ec818cd2076c6280c50f6fa"
 "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
-"checksum globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "feeb1b6840809ef5efcf7a4a990bc4e1b7ee3df8cf9e2379a75aeb2ba42ac9c3"
+"checksum globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "464627f948c3190ae3d04b1bc6d7dca2f785bda0ac01278e6db129ad383dbeb6"
 "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4"
 "checksum handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc"
 "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
@@ -2670,7 +2661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf"
 "checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
 "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
-"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148"
+"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
 "checksum libgit2-sys 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "6f74b4959cef96898f5123148724fc7dee043b9a6b99f219d948851bfbe53cb2"
 "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
 "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
@@ -2682,6 +2673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ac668292d1e5c7b1c6fd64f70d3a85105b8069a89558a0d67bdb2ff298ca1"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
+"checksum memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e01e64d9017d18e7fc09d8e4fe0e28ff6931019e979fb8019319db7ca827f8a6"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
@@ -2691,7 +2683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6"
 "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
 "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
-"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
+"checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe"
 "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
 "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
 "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
@@ -2715,15 +2707,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0"
-"checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"
+"checksum racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "034f1c4528581c40a60e96875467c03315868084e08ff4ceb46a00f7be3b16b4"
+"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
 "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3e4c03af262074324e732ba2313ce74968b4262b060367ed4d52940b6586fa1"
+"checksum rls-analysis 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b961e7270b2084839ede4d2788167086b24bc9cf09c9e955cc851afaf116054"
 "checksum rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48257ceade23c2e01a3ca8d2fc4226101b107f6a3c868f829cf3fd2f204a1fe6"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
@@ -2737,11 +2729,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
 "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799"
-"checksum serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1afcaae083fd1c46952a315062326bc9957f182358eb7da03b57ef1c688f7aa9"
-"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58"
+"checksum serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9cab69e16835717c9b8bd13c29f92b6aa34fe32ce2866b1ab481cf2da8442a"
+"checksum serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3bdafe3e71710131a919735916caa5b18c2754ad0d33d8ae5d586ccc804a403e"
+"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
 "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-"checksum serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee28c1d94a7745259b767ca9e5b95d55bafbd3205ca3acb978cad84a6ed6bc62"
+"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e"
 "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
@@ -2762,16 +2754,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum tendril 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1b72f8e2f5b73b65c315b1a70c730f24b9d7a25f39e98de8acbe2bb795caea"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
-"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9065bced9c3e43453aa3d56f1e98590b8455b341d2fa191a1090c0dd0b242c75"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
-"checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd"
+"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
 "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
 "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 typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
 "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
@@ -2780,7 +2770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
-"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
+"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3"
 "checksum utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f923c601c7ac48ef1d66f7d5b5b2d9a7ba9c51333ab75a3ddf8d0309185a56"
index bb3d9dc3f33b1e1d96ea858ff25c2c9f3523d727..cf9659350c18e413b57c286fd34123efd885156b 100644 (file)
@@ -624,9 +624,9 @@ pub fn cargo(&self,
             }
 
             if mode != Mode::Libstd && // FIXME(#45320)
+               mode != Mode::Libtest && // FIXME(#45511)
                self.config.rust_codegen_units.is_none() &&
-               self.build.is_rust_llvm(compiler.host) &&
-               !target.contains("mips") // FIXME(#45654)
+               self.build.is_rust_llvm(compiler.host)
             {
                 cargo.env("RUSTC_THINLTO", "1");
             }
index 4540f620872287f5d692a8ecc3eb6c5bdf8046fe..db013691bb1b8ca1aec7db48feb30e5a4a9951d4 100644 (file)
@@ -107,8 +107,8 @@ fn run(self, builder: &Builder) {
         let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build");
         std_cargo(build, &compiler, target, &mut cargo);
         run_cargo(build,
-                &mut cargo,
-                &libstd_stamp(build, compiler, target));
+                  &mut cargo,
+                  &libstd_stamp(build, compiler, target));
 
         builder.ensure(StdLink {
             compiler: builder.compiler(compiler.stage, build.build),
@@ -359,8 +359,8 @@ fn run(self, builder: &Builder) {
         let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build");
         test_cargo(build, &compiler, target, &mut cargo);
         run_cargo(build,
-                &mut cargo,
-                &libtest_stamp(build, compiler, target));
+                  &mut cargo,
+                  &libtest_stamp(build, compiler, target));
 
         builder.ensure(TestLink {
             compiler: builder.compiler(compiler.stage, build.build),
@@ -866,12 +866,13 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
             // `std-<hash>.dll.lib` on Windows. The aforementioned methods only
             // split the file name by the last extension (`.lib`) while we need
             // to split by all extensions (`.dll.lib`).
+            let expected_len = t!(filename.metadata()).len();
             let filename = filename.file_name().unwrap().to_str().unwrap();
             let mut parts = filename.splitn(2, '.');
             let file_stem = parts.next().unwrap().to_owned();
             let extension = parts.next().unwrap().to_owned();
 
-            toplevel.push((file_stem, extension));
+            toplevel.push((file_stem, extension, expected_len));
         }
     }
 
@@ -891,11 +892,12 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
         .map(|e| t!(e))
         .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
         .collect::<Vec<_>>();
-    for (prefix, extension) in toplevel {
-        let candidates = contents.iter().filter(|&&(_, ref filename, _)| {
+    for (prefix, extension, expected_len) in toplevel {
+        let candidates = contents.iter().filter(|&&(_, ref filename, ref meta)| {
             filename.starts_with(&prefix[..]) &&
                 filename[prefix.len()..].starts_with("-") &&
-                filename.ends_with(&extension[..])
+                filename.ends_with(&extension[..]) &&
+                meta.len() == expected_len
         });
         let max = candidates.max_by_key(|&&(_, _, ref metadata)| {
             FileTime::from_last_modification_time(metadata)
index e79f6e086ae04a64662595b48e5e2f205749bcab..090fb6c778c8631e3fc69ed6d7326611214620ad 100644 (file)
@@ -743,7 +743,6 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src/liblibc",
             "src/libpanic_abort",
             "src/libpanic_unwind",
-            "src/librand",
             "src/librustc_asan",
             "src/librustc_lsan",
             "src/librustc_msan",
index 608924c9c28d196b623d421a87e185030cbc59d5..c150459bee5c4fb5178c58d9482d17f7448dfa59 100644 (file)
@@ -27,10 +27,8 @@ pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
     install_sh(builder, "docs", "rust-docs", stage, Some(host));
 }
 
-pub fn install_std(builder: &Builder, stage: u32) {
-    for target in &builder.build.targets {
-        install_sh(builder, "std", "rust-std", stage, Some(*target));
-    }
+pub fn install_std(builder: &Builder, stage: u32, target: Interned<String>) {
+    install_sh(builder, "std", "rust-std", stage, Some(target));
 }
 
 pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
@@ -175,19 +173,24 @@ fn run($sel, $builder: &Builder) {
         install_docs(builder, self.stage, self.target);
     };
     Std, "src/libstd", true, only_hosts: true, {
-        builder.ensure(dist::Std {
-            compiler: builder.compiler(self.stage, self.host),
-            target: self.target
-        });
-        install_std(builder, self.stage);
+        for target in &builder.build.targets {
+            builder.ensure(dist::Std {
+                compiler: builder.compiler(self.stage, self.host),
+                target: *target
+            });
+            install_std(builder, self.stage, *target);
+        }
     };
     Cargo, "cargo", _config.extended, only_hosts: true, {
         builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
         install_cargo(builder, self.stage, self.target);
     };
     Rls, "rls", _config.extended, only_hosts: true, {
-        builder.ensure(dist::Rls { stage: self.stage, target: self.target });
-        install_rls(builder, self.stage, self.target);
+        if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() {
+            install_rls(builder, self.stage, self.target);
+        } else {
+            println!("skipping Install RLS stage{} ({})", self.stage, self.target);
+        }
     };
     Analysis, "analysis", _config.extended, only_hosts: false, {
         builder.ensure(dist::Analysis {
index adce6a00d46234d2a534d1b170e4663b8fd231fe..922deba7367e97442f491b180757caa4069dace3 100644 (file)
@@ -22,6 +22,48 @@ Images will output artifacts in an `obj` dir at the root of a repository.
 - `scripts` contains files shared by docker images
 - `disabled` contains images that are not built on travis
 
+## Docker Toolbox on Windows
+
+For Windows before Windows 10, the docker images can be run on Windows via
+[Docker Toolbox]. There are several preparation needs to be made before running
+a Docker image.
+
+1. Stop the virtual machine from the terminal with `docker-machine stop`
+
+2. If your Rust source is placed outside of `C:\Users\**`, e.g. if you place the
+    repository in the `E:\rust` folder, please add a shared folder from
+    VirtualBox by:
+
+    1. Select the "default" virtual machine inside VirtualBox, then click
+        "Settings"
+    2. Go to "Shared Folders", click "Add shared foldrer" (the folder icon with
+        a plus sign), fill in the following information, then click "OK":
+
+        * Folder path: `E:\rust`
+        * Folder name: `e/rust`
+        * Read-only: ☐ *unchecked*
+        * Auto-mount: ☑ *checked*
+        * Make Permanant: ☑ *checked*
+
+3. VirtualBox might not support creating symbolic links inside a shared folder
+    by default. You can enable it manually by running these from `cmd.exe`:
+
+    ```bat
+    cd "C:\Program Files\Oracle\VirtualBox"
+    VBoxManage setextradata default VBoxInternal2/SharedFoldersEnableSymlinksCreate/e/rust 1
+    ::                                                                              ^~~~~~
+    ::                                                                              folder name
+    ```
+
+4. Restart the virtual machine from terminal with `docker-machine start`.
+
+To run the image,
+
+1. Launch the "Docker Quickstart Terminal".
+2. Execute `./src/ci/docker/run.sh $image_name` as explained at the beginning.
+
+[Docker Toolbox]: https://www.docker.com/products/docker-toolbox
+
 ## Cross toolchains
 
 A number of these images take quite a long time to compile as they're building
@@ -137,7 +179,7 @@ For targets: `armv7-unknown-linux-gnueabihf`
     libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk
     file in Rust's source code.
 
-## `aarch64-linux-gnu.config`
+### `aarch64-linux-gnu.config`
 
 For targets: `aarch64-unknown-linux-gnu`
 
@@ -150,7 +192,7 @@ For targets: `aarch64-unknown-linux-gnu`
 - C compiler > gcc version = 5.2.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
-## `powerpc-linux-gnu.config`
+### `powerpc-linux-gnu.config`
 
 For targets: `powerpc-unknown-linux-gnu`
 
@@ -165,7 +207,7 @@ For targets: `powerpc-unknown-linux-gnu`
 - C compiler > gcc version = 4.9.3
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
-## `powerpc64-linux-gnu.config`
+### `powerpc64-linux-gnu.config`
 
 For targets: `powerpc64-unknown-linux-gnu`
 
@@ -184,7 +226,7 @@ For targets: `powerpc64-unknown-linux-gnu`
 
 (+) These CPU options match the configuration of the toolchains in RHEL6.
 
-## `s390x-linux-gnu.config`
+### `s390x-linux-gnu.config`
 
 For targets: `s390x-unknown-linux-gnu`
 
diff --git a/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile b/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile
new file mode 100644 (file)
index 0000000..f3509ef
--- /dev/null
@@ -0,0 +1,36 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  bzip2 \
+  xz-utils \
+  wget \
+  libssl-dev \
+  bsdtar \
+  pkg-config
+
+
+COPY dist-x86_64-dragonfly/build-toolchain.sh /tmp/
+COPY dist-x86_64-dragonfly/patch-toolchain /tmp/
+RUN /tmp/build-toolchain.sh /tmp/patch-toolchain
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV \
+    AR_x86_64_unknown_dragonfly=x86_64-unknown-dragonfly-ar \
+    CC_x86_64_unknown_dragonfly=x86_64-unknown-dragonfly-gcc \
+    CXX_x86_64_unknown_dragonfly=x86_64-unknown-dragonfly-g++
+
+ENV HOSTS=x86_64-unknown-dragonfly
+
+ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/disabled/dist-x86_64-dragonfly/build-toolchain.sh b/src/ci/docker/disabled/dist-x86_64-dragonfly/build-toolchain.sh
new file mode 100755 (executable)
index 0000000..3d58f3d
--- /dev/null
@@ -0,0 +1,120 @@
+#!/bin/bash
+# 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.
+
+set -ex
+
+ARCH=x86_64
+PATCH_TOOLCHAIN=$1
+BINUTILS=2.25.1
+GCC=6.4.0
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir binutils
+cd binutils
+
+# First up, build binutils
+curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf -
+mkdir binutils-build
+cd binutils-build
+hide_output ../binutils-$BINUTILS/configure \
+  --target=$ARCH-unknown-dragonfly
+hide_output make -j10
+hide_output make install
+cd ../..
+rm -rf binutils
+
+# Next, download the DragonFly libc and relevant header files
+
+URL=http://mirror-master.dragonflybsd.org/iso-images/dfly-x86_64-5.0.0_REL.iso.bz2
+mkdir dragonfly
+curl $URL | bzcat | bsdtar xf - -C dragonfly ./usr/include ./usr/lib ./lib
+
+dst=/usr/local/$ARCH-unknown-dragonfly
+
+mkdir -p $dst/lib
+cp -r dragonfly/usr/include $dst/
+cp dragonfly/usr/lib/crt1.o $dst/lib
+cp dragonfly/usr/lib/Scrt1.o $dst/lib
+cp dragonfly/usr/lib/crti.o $dst/lib
+cp dragonfly/usr/lib/crtn.o $dst/lib
+cp dragonfly/usr/lib/libc.a $dst/lib
+cp dragonfly/usr/lib/libutil.a $dst/lib
+cp dragonfly/usr/lib/libm.a $dst/lib
+cp dragonfly/usr/lib/librt.so.0 $dst/lib
+cp dragonfly/usr/lib/libexecinfo.so.1 $dst/lib
+cp dragonfly/lib/libc.so.8 $dst/lib
+cp dragonfly/lib/libm.so.4 $dst/lib
+cp dragonfly/lib/libutil.so.4 $dst/lib
+cp dragonfly/usr/lib/libpthread.so $dst/lib/libpthread.so
+cp dragonfly/usr/lib/thread/libthread_xu.so.2 $dst/lib/libpthread.so.0
+
+ln -s libc.so.8 $dst/lib/libc.so
+ln -s libm.so.4 $dst/lib/libm.so
+ln -s librt.so.0 $dst/lib/librt.so
+ln -s libutil.so.4 $dst/lib/libutil.so
+ln -s libexecinfo.so.1 $dst/lib/libexecinfo.so
+rm -rf dragonfly
+
+# Finally, download and build gcc to target DragonFly
+mkdir gcc
+cd gcc
+curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.gz | tar xzf -
+cd gcc-$GCC
+
+# The following three patches are taken from DragonFly's dports collection:
+# https://github.com/DragonFlyBSD/DPorts/tree/master/lang/gcc5
+# The dports specification for gcc5 contains a few more patches, but they are
+# not relevant in this situation, as they are for a language we don't need
+# (e.g. java), or a platform which is not supported by DragonFly (e.g. i386,
+# powerpc64, ia64, arm).
+#
+# These patches probably only need to be updated in case the gcc version is
+# updated.
+
+patch -p0 < $PATCH_TOOLCHAIN
+
+./contrib/download_prerequisites
+
+mkdir ../gcc-build
+cd ../gcc-build
+hide_output ../gcc-$GCC/configure                \
+  --enable-languages=c,c++                       \
+  --target=$ARCH-unknown-dragonfly               \
+  --disable-multilib                             \
+  --disable-nls                                  \
+  --disable-libgomp                              \
+  --disable-libquadmath                          \
+  --disable-libssp                               \
+  --disable-libvtv                               \
+  --disable-libcilkrts                           \
+  --disable-libada                               \
+  --disable-libsanitizer                         \
+  --disable-libquadmath-support                  \
+  --disable-lto
+hide_output make -j10
+hide_output make install
+cd ../..
+rm -rf gcc
diff --git a/src/ci/docker/disabled/dist-x86_64-dragonfly/patch-toolchain b/src/ci/docker/disabled/dist-x86_64-dragonfly/patch-toolchain
new file mode 100644 (file)
index 0000000..9842430
--- /dev/null
@@ -0,0 +1,23 @@
+--- libstdc++-v3/config/os/bsd/dragonfly/os_defines.h.orig     2015-07-09 16:08:54 UTC
++++ libstdc++-v3/config/os/bsd/dragonfly/os_defines.h
+@@ -29,4 +29,9 @@
+ // System-specific #define, typedefs, corrections, etc, go here.  This
+ // file will come before all others.
++#define _GLIBCXX_USE_C99_CHECK 1
++#define _GLIBCXX_USE_C99_DYNAMIC (!(__ISO_C_VISIBLE >= 1999))
++#define _GLIBCXX_USE_C99_LONG_LONG_CHECK 1
++#define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC (_GLIBCXX_USE_C99_DYNAMIC || !defined __LONG_LONG_SUPPORTED)
++
+ #endif
+--- libstdc++-v3/configure.orig        2016-05-26 18:34:47.163132921 +0200
++++ libstdc++-v3/configure     2016-05-26 18:35:29.594590648 +0200
+@@ -52013,7 +52013,7 @@
+     ;;
+-  *-freebsd*)
++  *-freebsd* | *-dragonfly*)
+     SECTION_FLAGS='-ffunction-sections -fdata-sections'
index f231d20b1975317ed57fdce74c42fa1683b7cc05..5f556b67081a310d148e0e0752df1c374b88d534 100755 (executable)
@@ -23,9 +23,9 @@ SYSROOT=/usr/local/$TARGET/sysroot
 mkdir -p $SYSROOT
 pushd $SYSROOT
 
-centos_base=http://mirror.centos.org/altarch/7/os/ppc64le/Packages
-glibc_v=2.17-196.el7
-kernel_v=3.10.0-693.el7
+centos_base=http://vault.centos.org/altarch/7.3.1611/os/ppc64le/Packages/
+glibc_v=2.17-157.el7
+kernel_v=3.10.0-514.el7
 for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
   curl $centos_base/$package.ppc64le.rpm | \
     rpm2cpio - | cpio -idm
index b2560c6b95b4ccf68f7766c61cded75c91dece55..dc02310b4f21ff102ac39550ee0f89852a68e9e0 100755 (executable)
@@ -11,6 +11,8 @@
 
 set -e
 
+export MSYS_NO_PATHCONV=1
+
 script=`cd $(dirname $0) && pwd`/`basename $0`
 image=$1
 
@@ -25,12 +27,19 @@ travis_fold start build_docker
 travis_time_start
 
 if [ -f "$docker_dir/$image/Dockerfile" ]; then
+    dockerfile="$docker_dir/$image/Dockerfile"
+    if [ -x /usr/bin/cygpath ]; then
+        context="`cygpath -w $docker_dir`"
+        dockerfile="`cygpath -w $dockerfile`"
+    else
+        context="$docker_dir"
+    fi
     retry docker \
       build \
       --rm \
       -t rust-ci \
-      -f "$docker_dir/$image/Dockerfile" \
-      "$docker_dir"
+      -f "$dockerfile" \
+      "$context"
 elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
     if [ -n "$TRAVIS_OS_NAME" ]; then
         echo Cannot run disabled images on travis!
index 5d632ebc68f7a3fd54f692902b8f81f378e460d3..ebe7c59313fa59df5f46918639a8df3b59257f3c 100644 (file)
@@ -22,7 +22,7 @@ Some things that might be helpful to you though:
 # Reference
 
 * [The Rust official site](https://www.rust-lang.org)
-* [The Rust reference](https://doc.rust-lang.org/reference.html)
+* [The Rust reference](https://doc.rust-lang.org/reference/index.html)
 
 # Docs
 
diff --git a/src/doc/unstable-book/src/library-features/rand.md b/src/doc/unstable-book/src/library-features/rand.md
deleted file mode 100644 (file)
index d0229d9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# `rand`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
index 75ab3f1a17be43f4e3669d6eb347ce6e7c56e4cb..cfe5b01e934e7032c0a99910ab144c5c63dfd7bf 100644 (file)
@@ -177,7 +177,7 @@ def main():
     normal1 = compress_normal(normal1)
 
     print("""\
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -226,7 +226,7 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
     current
 }
 
-pub fn is_printable(x: char) -> bool {
+pub(crate) fn is_printable(x: char) -> bool {
     let x = x as u32;
     let lower = x as u16;
     if x < 0x10000 {
index 686e5681d12b4c68625467efb04c3f3a0c424045..0a265ee1376a0acf48d83c3463d61eaca97bd891 100644 (file)
@@ -11,6 +11,9 @@ path = "lib.rs"
 core = { path = "../libcore" }
 std_unicode = { path = "../libstd_unicode" }
 
+[dev-dependencies]
+rand = "0.3"
+
 [[test]]
 name = "collectionstests"
 path = "../liballoc/tests/lib.rs"
index a40ed060604a7b1e4f8e19f30366d2a6fd15413a..3cc3ea467966be5a11dc56d4c6b429c00a450e0d 100644 (file)
 extern crate std;
 #[cfg(test)]
 extern crate test;
+#[cfg(test)]
+extern crate rand;
 
 extern crate std_unicode;
 
index f897feb7afaf65e823714e82791f08f688b75640..fac6acaca6125aa80b3882ac450a826b90646980 100644 (file)
@@ -1269,10 +1269,11 @@ unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
 
 #[cfg(test)]
 mod tests {
-    use std::__rand::{thread_rng, Rng};
     use std::thread;
     use std::vec::Vec;
 
+    use rand::{thread_rng, Rng};
+
     use super::{LinkedList, Node};
 
     #[cfg(test)]
index 5f0b4088fc07eaa53f5f3962985d53d327610da8..a167b2e57c07840e33e2d872acb906f9898ab3e0 100644 (file)
@@ -363,16 +363,16 @@ pub fn as_ptr(&self) -> *const u8 {
     /// # Examples
     ///
     /// ```
-    /// let mut v = String::from("🗻∈🌏");
+    /// let v = String::from("🗻∈🌏");
     ///
     /// assert_eq!(Some("🗻"), v.get(0..4));
     ///
     /// // indices not on UTF-8 sequence boundaries
-    /// assert!(v.get_mut(1..).is_none());
-    /// assert!(v.get_mut(..8).is_none());
+    /// assert!(v.get(1..).is_none());
+    /// assert!(v.get(..8).is_none());
     ///
     /// // out of bounds
-    /// assert!(v.get_mut(..42).is_none());
+    /// assert!(v.get(..42).is_none());
     /// ```
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
index c5beb63d12e9d0f07052b3fd1d38f54d30198f61..00ebd88d464ec418da2f9a3be77b95ed719215ef 100644 (file)
@@ -30,6 +30,7 @@
 #![feature(unicode)]
 
 extern crate std_unicode;
+extern crate rand;
 
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
index c53bf15f1bfb6263fe861c643defab423ffa3dd7..85d5ce304b88de2c27556a8414d61e93bb681173 100644 (file)
 
 use std::cmp::Ordering::{Equal, Greater, Less};
 use std::mem;
-use std::__rand::{Rng, thread_rng};
 use std::rc::Rc;
 
+use rand::{Rng, thread_rng};
+
 fn square(n: usize) -> usize {
     n * n
 }
index df6497fc64667be00e1be81eb2ae152625684e06..873220794bd0a128f7d3a42b3f5f0cb319122f64 100755 (executable)
 
   fi
 fi
+
+case "${host_os}" in
+darwin*)
+  have_mmap=no ;;
+esac
+
 if test "$have_mmap" = "no"; then
   VIEW_FILE=read.lo
   ALLOC_FILE=alloc.lo
index 7ae21b8d1a68c78bb67af749d939d525c01ed0b0..ea1b27d807e13d9741f4fa7821f16e6f2e0006c3 100644 (file)
@@ -283,6 +283,12 @@ else
     AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
   fi
 fi
+
+case "${host_os}" in
+darwin*)
+  have_mmap=no ;;
+esac
+
 if test "$have_mmap" = "no"; then
   VIEW_FILE=read.lo
   ALLOC_FILE=alloc.lo
index 178df02ccdde33e5e4c97a130a961f6f5c91ddc6..d1a0a5f09e0d5d83cac2c6149f2dc61d1d665053 100644 (file)
@@ -10,7 +10,7 @@ test = false
 bench = false
 
 [dev-dependencies]
-rand = { path = "../librand" }
+rand = "0.3"
 
 [[test]]
 name = "coretests"
index d2db329da799981b3a6d3a372211f21893603b6a..201064e823b1e6ecee851126f444c408fed73063 100644 (file)
@@ -20,6 +20,6 @@
 mod any;
 mod hash;
 mod iter;
-mod mem;
 mod num;
 mod ops;
+mod slice;
diff --git a/src/libcore/benches/slice.rs b/src/libcore/benches/slice.rs
new file mode 100644 (file)
index 0000000..b2fc745
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use test::black_box;
+use test::Bencher;
+
+enum Cache {
+    L1,
+    L2,
+    L3,
+}
+
+fn binary_search<F>(b: &mut Bencher, cache: Cache, mapper: F)
+    where F: Fn(usize) -> usize
+{
+    let size = match cache {
+        Cache::L1 => 1000, // 8kb
+        Cache::L2 => 10_000, // 80kb
+        Cache::L3 => 1_000_000, // 8Mb
+    };
+    let v = (0..size).map(&mapper).collect::<Vec<_>>();
+    let mut r = 0usize;
+    b.iter(move || {
+        // LCG constants from https://en.wikipedia.org/wiki/Numerical_Recipes.
+        r = r.wrapping_mul(1664525).wrapping_add(1013904223);
+        // Lookup the whole range to get 50% hits and 50% misses.
+        let i = mapper(r % size);
+        black_box(v.binary_search(&i).is_ok());
+    })
+}
+
+#[bench]
+fn binary_search_l1(b: &mut Bencher) {
+    binary_search(b, Cache::L1, |i| i * 2);
+}
+
+#[bench]
+fn binary_search_l2(b: &mut Bencher) {
+    binary_search(b, Cache::L2, |i| i * 2);
+}
+
+#[bench]
+fn binary_search_l3(b: &mut Bencher) {
+    binary_search(b, Cache::L3, |i| i * 2);
+}
+
+#[bench]
+fn binary_search_l1_with_dups(b: &mut Bencher) {
+    binary_search(b, Cache::L1, |i| i / 16 * 16);
+}
+
+#[bench]
+fn binary_search_l2_with_dups(b: &mut Bencher) {
+    binary_search(b, Cache::L2, |i| i / 16 * 16);
+}
+
+#[bench]
+fn binary_search_l3_with_dups(b: &mut Bencher) {
+    binary_search(b, Cache::L3, |i| i / 16 * 16);
+}
index 2c0f449b27601405bdcb1014552944c36b2461e7..e6803745ab543292a51484f8355648ee646d7b76 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -47,7 +47,7 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
     current
 }
 
-pub fn is_printable(x: char) -> bool {
+pub(crate) fn is_printable(x: char) -> bool {
     let x = x as u32;
     let lower = x as u16;
     if x < 0x10000 {
@@ -64,7 +64,10 @@ pub fn is_printable(x: char) -> bool {
         if 0x2b81e <= x && x < 0x2b820 {
             return false;
         }
-        if 0x2cea2 <= x && x < 0x2f800 {
+        if 0x2cea2 <= x && x < 0x2ceb0 {
+            return false;
+        }
+        if 0x2ebe1 <= x && x < 0x2f800 {
             return false;
         }
         if 0x2fa1e <= x && x < 0xe0100 {
@@ -83,12 +86,12 @@ pub fn is_printable(x: char) -> bool {
     (0x05, 8),
     (0x06, 3),
     (0x07, 4),
-    (0x08, 7),
+    (0x08, 8),
     (0x09, 16),
     (0x0a, 27),
-    (0x0b, 24),
+    (0x0b, 25),
     (0x0c, 22),
-    (0x0d, 20),
+    (0x0d, 18),
     (0x0e, 22),
     (0x0f, 4),
     (0x10, 3),
@@ -99,16 +102,15 @@ pub fn is_printable(x: char) -> bool {
     (0x18, 2),
     (0x19, 3),
     (0x1a, 7),
-    (0x1c, 1),
+    (0x1d, 1),
     (0x1f, 22),
     (0x20, 3),
-    (0x23, 1),
     (0x2b, 5),
     (0x2c, 2),
     (0x2d, 11),
     (0x2e, 1),
     (0x30, 3),
-    (0x31, 1),
+    (0x31, 3),
     (0x32, 2),
     (0xa7, 1),
     (0xa8, 2),
@@ -125,19 +127,19 @@ pub fn is_printable(x: char) -> bool {
     0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57,
     0x58, 0x60, 0x88, 0x8b, 0x8c, 0x90, 0x1c, 0x1d,
     0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0x2e, 0x2f, 0x3f,
-    0x5c, 0x5d, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91,
-    0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9,
-    0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, 0x29,
-    0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a,
-    0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba,
-    0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, 0x04,
-    0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
-    0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65,
-    0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x04,
-    0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65,
-    0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5,
-    0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, 0x0d, 0x11,
-    0x3b, 0x3c, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
+    0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e,
+    0x91, 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6,
+    0xc9, 0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12,
+    0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49,
+    0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4,
+    0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5,
+    0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31,
+    0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e,
+    0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce,
+    0xcf, 0x04, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57,
+    0x64, 0x65, 0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba,
+    0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04,
+    0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
     0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0,
     0xf1, 0x83, 0x85, 0x86, 0x89, 0x8b, 0x8c, 0x98,
     0xa0, 0xa4, 0xa6, 0xa8, 0xa9, 0xac, 0xba, 0xbe,
@@ -148,18 +150,18 @@ pub fn is_printable(x: char) -> bool {
     0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe,
     0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e,
     0x0f, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d,
-    0x7e, 0xae, 0xaf, 0xf7, 0x16, 0x17, 0x1e, 0x1f,
+    0x7e, 0xae, 0xaf, 0xfa, 0x16, 0x17, 0x1e, 0x1f,
     0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e,
     0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0,
-    0xf1, 0xf5, 0x72, 0x73, 0x8f, 0xff, 0x74, 0x75,
-    0x96, 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f,
-    0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf,
-    0x9a, 0x40, 0x97, 0x98, 0x8f, 0x1f, 0xff, 0xaf,
-    0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b,
-    0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef,
-    0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90,
-    0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9,
-    0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
+    0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96,
+    0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7,
+    0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a,
+    0x40, 0x97, 0x98, 0x2f, 0x30, 0x8f, 0x1f, 0xff,
+    0xaf, 0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a,
+    0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee,
+    0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45,
+    0x90, 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8,
+    0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
 ];
 const SINGLETONS1U: &'static [(u8, u8)] = &[
     (0x00, 6),
@@ -176,7 +178,9 @@ pub fn is_printable(x: char) -> bool {
     (0x13, 18),
     (0x14, 2),
     (0x15, 2),
+    (0x1a, 3),
     (0x1c, 5),
+    (0x1d, 4),
     (0x24, 1),
     (0x6a, 3),
     (0x6b, 2),
@@ -192,7 +196,7 @@ pub fn is_printable(x: char) -> bool {
     (0xee, 32),
     (0xf0, 4),
     (0xf1, 1),
-    (0xf9, 4),
+    (0xf9, 1),
 ];
 const SINGLETONS1L: &'static [u8] = &[
     0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e,
@@ -202,18 +206,18 @@ pub fn is_printable(x: char) -> bool {
     0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12,
     0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49,
     0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, 0xb6,
-    0xb7, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x6f, 0x5f,
-    0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28,
-    0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8,
-    0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15,
-    0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc,
-    0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5,
-    0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33,
-    0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55,
-    0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65,
-    0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4,
-    0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x1f, 0x31,
-    0x32, 0x3f,
+    0xb7, 0x84, 0x85, 0x9d, 0x09, 0x37, 0x90, 0x91,
+    0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x6f, 0x5f, 0xee,
+    0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, 0x55,
+    0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad,
+    0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d,
+    0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd,
+    0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5, 0xc6,
+    0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38,
+    0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, 0x56,
+    0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
+    0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa,
+    0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x3f,
 ];
 const NORMAL0: &'static [u8] = &[
     0x00, 0x20,
@@ -224,12 +228,12 @@ pub fn is_printable(x: char) -> bool {
     0x05, 0x11,
     0x81, 0xac, 0x0e,
     0x3b, 0x05,
-    0x5f, 0x41,
+    0x6b, 0x35,
     0x1e, 0x16,
     0x80, 0xdf, 0x03,
     0x19, 0x08,
     0x01, 0x04,
-    0x20, 0x05,
+    0x22, 0x03,
     0x0a, 0x04,
     0x34, 0x04,
     0x07, 0x03,
@@ -238,8 +242,7 @@ pub fn is_printable(x: char) -> bool {
     0x10, 0x0b,
     0x50, 0x0f,
     0x12, 0x07,
-    0x01, 0x07,
-    0x4d, 0x08,
+    0x55, 0x08,
     0x02, 0x04,
     0x1c, 0x0a,
     0x09, 0x03,
@@ -258,8 +261,8 @@ pub fn is_printable(x: char) -> bool {
     0x10, 0x08,
     0x56, 0x07,
     0x02, 0x07,
-    0x15, 0x0e,
-    0x4f, 0x04,
+    0x15, 0x0d,
+    0x50, 0x04,
     0x43, 0x03,
     0x2d, 0x03,
     0x01, 0x04,
@@ -304,34 +307,32 @@ pub fn is_printable(x: char) -> bool {
     0x3c, 0x37,
     0x08, 0x08,
     0x2a, 0x06,
-    0x80, 0xf6, 0x05,
-    0x82, 0x04, 0x11,
+    0x82, 0xff, 0x11,
     0x18, 0x08,
     0x2f, 0x11,
     0x2d, 0x03,
-    0x1f, 0x11,
+    0x20, 0x10,
     0x21, 0x0f,
     0x80, 0x8c, 0x04,
     0x82, 0x97, 0x19,
     0x0b, 0x15,
     0x87, 0x5a, 0x03,
-    0x15, 0x1a,
+    0x16, 0x19,
     0x04, 0x10,
     0x80, 0xf4, 0x05,
     0x2f, 0x05,
     0x3b, 0x07,
     0x02, 0x0e,
     0x18, 0x09,
-    0x80, 0xa5, 0x3b,
+    0x80, 0xaa, 0x36,
     0x74, 0x0c,
     0x80, 0xd6, 0x1a,
     0x0c, 0x05,
     0x80, 0xff, 0x05,
-    0x29, 0x03,
-    0x80, 0x8a, 0x05,
+    0x80, 0xb6, 0x05,
     0x24, 0x0c,
     0x9b, 0xc6, 0x0a,
-    0xd2, 0x16, 0x2a,
+    0xd2, 0x2b, 0x15,
     0x84, 0x8d, 0x03,
     0x37, 0x09,
     0x81, 0x5c, 0x14,
@@ -378,8 +379,8 @@ pub fn is_printable(x: char) -> bool {
     0x1d, 0x03,
     0x31, 0x0f,
     0x1c, 0x04,
-    0x24, 0x0c,
-    0x1b, 0x05,
+    0x24, 0x09,
+    0x1e, 0x05,
     0x2b, 0x05,
     0x44, 0x04,
     0x0e, 0x2a,
@@ -447,11 +448,16 @@ pub fn is_printable(x: char) -> bool {
     0x0f, 0x04,
     0x10, 0x81, 0x60,
     0x53, 0x0c,
-    0x01, 0x81, 0xc0,
+    0x01, 0x81, 0x00,
+    0x48, 0x08,
+    0x53, 0x1d,
     0x39, 0x81, 0x07,
     0x46, 0x0a,
     0x1d, 0x03,
-    0x47, 0x83, 0x49,
+    0x47, 0x49,
+    0x37, 0x03,
+    0x0e, 0x08,
+    0x0a, 0x82, 0xa6,
     0x83, 0x9a, 0x66,
     0x75, 0x0b,
     0x80, 0xc4, 0x8a, 0xbc,
@@ -467,10 +473,11 @@ pub fn is_printable(x: char) -> bool {
     0x45, 0x0b,
     0x2f, 0x10,
     0x11, 0x40,
-    0x01, 0x1f,
+    0x02, 0x1e,
     0x97, 0xed, 0x13,
     0x82, 0xf3, 0xa5, 0x0d,
-    0x02, 0x8b, 0xfe,
+    0x81, 0x1f, 0x51,
+    0x81, 0x8c, 0x89, 0x04,
     0x6b, 0x05,
     0x0d, 0x03,
     0x09, 0x07,
@@ -503,20 +510,22 @@ pub fn is_printable(x: char) -> bool {
     0x1d, 0x0d,
     0x2c, 0x04,
     0x09, 0x07,
-    0x02, 0x80, 0xae,
-    0x83, 0xd3, 0x0d,
+    0x02, 0x0e,
+    0x06, 0x80, 0x9a,
+    0x83, 0xd5, 0x0b,
     0x0d, 0x03,
-    0x07, 0x09,
+    0x09, 0x07,
     0x74, 0x0c,
     0x55, 0x2b,
     0x0c, 0x04,
     0x38, 0x08,
     0x0a, 0x06,
     0x28, 0x08,
-    0x1e, 0x62,
-    0x18, 0x08,
-    0x1c, 0x04,
-    0x0f, 0x21,
-    0x12, 0x2e,
-    0x01, 0x86, 0x3f,
+    0x1e, 0x52,
+    0x0c, 0x04,
+    0x3d, 0x03,
+    0x1c, 0x14,
+    0x18, 0x28,
+    0x01, 0x0f,
+    0x17, 0x86, 0x19,
 ];
index 1e45af5b105c9ca2c50f448bcbee27c394ba1f5a..e2d61890c309681ab87d29e908bb93c753d3a402 100644 (file)
@@ -525,6 +525,26 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
 #[lang = "debug_trait"]
 pub trait Debug {
     /// Formats the value using the given formatter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fmt;
+    ///
+    /// struct Position {
+    ///     longitude: f32,
+    ///     latitude: f32,
+    /// }
+    ///
+    /// impl fmt::Debug for Position {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "({:?}, {:?})", self.longitude, self.latitude)
+    ///     }
+    /// }
+    ///
+    /// assert_eq!("(1.987, 2.983)".to_owned(),
+    ///            format!("{:?}", Position { longitude: 1.987, latitude: 2.983, }));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter) -> Result;
 }
index b3c11ed1b5ac4d245ee0f0c1e462dbe4b20fbd70..15545a04b64de04e7b37e8115ad8d6b491a92cd4 100644 (file)
@@ -259,7 +259,7 @@ pub trait Hasher {
     /// println!("Hash is {:x}!", hasher.finish());
     /// ```
     ///
-    /// ['write']: #tymethod.write
+    /// [`write`]: #tymethod.write
     #[stable(feature = "rust1", since = "1.0.0")]
     fn finish(&self) -> u64;
 
index 5659d5b8d66b29d6ac58bc44f99b9d88e9c8b713..4a57417e86a1c0b4c3a8229fa2b7e52ce7c2dc4c 100644 (file)
 mod char_private;
 mod iter_private;
 mod tuple;
+mod unit;
index 12667036444e63ce4d8091f04085737c5312f3c9..c410c2d900470debf2e74a6ca9ae09048fc73627 100644 (file)
@@ -120,6 +120,9 @@ macro_rules! assert_eq {
             }
         }
     });
+    ($left:expr, $right:expr,) => ({
+        assert_eq!($left, $right)
+    });
     ($left:expr, $right:expr, $($arg:tt)+) => ({
         match (&($left), &($right)) {
             (left_val, right_val) => {
@@ -168,6 +171,9 @@ macro_rules! assert_ne {
             }
         }
     });
+    ($left:expr, $right:expr,) => {
+        assert_ne!($left, $right)
+    };
     ($left:expr, $right:expr, $($arg:tt)+) => ({
         match (&($left), &($right)) {
             (left_val, right_val) => {
index e47b99ed552d3be974624a6b3a56d367dfe84834..0a8127f4ce4fe64b2a723f7c2b9a9a1300b9dd0e 100644 (file)
@@ -39,7 +39,7 @@
 /// [arc]: ../../std/sync/struct.Arc.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[lang = "send"]
+#[cfg_attr(stage0, lang = "send")]
 #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
 pub unsafe trait Send {
     // empty.
index 980ea551f0806a888ce834bcbfbf3b196fffffd6..12e6e8430562a8baeb3f1472b00a5c7121ed8094 100644 (file)
@@ -607,6 +607,41 @@ pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
         }
     }
 
+    /// Returns `None` if the option is `None`, otherwise calls `predicate`
+    /// with the wrapped value and returns:
+    ///
+    /// - `Some(t)` if `predicate` returns `true` (where `t` is the wrapped
+    ///   value), and
+    /// - `None` if `predicate` returns `false`.
+    ///
+    /// This function works similar to `Iterator::filter()`. You can imagine
+    /// the `Option<T>` being an iterator over one or zero elements. `filter()`
+    /// lets you decide which elements to keep.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(option_filter)]
+    ///
+    /// fn is_even(n: &i32) -> bool {
+    ///     n % 2 == 0
+    /// }
+    ///
+    /// assert_eq!(None.filter(is_even), None);
+    /// assert_eq!(Some(3).filter(is_even), None);
+    /// assert_eq!(Some(4).filter(is_even), Some(4));
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_filter", issue = "45860")]
+    pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
+        if let Some(x) = self {
+            if predicate(&x) {
+                return Some(x)
+            }
+        }
+        None
+    }
+
     /// Returns the option if it contains a value, otherwise returns `optb`.
     ///
     /// # Examples
index 5cd672b03ffc9d1901364eae4246ad76789547cf..126558e3025d53103362ab521a3dbf77bb4f6968 100644 (file)
@@ -517,8 +517,10 @@ pub fn is_null(self) -> bool where T: Sized {
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
-    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
-        if self.is_null() {
+    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+        // Check for null via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        if (self as *const u8).is_null() {
             None
         } else {
             Some(&*self)
@@ -1148,8 +1150,10 @@ pub fn is_null(self) -> bool where T: Sized {
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
-    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
-        if self.is_null() {
+    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+        // Check for null via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        if (self as *const u8).is_null() {
             None
         } else {
             Some(&*self)
@@ -1272,8 +1276,10 @@ pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized {
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
-    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized {
-        if self.is_null() {
+    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
+        // Check for null via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        if (self as *mut u8).is_null() {
             None
         } else {
             Some(&mut *self)
index 57e5ae28664e0ff2aa0841f9f29516cd41effcbe..74182f303c945c31909805100602a4ffb13f4887 100644 (file)
@@ -16,9 +16,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-// FIXME: after next stage0, change RangeInclusive { ... } back to ..=
-use ops::RangeInclusive;
-
 // How this module is organized.
 //
 // The library infrastructure for slices is fairly messy. There's
@@ -394,23 +391,25 @@ fn as_ptr(&self) -> *const T {
     fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
         where F: FnMut(&'a T) -> Ordering
     {
+        let s = self;
+        let mut size = s.len();
+        if size == 0 {
+            return Err(0);
+        }
         let mut base = 0usize;
-        let mut s = self;
-
-        loop {
-            let (head, tail) = s.split_at(s.len() >> 1);
-            if tail.is_empty() {
-                return Err(base)
-            }
-            match f(&tail[0]) {
-                Less => {
-                    base += head.len() + 1;
-                    s = &tail[1..];
-                }
-                Greater => s = head,
-                Equal => return Ok(base + head.len()),
-            }
+        while size > 1 {
+            let half = size / 2;
+            let mid = base + half;
+            // mid is always in [0, size).
+            // mid >= 0: by definition
+            // mid < size: mid = size / 2 + size / 4 + size / 8 ...
+            let cmp = f(unsafe { s.get_unchecked(mid) });
+            base = if cmp == Greater { base } else { mid };
+            size -= half;
         }
+        // base is always in [0, size) because base <= mid.
+        let cmp = f(unsafe { s.get_unchecked(base) });
+        if cmp == Equal { Ok(base) } else { Err(base + (cmp == Less) as usize) }
     }
 
     #[inline]
@@ -1047,32 +1046,32 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&[T]> {
-        (RangeInclusive { start: 0, end: self.end }).get(slice)
+        (0..=self.end).get(slice)
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        (RangeInclusive { start: 0, end: self.end }).get_mut(slice)
+        (0..=self.end).get_mut(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        (RangeInclusive { start: 0, end: self.end }).get_unchecked(slice)
+        (0..=self.end).get_unchecked(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        (RangeInclusive { start: 0, end: self.end }).get_unchecked_mut(slice)
+        (0..=self.end).get_unchecked_mut(slice)
     }
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        (RangeInclusive { start: 0, end: self.end }).index(slice)
+        (0..=self.end).index(slice)
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (RangeInclusive { start: 0, end: self.end }).index_mut(slice)
+        (0..=self.end).index_mut(slice)
     }
 }
 
index cd3dd9ce1399e2e2f604549b425f8be0df078a2e..b7cf6d778a2f9d4298af22a2fe04641ff8536d98 100644 (file)
@@ -927,6 +927,7 @@ pub fn compare_exchange_weak(&self,
     }
 }
 
+#[cfg(target_has_atomic = "ptr")]
 #[stable(feature = "atomic_from", since = "1.23.0")]
 impl<T> From<*mut T> for AtomicPtr<T> {
     #[inline]
index 0f4d19e7092571495405338fb31ef9f3a1f5fd9b..2720c5c8677af8a6ec67464d05e0d50b0b46cd96 100644 (file)
@@ -10,8 +10,7 @@
 
 use std::prelude::v1::*;
 use std::{str, mem, i16, f32, f64, fmt};
-use std::__rand as rand;
-use rand::{Rand, XorShiftRng};
+use rand::{self, Rand, XorShiftRng};
 use rand::distributions::{IndependentSample, Range};
 
 use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
index c2d53840f8f570e572c6fc48ba5114bb4fb577b8..e93e9be0cd50b378846ffe60fe6a99f3d13050cd 100644 (file)
@@ -85,6 +85,39 @@ fn test_as_ref() {
             let p = &u as *const isize;
             assert_eq!(p.as_ref().unwrap(), &2);
         }
+
+        // Pointers to unsized types -- slices
+        let s: &mut [u8] = &mut [1, 2, 3];
+        let cs: *const [u8] = s;
+        assert_eq!(cs.as_ref(), Some(&*s));
+
+        let ms: *mut [u8] = s;
+        assert_eq!(ms.as_ref(), Some(&*s));
+
+        let cz: *const [u8] = &[];
+        assert_eq!(cz.as_ref(), Some(&[][..]));
+
+        let mz: *mut [u8] = &mut [];
+        assert_eq!(mz.as_ref(), Some(&[][..]));
+
+        let ncs: *const [u8] = null::<[u8; 3]>();
+        assert_eq!(ncs.as_ref(), None);
+
+        let nms: *mut [u8] = null_mut::<[u8; 3]>();
+        assert_eq!(nms.as_ref(), None);
+
+        // Pointers to unsized types -- trait objects
+        let ci: *const ToString = &3;
+        assert!(ci.as_ref().is_some());
+
+        let mi: *mut ToString = &mut 3;
+        assert!(mi.as_ref().is_some());
+
+        let nci: *const ToString = null::<isize>();
+        assert!(nci.as_ref().is_none());
+
+        let nmi: *mut ToString = null_mut::<isize>();
+        assert!(nmi.as_ref().is_none());
     }
 }
 
@@ -103,6 +136,24 @@ fn test_as_mut() {
             let p = &mut u as *mut isize;
             assert!(p.as_mut().unwrap() == &mut 2);
         }
+
+        // Pointers to unsized types -- slices
+        let s: &mut [u8] = &mut [1, 2, 3];
+        let ms: *mut [u8] = s;
+        assert_eq!(ms.as_mut(), Some(s));
+
+        let mz: *mut [u8] = &mut [];
+        assert_eq!(mz.as_mut(), Some(&mut [][..]));
+
+        let nms: *mut [u8] = null_mut::<[u8; 3]>();
+        assert_eq!(nms.as_mut(), None);
+
+        // Pointers to unsized types -- trait objects
+        let mi: *mut ToString = &mut 3;
+        assert!(mi.as_mut().is_some());
+
+        let nmi: *mut ToString = null_mut::<isize>();
+        assert!(nmi.as_mut().is_none());
     }
 }
 
index 8c31d2e83d3524f797c1417cd27c0db7587028fb..7835080db1d45ad2754fb36bac9b0d3f93d2cc36 100644 (file)
 
 #[test]
 fn test_binary_search() {
+    let b: [i32; 0] = [];
+    assert_eq!(b.binary_search(&5), Err(0));
+
+    let b = [4];
+    assert_eq!(b.binary_search(&3), Err(0));
+    assert_eq!(b.binary_search(&4), Ok(0));
+    assert_eq!(b.binary_search(&5), Err(1));
+
     let b = [1, 2, 4, 6, 8, 9];
-    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
-    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
-    let b = [1, 2, 4, 6, 7, 8, 9];
-    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
-    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
-    let b = [1, 2, 4, 6, 8, 9];
-    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
-    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
+    assert_eq!(b.binary_search(&5), Err(3));
+    assert_eq!(b.binary_search(&6), Ok(3));
+    assert_eq!(b.binary_search(&7), Err(4));
+    assert_eq!(b.binary_search(&8), Ok(4));
+
+    let b = [1, 2, 4, 5, 6, 8];
+    assert_eq!(b.binary_search(&9), Err(6));
+
     let b = [1, 2, 4, 6, 7, 8, 9];
-    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
+    assert_eq!(b.binary_search(&6), Ok(3));
+    assert_eq!(b.binary_search(&5), Err(3));
+    assert_eq!(b.binary_search(&8), Ok(5));
+
     let b = [1, 2, 4, 5, 6, 8, 9];
-    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
-    assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
-    let b = [1, 2, 4, 5, 6, 8];
-    assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
+    assert_eq!(b.binary_search(&7), Err(5));
+    assert_eq!(b.binary_search(&0), Err(0));
+
+    let b = [1, 3, 3, 3, 7];
+    assert_eq!(b.binary_search(&0), Err(0));
+    assert_eq!(b.binary_search(&1), Ok(0));
+    assert_eq!(b.binary_search(&2), Err(1));
+    assert!(match b.binary_search(&3) { Ok(1...3) => true, _ => false });
+    assert!(match b.binary_search(&3) { Ok(1...3) => true, _ => false });
+    assert_eq!(b.binary_search(&4), Err(4));
+    assert_eq!(b.binary_search(&5), Err(4));
+    assert_eq!(b.binary_search(&6), Err(4));
+    assert_eq!(b.binary_search(&7), Ok(4));
+    assert_eq!(b.binary_search(&8), Err(5));
+}
+
+#[test]
+// Test implementation specific behavior when finding equivalent elements.
+// It is ok to break this test but when you do a crater run is highly advisable.
+fn test_binary_search_implementation_details() {
+    let b = [1, 1, 2, 2, 3, 3, 3];
+    assert_eq!(b.binary_search(&1), Ok(1));
+    assert_eq!(b.binary_search(&2), Ok(3));
+    assert_eq!(b.binary_search(&3), Ok(6));
+    let b = [1, 1, 1, 1, 1, 3, 3, 3, 3];
+    assert_eq!(b.binary_search(&1), Ok(4));
+    assert_eq!(b.binary_search(&3), Ok(8));
+    let b = [1, 1, 1, 1, 3, 3, 3, 3, 3];
+    assert_eq!(b.binary_search(&1), Ok(3));
+    assert_eq!(b.binary_search(&3), Ok(8));
 }
 
 #[test]
diff --git a/src/libcore/unit.rs b/src/libcore/unit.rs
new file mode 100644 (file)
index 0000000..087ddf9
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use iter::FromIterator;
+
+/// Collapses all unit items from an iterator into one.
+///
+/// This is more useful when combined with higher-level abstractions, like
+/// collecting to a `Result<(), E>` where you only care about errors:
+///
+/// ```
+/// use std::io::*;
+/// let data = vec![1, 2, 3, 4, 5];
+/// let res: Result<()> = data.iter()
+///     .map(|x| writeln!(stdout(), "{}", x))
+///     .collect();
+/// assert!(res.is_ok());
+/// ```
+#[stable(feature = "unit_from_iter", since = "1.23.0")]
+impl FromIterator<()> for () {
+    fn from_iter<I: IntoIterator<Item=()>>(iter: I) -> Self {
+        iter.into_iter().for_each(|()| {})
+    }
+}
index 24430b2e377f599529c02afdc1371349a73abf2d..44cdb5e8a3676b23e6ead56ebedbdcf7ff9cf5f5 100644 (file)
@@ -73,7 +73,9 @@ pub struct FormatSpec<'a> {
 /// Enum describing where an argument for a format can be located.
 #[derive(Copy, Clone, PartialEq)]
 pub enum Position<'a> {
-    /// The argument is located at a specific index.
+    /// The arugment is implied to be located at an index
+    ArgumentImplicitlyIs(usize),
+    /// The argument is located at a specific index given in the format
     ArgumentIs(usize),
     /// The argument has a name.
     ArgumentNamed(&'a str),
@@ -275,7 +277,7 @@ fn argument(&mut self) -> Argument<'a> {
             None => {
                 let i = self.curarg;
                 self.curarg += 1;
-                ArgumentIs(i)
+                ArgumentImplicitlyIs(i)
             }
         };
 
@@ -517,7 +519,7 @@ fn invalid06() {
     fn format_nothing() {
         same("{}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: fmtdflt(),
                })]);
     }
@@ -595,7 +597,7 @@ fn format_align_fill() {
     fn format_counts() {
         same("{:10s}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -607,7 +609,7 @@ fn format_counts() {
                })]);
         same("{:10$.10s}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -619,7 +621,7 @@ fn format_counts() {
                })]);
         same("{:.*s}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(1),
+                   position: ArgumentImplicitlyIs(1),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -631,7 +633,7 @@ fn format_counts() {
                })]);
         same("{:.10$s}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -643,7 +645,7 @@ fn format_counts() {
                })]);
         same("{:a$.b$s}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -658,7 +660,7 @@ fn format_counts() {
     fn format_flags() {
         same("{:-}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -670,7 +672,7 @@ fn format_flags() {
                })]);
         same("{:+#}",
              &[NextArgument(Argument {
-                   position: ArgumentIs(0),
+                   position: ArgumentImplicitlyIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
index cf30966fa89715c2ff695069b5ca9f00321df21f..8a400f3e6360e39573e313dc60e751e23868c634 100644 (file)
@@ -191,7 +191,7 @@ fn default() -> Span {
 /// This is needed to implement a custom quoter.
 #[unstable(feature = "proc_macro", issue = "38356")]
 pub fn quote_span(span: Span) -> TokenStream {
-    TokenStream(quote::Quote::quote(&span.0))
+    quote::Quote::quote(span)
 }
 
 macro_rules! diagnostic_method {
@@ -728,7 +728,7 @@ fn to_internal(self) -> tokenstream::TokenStream {
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
 #[doc(hidden)]
 pub mod __internal {
-    pub use quote::{Quoter, __rt};
+    pub use quote::{LiteralKind, Quoter, unquote};
 
     use std::cell::Cell;
 
index 8c1f6bfc11a5fcff35deb04e966c2b80e9ac5d78..26f88ad6bf64937d8819cb0350fa3c8096d76329 100644 (file)
 //! # Quasiquoter
 //! This file contains the implementation internals of the quasiquoter provided by `quote!`.
 
-//! This quasiquoter uses macros 2.0 hygiene to reliably use items from `__rt`,
-//! including re-exported API `libsyntax`, to build a `syntax::tokenstream::TokenStream`
-//! and wrap it into a `proc_macro::TokenStream`.
+//! This quasiquoter uses macros 2.0 hygiene to reliably access
+//! items from `proc_macro`, to build a `proc_macro::TokenStream`.
+
+use {Delimiter, Literal, Spacing, Span, Term, TokenNode, TokenStream, TokenTree};
 
-use syntax::ast::Ident;
 use syntax::ext::base::{ExtCtxt, ProcMacro};
-use syntax::parse::token::{self, Token, Lit};
-use syntax::symbol::Symbol;
-use syntax::tokenstream::{Delimited, TokenTree, TokenStream, TokenStreamBuilder};
-use syntax_pos::{DUMMY_SP, Span};
-use syntax_pos::hygiene::SyntaxContext;
+use syntax::parse::token;
+use syntax::tokenstream;
 
 pub struct Quoter;
 
-pub mod __rt {
-    pub use syntax::ast::Ident;
-    pub use syntax::parse::token;
-    pub use syntax::symbol::Symbol;
-    pub use syntax::tokenstream::{TokenStream, TokenStreamBuilder, TokenTree, Delimited};
-    pub use super::{ctxt, span};
-
-    pub fn unquote<T: Into<::TokenStream> + Clone>(tokens: &T) -> TokenStream {
-        T::into(tokens.clone()).0
-    }
-}
-
-pub fn ctxt() -> SyntaxContext {
-    ::__internal::with_sess(|(_, mark)| SyntaxContext::empty().apply_mark(mark))
-}
-
-pub fn span() -> Span {
-    ::Span::default().0
+pub fn unquote<T: Into<TokenStream> + Clone>(tokens: &T) -> TokenStream {
+    T::into(tokens.clone())
 }
 
 pub trait Quote {
-    fn quote(&self) -> TokenStream;
+    fn quote(self) -> TokenStream;
 }
 
 macro_rules! quote_tok {
-    (,) => { Token::Comma };
-    (.) => { Token::Dot };
-    (:) => { Token::Colon };
-    (::) => { Token::ModSep };
-    (!) => { Token::Not };
-    (<) => { Token::Lt };
-    (>) => { Token::Gt };
-    (_) => { Token::Underscore };
-    (0) => { Token::Literal(token::Lit::Integer(Symbol::intern("0")), None) };
-    (&) => { Token::BinOp(token::And) };
-    ($i:ident) => { Token::Ident(Ident { name: Symbol::intern(stringify!($i)), ctxt: ctxt() }) };
+    (,) => { TokenNode::Op(',', Spacing::Alone) };
+    (.) => { TokenNode::Op('.', Spacing::Alone) };
+    (:) => { TokenNode::Op(':', Spacing::Alone) };
+    (::) => {
+        [
+            TokenNode::Op(':', Spacing::Joint),
+            TokenNode::Op(':', Spacing::Alone)
+        ].iter().cloned().collect::<TokenStream>()
+    };
+    (!) => { TokenNode::Op('!', Spacing::Alone) };
+    (<) => { TokenNode::Op('<', Spacing::Alone) };
+    (>) => { TokenNode::Op('>', Spacing::Alone) };
+    (_) => { TokenNode::Op('_', Spacing::Alone) };
+    (0) => { TokenNode::Literal(::Literal::integer(0)) };
+    (&) => { TokenNode::Op('&', Spacing::Alone) };
+    ($i:ident) => { TokenNode::Term(Term::intern(stringify!($i))) };
 }
 
 macro_rules! quote_tree {
-    ((unquote $($t:tt)*)) => { TokenStream::from($($t)*) };
+    ((unquote $($t:tt)*)) => { $($t)* };
     ((quote $($t:tt)*)) => { ($($t)*).quote() };
-    (($($t:tt)*)) => { delimit(token::Paren, quote!($($t)*)) };
-    ([$($t:tt)*]) => { delimit(token::Bracket, quote!($($t)*)) };
-    ({$($t:tt)*}) => { delimit(token::Brace, quote!($($t)*)) };
-    (rt) => { quote!(::__internal::__rt) };
-    ($t:tt) => { TokenStream::from(TokenTree::Token(span(), quote_tok!($t))) };
-}
-
-fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream {
-    TokenTree::Delimited(span(), Delimited { delim: delim, tts: stream.into() }).into()
+    (($($t:tt)*)) => { TokenNode::Group(Delimiter::Parenthesis, quote!($($t)*)) };
+    ([$($t:tt)*]) => { TokenNode::Group(Delimiter::Bracket, quote!($($t)*)) };
+    ({$($t:tt)*}) => { TokenNode::Group(Delimiter::Brace, quote!($($t)*)) };
+    ($t:tt) => { quote_tok!($t) };
 }
 
 macro_rules! quote {
     () => { TokenStream::empty() };
-    ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::<TokenStream>() };
+    ($($t:tt)*) => {
+        [
+            $(TokenStream::from(quote_tree!($t)),)*
+        ].iter().cloned().collect::<TokenStream>()
+    };
 }
 
 impl ProcMacro for Quoter {
-    fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, _: Span, stream: TokenStream) -> TokenStream {
+    fn expand<'cx>(&self, cx: &'cx mut ExtCtxt,
+                   _: ::syntax_pos::Span,
+                   stream: tokenstream::TokenStream)
+                   -> tokenstream::TokenStream {
         let mut info = cx.current_expansion.mark.expn_info().unwrap();
         info.callee.allow_internal_unstable = true;
         cx.current_expansion.mark.set_expn_info(info);
-        ::__internal::set_sess(cx, || quote!(::TokenStream { 0: (quote stream) }))
+        ::__internal::set_sess(cx, || TokenStream(stream).quote().0)
     }
 }
 
 impl<T: Quote> Quote for Option<T> {
-    fn quote(&self) -> TokenStream {
-        match *self {
-            Some(ref t) => quote!(Some((quote t))),
+    fn quote(self) -> TokenStream {
+        match self {
+            Some(t) => quote!(Some((quote t))),
             None => quote!(None),
         }
     }
 }
 
 impl Quote for TokenStream {
-    fn quote(&self) -> TokenStream {
-        let mut builder = TokenStreamBuilder::new();
-        builder.push(quote!(rt::TokenStreamBuilder::new()));
-
-        let mut trees = self.trees();
-        loop {
-            let (mut tree, mut is_joint) = match trees.next_as_stream() {
-                Some(next) => next.as_tree(),
-                None => return builder.add(quote!(.build())).build(),
-            };
-            if let TokenTree::Token(_, Token::Dollar) = tree {
-                let (next_tree, next_is_joint) = match trees.next_as_stream() {
-                    Some(next) => next.as_tree(),
-                    None => panic!("unexpected trailing `$` in `quote!`"),
-                };
-                match next_tree {
-                    TokenTree::Token(_, Token::Ident(..)) => {
-                        builder.push(quote!(.add(rt::unquote(&(unquote next_tree)))));
-                        continue
-                    }
-                    TokenTree::Token(_, Token::Dollar) => {
-                        tree = next_tree;
-                        is_joint = next_is_joint;
+    fn quote(self) -> TokenStream {
+        if self.is_empty() {
+            return quote!(::TokenStream::empty());
+        }
+        let mut after_dollar = false;
+        let tokens = self.into_iter().filter_map(|tree| {
+            if after_dollar {
+                after_dollar = false;
+                match tree.kind {
+                    TokenNode::Term(_) => {
+                        return Some(quote!(::__internal::unquote(&(unquote tree)),));
                     }
+                    TokenNode::Op('$', _) => {}
                     _ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
                 }
+            } else if let TokenNode::Op('$', _) = tree.kind {
+                after_dollar = true;
+                return None;
             }
 
-            builder.push(match is_joint {
-                true => quote!(.add((quote tree).joint())),
-                false => quote!(.add(rt::TokenStream::from((quote tree)))),
-            });
+            Some(quote!(::TokenStream::from((quote tree)),))
+        }).collect::<TokenStream>();
+
+        if after_dollar {
+            panic!("unexpected trailing `$` in `quote!`");
         }
+
+        quote!([(unquote tokens)].iter().cloned().collect::<::TokenStream>())
     }
 }
 
 impl Quote for TokenTree {
-    fn quote(&self) -> TokenStream {
-        match *self {
-            TokenTree::Token(span, ref token) => quote! {
-                rt::TokenTree::Token((quote span), (quote token))
-            },
-            TokenTree::Delimited(span, ref delimited) => quote! {
-                rt::TokenTree::Delimited((quote span), (quote delimited))
-            },
-        }
+    fn quote(self) -> TokenStream {
+        quote!(::TokenTree { span: (quote self.span), kind: (quote self.kind) })
     }
 }
 
-impl Quote for Delimited {
-    fn quote(&self) -> TokenStream {
-        quote!(rt::Delimited { delim: (quote self.delim), tts: (quote self.stream()).into() })
+impl Quote for TokenNode {
+    fn quote(self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident($($arg:ident),+)),*) => {
+                match self {
+                    $(TokenNode::$i($($arg),+) => quote! {
+                        ::TokenNode::$i($((quote $arg)),+)
+                    },)*
+                }
+            }
+        }
+
+        gen_match! { Op(op, kind), Group(delim, tokens), Term(term), Literal(lit) }
     }
 }
 
-impl<'a> Quote for &'a str {
-    fn quote(&self) -> TokenStream {
-        TokenTree::Token(span(), Token::Literal(token::Lit::Str_(Symbol::intern(self)), None))
-            .into()
+impl Quote for char {
+    fn quote(self) -> TokenStream {
+        TokenNode::Literal(Literal::character(self)).into()
     }
 }
 
-impl Quote for usize {
-    fn quote(&self) -> TokenStream {
-        let integer_symbol = Symbol::intern(&self.to_string());
-        TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Integer(integer_symbol), None))
-            .into()
+impl<'a> Quote for &'a str {
+    fn quote(self) -> TokenStream {
+        TokenNode::Literal(Literal::string(self)).into()
     }
 }
 
-impl Quote for Ident {
-    fn quote(&self) -> TokenStream {
-        quote!(rt::Ident { name: (quote self.name), ctxt: rt::ctxt() })
+impl Quote for usize {
+    fn quote(self) -> TokenStream {
+        TokenNode::Literal(Literal::integer(self as i128)).into()
     }
 }
 
-impl Quote for Symbol {
-    fn quote(&self) -> TokenStream {
-        quote!(rt::Symbol::intern((quote &*self.as_str())))
+impl Quote for Term {
+    fn quote(self) -> TokenStream {
+        quote!(::Term::intern((quote self.as_str())))
     }
 }
 
 impl Quote for Span {
-    fn quote(&self) -> TokenStream {
-        quote!(rt::span())
+    fn quote(self) -> TokenStream {
+        quote!(::Span::default())
     }
 }
 
-impl Quote for Token {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*; $($t:tt)*) => {
-                match *self {
-                    $( Token::$i => quote!(rt::token::$i), )*
-                    $( $t )*
+macro_rules! literals {
+    ($($i:ident),*; $($raw:ident),*) => {
+        pub enum LiteralKind {
+            $($i,)*
+            $($raw(usize),)*
+        }
+
+        impl LiteralKind {
+            pub fn with_contents_and_suffix(self, contents: Term, suffix: Option<Term>)
+                                            -> Literal {
+                let contents = contents.0;
+                let suffix = suffix.map(|t| t.0);
+                match self {
+                    $(LiteralKind::$i => {
+                        Literal(token::Literal(token::Lit::$i(contents), suffix))
+                    })*
+                    $(LiteralKind::$raw(n) => {
+                        Literal(token::Literal(token::Lit::$raw(contents, n), suffix))
+                    })*
                 }
             }
         }
 
-        gen_match! {
-            Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
-            DotDotEq, Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar,
-            Question, Underscore;
-
-            Token::OpenDelim(delim) => quote!(rt::token::OpenDelim((quote delim))),
-            Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))),
-            Token::BinOp(tok) => quote!(rt::token::BinOp((quote tok))),
-            Token::BinOpEq(tok) => quote!(rt::token::BinOpEq((quote tok))),
-            Token::Ident(ident) => quote!(rt::token::Ident((quote ident))),
-            Token::Lifetime(ident) => quote!(rt::token::Lifetime((quote ident))),
-            Token::Literal(lit, sfx) => quote!(rt::token::Literal((quote lit), (quote sfx))),
-            _ => panic!("Unhandled case!"),
+        impl Literal {
+            fn kind_contents_and_suffix(self) -> (LiteralKind, Term, Option<Term>) {
+                let (lit, suffix) = match self.0 {
+                    token::Literal(lit, suffix) => (lit, suffix),
+                    _ => panic!("unsupported literal {:?}", self.0),
+                };
+
+                let (kind, contents) = match lit {
+                    $(token::Lit::$i(contents) => (LiteralKind::$i, contents),)*
+                    $(token::Lit::$raw(contents, n) => (LiteralKind::$raw(n), contents),)*
+                };
+                (kind, Term(contents), suffix.map(Term))
+            }
         }
-    }
-}
 
-impl Quote for token::BinOpToken {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $( token::BinOpToken::$i => quote!(rt::token::BinOpToken::$i), )*
+        impl Quote for LiteralKind {
+            fn quote(self) -> TokenStream {
+                match self {
+                    $(LiteralKind::$i => quote! {
+                        ::__internal::LiteralKind::$i
+                    },)*
+                    $(LiteralKind::$raw(n) => quote! {
+                        ::__internal::LiteralKind::$raw((quote n))
+                    },)*
                 }
             }
         }
 
-        gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr)
+        impl Quote for Literal {
+            fn quote(self) -> TokenStream {
+                let (kind, contents, suffix) = self.kind_contents_and_suffix();
+                quote! {
+                    (quote kind).with_contents_and_suffix((quote contents), (quote suffix))
+                }
+            }
+        }
     }
 }
 
-impl Quote for Lit {
-    fn quote(&self) -> TokenStream {
+literals!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw);
+
+impl Quote for Delimiter {
+    fn quote(self) -> TokenStream {
         macro_rules! gen_match {
-            ($($i:ident),*; $($raw:ident),*) => {
-                match *self {
-                    $( Lit::$i(lit) => quote!(rt::token::Lit::$i((quote lit))), )*
-                    $( Lit::$raw(lit, n) => {
-                        quote!(::syntax::parse::token::Lit::$raw((quote lit), (quote n)))
-                    })*
+            ($($i:ident),*) => {
+                match self {
+                    $(Delimiter::$i => { quote!(::Delimiter::$i) })*
                 }
             }
         }
 
-        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw)
+        gen_match!(Parenthesis, Brace, Bracket, None)
     }
 }
 
-impl Quote for token::DelimToken {
-    fn quote(&self) -> TokenStream {
+impl Quote for Spacing {
+    fn quote(self) -> TokenStream {
         macro_rules! gen_match {
             ($($i:ident),*) => {
-                match *self {
-                    $(token::DelimToken::$i => { quote!(rt::token::DelimToken::$i) })*
+                match self {
+                    $(Spacing::$i => { quote!(::Spacing::$i) })*
                 }
             }
         }
 
-        gen_match!(Paren, Bracket, Brace, NoDelim)
+        gen_match!(Alone, Joint)
     }
 }
diff --git a/src/librand/Cargo.toml b/src/librand/Cargo.toml
deleted file mode 100644 (file)
index eda5f21..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "rand"
-version = "0.0.0"
-
-[lib]
-name = "rand"
-path = "lib.rs"
-doc = false
-
-[dependencies]
-core = { path = "../libcore" }
diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs
deleted file mode 100644 (file)
index e355eb4..0000000
+++ /dev/null
@@ -1,309 +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.
-
-//! The ChaCha random number generator.
-
-use core::fmt;
-use {Rand, Rng, SeedableRng};
-
-const KEY_WORDS: usize = 8; // 8 words for the 256-bit key
-const STATE_WORDS: usize = 16;
-const CHACHA_ROUNDS: usize = 20; // Cryptographically secure from 8 upwards as of this writing
-
-/// A random number generator that uses the ChaCha20 algorithm [1].
-///
-/// The ChaCha algorithm is widely accepted as suitable for
-/// cryptographic purposes, but this implementation has not been
-/// verified as such. Prefer a generator like `OsRng` that defers to
-/// the operating system for cases that need high security.
-///
-/// [1]: D. J. Bernstein, [*ChaCha, a variant of
-/// Salsa20*](http://cr.yp.to/chacha.html)
-#[derive(Copy, Clone)]
-pub struct ChaChaRng {
-    buffer: [u32; STATE_WORDS], // Internal buffer of output
-    state: [u32; STATE_WORDS], // Initial state
-    index: usize, // Index into state
-}
-
-impl fmt::Debug for ChaChaRng {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("ChaChaRng")
-         .field("buffer", &self.buffer.iter())
-         .field("state", &self.state.iter())
-         .field("index", &self.index)
-         .finish()
-    }
-}
-
-static EMPTY: ChaChaRng = ChaChaRng {
-    buffer: [0; STATE_WORDS],
-    state: [0; STATE_WORDS],
-    index: STATE_WORDS,
-};
-
-
-macro_rules! quarter_round{
-    ($a: expr, $b: expr, $c: expr, $d: expr) => {{
-        $a = $a.wrapping_add($b); $d = $d ^ $a; $d = $d.rotate_left(16);
-        $c = $c.wrapping_add($d); $b = $b ^ $c; $b = $b.rotate_left(12);
-        $a = $a.wrapping_add($b); $d = $d ^ $a; $d = $d.rotate_left( 8);
-        $c = $c.wrapping_add($d); $b = $b ^ $c; $b = $b.rotate_left( 7);
-    }}
-}
-
-macro_rules! double_round{
-    ($x: expr) => {{
-        // Column round
-        quarter_round!($x[ 0], $x[ 4], $x[ 8], $x[12]);
-        quarter_round!($x[ 1], $x[ 5], $x[ 9], $x[13]);
-        quarter_round!($x[ 2], $x[ 6], $x[10], $x[14]);
-        quarter_round!($x[ 3], $x[ 7], $x[11], $x[15]);
-        // Diagonal round
-        quarter_round!($x[ 0], $x[ 5], $x[10], $x[15]);
-        quarter_round!($x[ 1], $x[ 6], $x[11], $x[12]);
-        quarter_round!($x[ 2], $x[ 7], $x[ 8], $x[13]);
-        quarter_round!($x[ 3], $x[ 4], $x[ 9], $x[14]);
-    }}
-}
-
-#[inline]
-fn core(output: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) {
-    *output = *input;
-
-    for _ in 0..CHACHA_ROUNDS / 2 {
-        double_round!(output);
-    }
-
-    for i in 0..STATE_WORDS {
-        output[i] = output[i].wrapping_add(input[i]);
-    }
-}
-
-impl ChaChaRng {
-    /// Create an ChaCha random number generator using the default
-    /// fixed key of 8 zero words.
-    pub fn new_unseeded() -> ChaChaRng {
-        let mut rng = EMPTY;
-        rng.init(&[0; KEY_WORDS]);
-        rng
-    }
-
-    /// Sets the internal 128-bit ChaCha counter to
-    /// a user-provided value. This permits jumping
-    /// arbitrarily ahead (or backwards) in the pseudorandom stream.
-    ///
-    /// Since the nonce words are used to extend the counter to 128 bits,
-    /// users wishing to obtain the conventional ChaCha pseudorandom stream
-    /// associated with a particular nonce can call this function with
-    /// arguments `0, desired_nonce`.
-    pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
-        self.state[12] = (counter_low >> 0) as u32;
-        self.state[13] = (counter_low >> 32) as u32;
-        self.state[14] = (counter_high >> 0) as u32;
-        self.state[15] = (counter_high >> 32) as u32;
-        self.index = STATE_WORDS; // force recomputation
-    }
-
-    /// Initializes `self.state` with the appropriate key and constants
-    ///
-    /// We deviate slightly from the ChaCha specification regarding
-    /// the nonce, which is used to extend the counter to 128 bits.
-    /// This is provably as strong as the original cipher, though,
-    /// since any distinguishing attack on our variant also works
-    /// against ChaCha with a chosen-nonce. See the XSalsa20 [1]
-    /// security proof for a more involved example of this.
-    ///
-    /// The modified word layout is:
-    /// ```text
-    /// constant constant constant constant
-    /// key      key      key      key
-    /// key      key      key      key
-    /// counter  counter  counter  counter
-    /// ```
-    /// [1]: Daniel J. Bernstein. [*Extending the Salsa20
-    /// nonce.*](http://cr.yp.to/papers.html#xsalsa)
-    fn init(&mut self, key: &[u32; KEY_WORDS]) {
-        self.state[0] = 0x61707865;
-        self.state[1] = 0x3320646E;
-        self.state[2] = 0x79622D32;
-        self.state[3] = 0x6B206574;
-
-        for i in 0..KEY_WORDS {
-            self.state[4 + i] = key[i];
-        }
-
-        self.state[12] = 0;
-        self.state[13] = 0;
-        self.state[14] = 0;
-        self.state[15] = 0;
-
-        self.index = STATE_WORDS;
-    }
-
-    /// Refill the internal output buffer (`self.buffer`)
-    fn update(&mut self) {
-        core(&mut self.buffer, &self.state);
-        self.index = 0;
-        // update 128-bit counter
-        self.state[12] += 1;
-        if self.state[12] != 0 {
-            return;
-        }
-        self.state[13] += 1;
-        if self.state[13] != 0 {
-            return;
-        }
-        self.state[14] += 1;
-        if self.state[14] != 0 {
-            return;
-        }
-        self.state[15] += 1;
-    }
-}
-
-impl Rng for ChaChaRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        if self.index == STATE_WORDS {
-            self.update();
-        }
-
-        let value = self.buffer[self.index % STATE_WORDS];
-        self.index += 1;
-        value
-    }
-}
-
-impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
-    fn reseed(&mut self, seed: &'a [u32]) {
-        // reset state
-        self.init(&[0; KEY_WORDS]);
-        // set key in place
-        let key = &mut self.state[4..4 + KEY_WORDS];
-        for (k, s) in key.iter_mut().zip(seed) {
-            *k = *s;
-        }
-    }
-
-    /// Create a ChaCha generator from a seed,
-    /// obtained from a variable-length u32 array.
-    /// Only up to 8 words are used; if less than 8
-    /// words are used, the remaining are set to zero.
-    fn from_seed(seed: &'a [u32]) -> ChaChaRng {
-        let mut rng = EMPTY;
-        rng.reseed(seed);
-        rng
-    }
-}
-
-impl Rand for ChaChaRng {
-    fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
-        let mut key: [u32; KEY_WORDS] = [0; KEY_WORDS];
-        for word in &mut key {
-            *word = other.gen();
-        }
-        SeedableRng::from_seed(&key[..])
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    use std::prelude::v1::*;
-
-    use {Rng, SeedableRng};
-    use super::ChaChaRng;
-
-    #[test]
-    fn test_rng_rand_seeded() {
-        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>();
-        let mut ra: ChaChaRng = SeedableRng::from_seed(&*s);
-        let mut rb: ChaChaRng = SeedableRng::from_seed(&*s);
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-
-    #[test]
-    fn test_rng_seeded() {
-        let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
-        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
-        let mut rb: ChaChaRng = SeedableRng::from_seed(seed);
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-
-    #[test]
-    fn test_rng_reseed() {
-        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>();
-        let mut r: ChaChaRng = SeedableRng::from_seed(&*s);
-        let string1: String = r.gen_ascii_chars().take(100).collect();
-
-        r.reseed(&s);
-
-        let string2: String = r.gen_ascii_chars().take(100).collect();
-        assert_eq!(string1, string2);
-    }
-
-    #[test]
-    #[rustfmt_skip]
-    fn test_rng_true_values() {
-        // Test vectors 1 and 2 from
-        // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
-        let seed: &[_] = &[0; 8];
-        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
-
-        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
-        assert_eq!(v,
-                   vec![0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653,
-                        0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b,
-                        0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8,
-                        0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2]);
-
-        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
-        assert_eq!(v,
-                   vec![0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73,
-                        0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32,
-                        0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874,
-                        0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b]);
-
-
-        let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
-        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
-
-        // Store the 17*i-th 32-bit word,
-        // i.e., the i-th word of the i-th 16-word block
-        let mut v: Vec<u32> = Vec::new();
-        for _ in 0..16 {
-            v.push(ra.next_u32());
-            for _ in 0..16 {
-                ra.next_u32();
-            }
-        }
-
-        assert_eq!(v,
-                   vec![0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036,
-                        0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384,
-                        0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
-                        0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4]);
-    }
-
-    #[test]
-    fn test_rng_clone() {
-        let seed: &[_] = &[0; 8];
-        let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
-        let mut clone = rng.clone();
-        for _ in 0..16 {
-            assert_eq!(rng.next_u64(), clone.next_u64());
-        }
-    }
-}
diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs
deleted file mode 100644 (file)
index 3337cc2..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The exponential distribution.
-
-use core::fmt;
-
-#[cfg(not(test))] // only necessary for no_std
-use FloatMath;
-
-use {Rand, Rng};
-use distributions::{IndependentSample, Sample, ziggurat, ziggurat_tables};
-
-/// A wrapper around an `f64` to generate Exp(1) random numbers.
-///
-/// See `Exp` for the general exponential distribution. Note that this has to
-/// be unwrapped before use as an `f64` (using either `*` or `mem::transmute`
-/// is safe).
-///
-/// Implemented via the ZIGNOR variant[1] of the Ziggurat method. The
-/// exact description in the paper was adjusted to use tables for the
-/// exponential distribution rather than normal.
-///
-/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
-/// Generate Normal Random
-/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
-/// College, Oxford
-#[derive(Copy, Clone)]
-pub struct Exp1(pub f64);
-
-// This could be done via `-rng.gen::<f64>().ln()` but that is slower.
-impl Rand for Exp1 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> Exp1 {
-        #[inline]
-        fn pdf(x: f64) -> f64 {
-            (-x).exp()
-        }
-        #[inline]
-        fn zero_case<R: Rng>(rng: &mut R, _u: f64) -> f64 {
-            ziggurat_tables::ZIG_EXP_R - rng.gen::<f64>().ln()
-        }
-
-        Exp1(ziggurat(rng,
-                      false,
-                      &ziggurat_tables::ZIG_EXP_X,
-                      &ziggurat_tables::ZIG_EXP_F,
-                      pdf,
-                      zero_case))
-    }
-}
-
-impl fmt::Debug for Exp1 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("Exp1")
-         .field(&self.0)
-         .finish()
-    }
-}
-
-/// The exponential distribution `Exp(lambda)`.
-///
-/// This distribution has density function: `f(x) = lambda *
-/// exp(-lambda * x)` for `x > 0`.
-#[derive(Copy, Clone)]
-pub struct Exp {
-    /// `lambda` stored as `1/lambda`, since this is what we scale by.
-    lambda_inverse: f64,
-}
-
-impl Exp {
-    /// Construct a new `Exp` with the given shape parameter
-    /// `lambda`. Panics if `lambda <= 0`.
-    pub fn new(lambda: f64) -> Exp {
-        assert!(lambda > 0.0, "Exp::new called with `lambda` <= 0");
-        Exp { lambda_inverse: 1.0 / lambda }
-    }
-}
-
-impl Sample<f64> for Exp {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for Exp {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        let Exp1(n) = rng.gen::<Exp1>();
-        n * self.lambda_inverse
-    }
-}
-
-impl fmt::Debug for Exp {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Exp")
-         .field("lambda_inverse", &self.lambda_inverse)
-         .finish()
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use distributions::{IndependentSample, Sample};
-    use super::Exp;
-
-    #[test]
-    fn test_exp() {
-        let mut exp = Exp::new(10.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            assert!(exp.sample(&mut rng) >= 0.0);
-            assert!(exp.ind_sample(&mut rng) >= 0.0);
-        }
-    }
-    #[test]
-    #[should_panic]
-    fn test_exp_invalid_lambda_zero() {
-        Exp::new(0.0);
-    }
-    #[test]
-    #[should_panic]
-    fn test_exp_invalid_lambda_neg() {
-        Exp::new(-10.0);
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-
-    use self::test::Bencher;
-    use std::mem::size_of;
-    use super::Exp;
-    use distributions::Sample;
-
-    #[bench]
-    fn rand_exp(b: &mut Bencher) {
-        let mut rng = ::test::weak_rng();
-        let mut exp = Exp::new(2.71828 * 3.14159);
-
-        b.iter(|| {
-            for _ in 0..::RAND_BENCH_N {
-                exp.sample(&mut rng);
-            }
-        });
-        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-    }
-}
diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs
deleted file mode 100644 (file)
index e796197..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The Gamma and derived distributions.
-
-use core::fmt;
-
-use self::GammaRepr::*;
-use self::ChiSquaredRepr::*;
-
-#[cfg(not(test))] // only necessary for no_std
-use FloatMath;
-
-use {Open01, Rng};
-use super::normal::StandardNormal;
-use super::{Exp, IndependentSample, Sample};
-
-/// The Gamma distribution `Gamma(shape, scale)` distribution.
-///
-/// The density function of this distribution is
-///
-/// ```text
-/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
-/// ```
-///
-/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
-/// scale and both `k` and `θ` are strictly positive.
-///
-/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
-/// falling back to directly sampling from an Exponential for `shape
-/// == 1`, and using the boosting technique described in [1] for
-/// `shape < 1`.
-///
-/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
-/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
-/// (September 2000),
-/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
-pub struct Gamma {
-    repr: GammaRepr,
-}
-
-impl fmt::Debug for Gamma {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Gamma")
-         .field("repr",
-                &match self.repr {
-                    GammaRepr::Large(_) => "Large",
-                    GammaRepr::One(_) => "Exp",
-                    GammaRepr::Small(_) => "Small"
-                })
-          .finish()
-    }
-}
-
-enum GammaRepr {
-    Large(GammaLargeShape),
-    One(Exp),
-    Small(GammaSmallShape),
-}
-
-// These two helpers could be made public, but saving the
-// match-on-Gamma-enum branch from using them directly (e.g. if one
-// knows that the shape is always > 1) doesn't appear to be much
-// faster.
-
-/// Gamma distribution where the shape parameter is less than 1.
-///
-/// Note, samples from this require a compulsory floating-point `pow`
-/// call, which makes it significantly slower than sampling from a
-/// gamma distribution where the shape parameter is greater than or
-/// equal to 1.
-///
-/// See `Gamma` for sampling from a Gamma distribution with general
-/// shape parameters.
-struct GammaSmallShape {
-    inv_shape: f64,
-    large_shape: GammaLargeShape,
-}
-
-/// Gamma distribution where the shape parameter is larger than 1.
-///
-/// See `Gamma` for sampling from a Gamma distribution with general
-/// shape parameters.
-struct GammaLargeShape {
-    scale: f64,
-    c: f64,
-    d: f64,
-}
-
-impl Gamma {
-    /// Construct an object representing the `Gamma(shape, scale)`
-    /// distribution.
-    ///
-    /// Panics if `shape <= 0` or `scale <= 0`.
-    pub fn new(shape: f64, scale: f64) -> Gamma {
-        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
-        assert!(scale > 0.0, "Gamma::new called with scale <= 0");
-
-        let repr = if shape == 1.0 {
-            One(Exp::new(1.0 / scale))
-        } else if 0.0 <= shape && shape < 1.0 {
-            Small(GammaSmallShape::new_raw(shape, scale))
-        } else {
-            Large(GammaLargeShape::new_raw(shape, scale))
-        };
-        Gamma { repr }
-    }
-}
-
-impl GammaSmallShape {
-    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
-        GammaSmallShape {
-            inv_shape: 1. / shape,
-            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale),
-        }
-    }
-}
-
-impl GammaLargeShape {
-    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
-        let d = shape - 1. / 3.;
-        GammaLargeShape {
-            scale,
-            c: 1. / (9. * d).sqrt(),
-            d,
-        }
-    }
-}
-
-impl Sample<f64> for Gamma {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-impl Sample<f64> for GammaSmallShape {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-impl Sample<f64> for GammaLargeShape {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for Gamma {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        match self.repr {
-            Small(ref g) => g.ind_sample(rng),
-            One(ref g) => g.ind_sample(rng),
-            Large(ref g) => g.ind_sample(rng),
-        }
-    }
-}
-impl IndependentSample<f64> for GammaSmallShape {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        let Open01(u) = rng.gen::<Open01<f64>>();
-
-        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
-    }
-}
-impl IndependentSample<f64> for GammaLargeShape {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        loop {
-            let StandardNormal(x) = rng.gen::<StandardNormal>();
-            let v_cbrt = 1.0 + self.c * x;
-            if v_cbrt <= 0.0 {
-                // a^3 <= 0 iff a <= 0
-                continue;
-            }
-
-            let v = v_cbrt * v_cbrt * v_cbrt;
-            let Open01(u) = rng.gen::<Open01<f64>>();
-
-            let x_sqr = x * x;
-            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
-               u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
-                return self.d * v * self.scale;
-            }
-        }
-    }
-}
-
-/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
-/// freedom.
-///
-/// For `k > 0` integral, this distribution is the sum of the squares
-/// of `k` independent standard normal random variables. For other
-/// `k`, this uses the equivalent characterization `χ²(k) = Gamma(k/2,
-/// 2)`.
-pub struct ChiSquared {
-    repr: ChiSquaredRepr,
-}
-
-impl fmt::Debug for ChiSquared {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("ChiSquared")
-         .field("repr",
-                &match self.repr {
-                    ChiSquaredRepr::DoFExactlyOne => "DoFExactlyOne",
-                    ChiSquaredRepr::DoFAnythingElse(_) => "DoFAnythingElse",
-                })
-         .finish()
-    }
-}
-
-enum ChiSquaredRepr {
-    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
-    // e.g. when alpha = 1/2 as it would be for this case, so special-
-    // casing and using the definition of N(0,1)^2 is faster.
-    DoFExactlyOne,
-    DoFAnythingElse(Gamma),
-}
-
-impl ChiSquared {
-    /// Create a new chi-squared distribution with degrees-of-freedom
-    /// `k`. Panics if `k < 0`.
-    pub fn new(k: f64) -> ChiSquared {
-        let repr = if k == 1.0 {
-            DoFExactlyOne
-        } else {
-            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
-            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
-        };
-        ChiSquared { repr: repr }
-    }
-}
-
-impl Sample<f64> for ChiSquared {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for ChiSquared {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        match self.repr {
-            DoFExactlyOne => {
-                // k == 1 => N(0,1)^2
-                let StandardNormal(norm) = rng.gen::<StandardNormal>();
-                norm * norm
-            }
-            DoFAnythingElse(ref g) => g.ind_sample(rng),
-        }
-    }
-}
-
-/// The Fisher F distribution `F(m, n)`.
-///
-/// This distribution is equivalent to the ratio of two normalized
-/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
-/// (χ²(n)/n)`.
-pub struct FisherF {
-    numer: ChiSquared,
-    denom: ChiSquared,
-    // denom_dof / numer_dof so that this can just be a straight
-    // multiplication, rather than a division.
-    dof_ratio: f64,
-}
-
-impl FisherF {
-    /// Create a new `FisherF` distribution, with the given
-    /// parameter. Panics if either `m` or `n` are not positive.
-    pub fn new(m: f64, n: f64) -> FisherF {
-        assert!(m > 0.0, "FisherF::new called with `m < 0`");
-        assert!(n > 0.0, "FisherF::new called with `n < 0`");
-
-        FisherF {
-            numer: ChiSquared::new(m),
-            denom: ChiSquared::new(n),
-            dof_ratio: n / m,
-        }
-    }
-}
-
-impl Sample<f64> for FisherF {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for FisherF {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
-    }
-}
-
-impl fmt::Debug for FisherF {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("FisherF")
-         .field("numer", &self.numer)
-         .field("denom", &self.denom)
-         .field("dof_ratio", &self.dof_ratio)
-         .finish()
-    }
-}
-
-/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
-/// freedom.
-pub struct StudentT {
-    chi: ChiSquared,
-    dof: f64,
-}
-
-impl StudentT {
-    /// Create a new Student t distribution with `n` degrees of
-    /// freedom. Panics if `n <= 0`.
-    pub fn new(n: f64) -> StudentT {
-        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
-        StudentT {
-            chi: ChiSquared::new(n),
-            dof: n,
-        }
-    }
-}
-
-impl Sample<f64> for StudentT {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for StudentT {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        let StandardNormal(norm) = rng.gen::<StandardNormal>();
-        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
-    }
-}
-
-impl fmt::Debug for StudentT {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("StudentT")
-         .field("chi", &self.chi)
-         .field("dof", &self.dof)
-         .finish()
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use distributions::{IndependentSample, Sample};
-    use super::{ChiSquared, FisherF, StudentT};
-
-    #[test]
-    fn test_chi_squared_one() {
-        let mut chi = ChiSquared::new(1.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            chi.sample(&mut rng);
-            chi.ind_sample(&mut rng);
-        }
-    }
-    #[test]
-    fn test_chi_squared_small() {
-        let mut chi = ChiSquared::new(0.5);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            chi.sample(&mut rng);
-            chi.ind_sample(&mut rng);
-        }
-    }
-    #[test]
-    fn test_chi_squared_large() {
-        let mut chi = ChiSquared::new(30.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            chi.sample(&mut rng);
-            chi.ind_sample(&mut rng);
-        }
-    }
-    #[test]
-    #[should_panic]
-    fn test_chi_squared_invalid_dof() {
-        ChiSquared::new(-1.0);
-    }
-
-    #[test]
-    fn test_f() {
-        let mut f = FisherF::new(2.0, 32.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            f.sample(&mut rng);
-            f.ind_sample(&mut rng);
-        }
-    }
-
-    #[test]
-    fn test_t() {
-        let mut t = StudentT::new(11.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            t.sample(&mut rng);
-            t.ind_sample(&mut rng);
-        }
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-    use self::test::Bencher;
-    use std::mem::size_of;
-    use distributions::IndependentSample;
-    use super::Gamma;
-
-
-    #[bench]
-    fn bench_gamma_large_shape(b: &mut Bencher) {
-        let gamma = Gamma::new(10., 1.0);
-        let mut rng = ::test::weak_rng();
-
-        b.iter(|| {
-            for _ in 0..::RAND_BENCH_N {
-                gamma.ind_sample(&mut rng);
-            }
-        });
-        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-    }
-
-    #[bench]
-    fn bench_gamma_small_shape(b: &mut Bencher) {
-        let gamma = Gamma::new(0.1, 1.0);
-        let mut rng = ::test::weak_rng();
-
-        b.iter(|| {
-            for _ in 0..::RAND_BENCH_N {
-                gamma.ind_sample(&mut rng);
-            }
-        });
-        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-    }
-}
diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs
deleted file mode 100644 (file)
index 47967a7..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Sampling from random distributions.
-//!
-//! This is a generalization of `Rand` to allow parameters to control the
-//! exact properties of the generated values, e.g. the mean and standard
-//! deviation of a normal distribution. The `Sample` trait is the most
-//! general, and allows for generating values that change some state
-//! internally. The `IndependentSample` trait is for generating values
-//! that do not need to record state.
-
-use core::fmt;
-
-#[cfg(not(test))] // only necessary for no_std
-use core::num::Float;
-
-use core::marker::PhantomData;
-
-use {Rand, Rng};
-
-pub use self::range::Range;
-pub use self::gamma::{ChiSquared, FisherF, Gamma, StudentT};
-pub use self::normal::{LogNormal, Normal};
-pub use self::exponential::Exp;
-
-pub mod range;
-pub mod gamma;
-pub mod normal;
-pub mod exponential;
-
-/// Types that can be used to create a random instance of `Support`.
-pub trait Sample<Support> {
-    /// Generate a random value of `Support`, using `rng` as the
-    /// source of randomness.
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> Support;
-}
-
-/// `Sample`s that do not require keeping track of state.
-///
-/// Since no state is recorded, each sample is (statistically)
-/// independent of all others, assuming the `Rng` used has this
-/// property.
-// FIXME maybe having this separate is overkill (the only reason is to
-// take &self rather than &mut self)? or maybe this should be the
-// trait called `Sample` and the other should be `DependentSample`.
-pub trait IndependentSample<Support>: Sample<Support> {
-    /// Generate a random value.
-    fn ind_sample<R: Rng>(&self, _: &mut R) -> Support;
-}
-
-/// A wrapper for generating types that implement `Rand` via the
-/// `Sample` & `IndependentSample` traits.
-pub struct RandSample<Sup> {
-    _marker: PhantomData<Sup>,
-}
-
-impl<Sup> RandSample<Sup> {
-    pub fn new() -> RandSample<Sup> {
-        RandSample { _marker: PhantomData }
-    }
-}
-
-impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup {
-        self.ind_sample(rng)
-    }
-}
-
-impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
-        rng.gen()
-    }
-}
-
-impl<Sup> fmt::Debug for RandSample<Sup> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("RandSample { .. }")
-    }
-}
-
-/// A value with a particular weight for use with `WeightedChoice`.
-pub struct Weighted<T> {
-    /// The numerical weight of this item
-    pub weight: usize,
-    /// The actual item which is being weighted
-    pub item: T,
-}
-
-impl<T: fmt::Debug> fmt::Debug for Weighted<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Weighted")
-         .field("weight", &self.weight)
-         .field("item", &self.item)
-         .finish()
-    }
-}
-
-/// A distribution that selects from a finite collection of weighted items.
-///
-/// Each item has an associated weight that influences how likely it
-/// is to be chosen: higher weight is more likely.
-///
-/// The `Clone` restriction is a limitation of the `Sample` and
-/// `IndependentSample` traits. Note that `&T` is (cheaply) `Clone` for
-/// all `T`, as is `usize`, so one can store references or indices into
-/// another vector.
-pub struct WeightedChoice<'a, T: 'a> {
-    items: &'a mut [Weighted<T>],
-    weight_range: Range<usize>,
-}
-
-impl<'a, T: Clone> WeightedChoice<'a, T> {
-    /// Create a new `WeightedChoice`.
-    ///
-    /// Panics if:
-    /// - `v` is empty
-    /// - the total weight is 0
-    /// - the total weight is larger than a `usize` can contain.
-    pub fn new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
-        // strictly speaking, this is subsumed by the total weight == 0 case
-        assert!(!items.is_empty(),
-                "WeightedChoice::new called with no items");
-
-        let mut running_total = 0_usize;
-
-        // we convert the list from individual weights to cumulative
-        // weights so we can binary search. This *could* drop elements
-        // with weight == 0 as an optimisation.
-        for item in &mut *items {
-            running_total = match running_total.checked_add(item.weight) {
-                Some(n) => n,
-                None => {
-                    panic!("WeightedChoice::new called with a total weight larger than a usize \
-                            can contain")
-                }
-            };
-
-            item.weight = running_total;
-        }
-        assert!(running_total != 0,
-                "WeightedChoice::new called with a total weight of 0");
-
-        WeightedChoice {
-            items,
-            // we're likely to be generating numbers in this range
-            // relatively often, so might as well cache it
-            weight_range: Range::new(0, running_total),
-        }
-    }
-}
-
-impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> T {
-        self.ind_sample(rng)
-    }
-}
-
-impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> T {
-        // we want to find the first element that has cumulative
-        // weight > sample_weight, which we do by binary since the
-        // cumulative weights of self.items are sorted.
-
-        // choose a weight in [0, total_weight)
-        let sample_weight = self.weight_range.ind_sample(rng);
-
-        // short circuit when it's the first item
-        if sample_weight < self.items[0].weight {
-            return self.items[0].item.clone();
-        }
-
-        let mut idx = 0;
-        let mut modifier = self.items.len();
-
-        // now we know that every possibility has an element to the
-        // left, so we can just search for the last element that has
-        // cumulative weight <= sample_weight, then the next one will
-        // be "it". (Note that this greatest element will never be the
-        // last element of the vector, since sample_weight is chosen
-        // in [0, total_weight) and the cumulative weight of the last
-        // one is exactly the total weight.)
-        while modifier > 1 {
-            let i = idx + modifier / 2;
-            if self.items[i].weight <= sample_weight {
-                // we're small, so look to the right, but allow this
-                // exact element still.
-                idx = i;
-                // we need the `/ 2` to round up otherwise we'll drop
-                // the trailing elements when `modifier` is odd.
-                modifier += 1;
-            } else {
-                // otherwise we're too big, so go left. (i.e. do
-                // nothing)
-            }
-            modifier /= 2;
-        }
-        return self.items[idx + 1].item.clone();
-    }
-}
-
-impl<'a, T: fmt::Debug> fmt::Debug for WeightedChoice<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("WeightedChoice")
-         .field("items", &self.items)
-         .field("weight_range", &self.weight_range)
-         .finish()
-    }
-}
-
-mod ziggurat_tables;
-
-/// Sample a random number using the Ziggurat method (specifically the
-/// ZIGNOR variant from Doornik 2005). Most of the arguments are
-/// directly from the paper:
-///
-/// * `rng`: source of randomness
-/// * `symmetric`: whether this is a symmetric distribution, or one-sided with P(x < 0) = 0.
-/// * `X`: the $x_i$ abscissae.
-/// * `F`: precomputed values of the PDF at the $x_i$, (i.e. $f(x_i)$)
-/// * `F_DIFF`: precomputed values of $f(x_i) - f(x_{i+1})$
-/// * `pdf`: the probability density function
-/// * `zero_case`: manual sampling from the tail when we chose the
-///    bottom box (i.e. i == 0)
-// the perf improvement (25-50%) is definitely worth the extra code
-// size from force-inlining.
-#[inline(always)]
-fn ziggurat<R: Rng, P, Z>(rng: &mut R,
-                          symmetric: bool,
-                          x_tab: ziggurat_tables::ZigTable,
-                          f_tab: ziggurat_tables::ZigTable,
-                          mut pdf: P,
-                          mut zero_case: Z)
-                          -> f64
-    where P: FnMut(f64) -> f64,
-          Z: FnMut(&mut R, f64) -> f64
-{
-    const SCALE: f64 = (1u64 << 53) as f64;
-    loop {
-        // reimplement the f64 generation as an optimisation suggested
-        // by the Doornik paper: we have a lot of precision-space
-        // (i.e. there are 11 bits of the 64 of a u64 to use after
-        // creating a f64), so we might as well reuse some to save
-        // generating a whole extra random number. (Seems to be 15%
-        // faster.)
-        //
-        // This unfortunately misses out on the benefits of direct
-        // floating point generation if an RNG like dSMFT is
-        // used. (That is, such RNGs create floats directly, highly
-        // efficiently and overload next_f32/f64, so by not calling it
-        // this may be slower than it would be otherwise.)
-        // FIXME: investigate/optimise for the above.
-        let bits: u64 = rng.gen();
-        let i = (bits & 0xff) as usize;
-        let f = (bits >> 11) as f64 / SCALE;
-
-        // u is either U(-1, 1) or U(0, 1) depending on if this is a
-        // symmetric distribution or not.
-        let u = if symmetric { 2.0 * f - 1.0 } else { f };
-        let x = u * x_tab[i];
-
-        let test_x = if symmetric { x.abs() } else { x };
-
-        // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i])
-        if test_x < x_tab[i + 1] {
-            return x;
-        }
-        if i == 0 {
-            return zero_case(rng, u);
-        }
-        // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
-        if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen::<f64>() < pdf(x) {
-            return x;
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use {Rand, Rng};
-    use super::{IndependentSample, RandSample, Sample, Weighted, WeightedChoice};
-
-    #[derive(PartialEq, Debug)]
-    struct ConstRand(usize);
-    impl Rand for ConstRand {
-        fn rand<R: Rng>(_: &mut R) -> ConstRand {
-            ConstRand(0)
-        }
-    }
-
-    // 0, 1, 2, 3, ...
-    struct CountingRng {
-        i: u32,
-    }
-    impl Rng for CountingRng {
-        fn next_u32(&mut self) -> u32 {
-            self.i += 1;
-            self.i - 1
-        }
-        fn next_u64(&mut self) -> u64 {
-            self.next_u32() as u64
-        }
-    }
-
-    #[test]
-    fn test_rand_sample() {
-        let mut rand_sample = RandSample::<ConstRand>::new();
-
-        assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
-        assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
-    }
-    #[test]
-    #[rustfmt_skip]
-    fn test_weighted_choice() {
-        // this makes assumptions about the internal implementation of
-        // WeightedChoice, specifically: it doesn't reorder the items,
-        // it doesn't do weird things to the RNG (so 0 maps to 0, 1 to
-        // 1, internally; modulo a modulo operation).
-
-        macro_rules! t {
-            ($items:expr, $expected:expr) => {{
-                let mut items = $items;
-                let wc = WeightedChoice::new(&mut items);
-                let expected = $expected;
-
-                let mut rng = CountingRng { i: 0 };
-
-                for &val in &expected {
-                    assert_eq!(wc.ind_sample(&mut rng), val)
-                }
-            }}
-        }
-
-        t!(vec![Weighted { weight: 1, item: 10 }],
-           [10]);
-
-        // skip some
-        t!(vec![Weighted { weight: 0, item: 20 },
-                Weighted { weight: 2, item: 21 },
-                Weighted { weight: 0, item: 22 },
-                Weighted { weight: 1, item: 23 }],
-           [21, 21, 23]);
-
-        // different weights
-        t!(vec![Weighted { weight: 4, item: 30 },
-                Weighted { weight: 3, item: 31 }],
-           [30, 30, 30, 30, 31, 31, 31]);
-
-        // check that we're binary searching
-        // correctly with some vectors of odd
-        // length.
-        t!(vec![Weighted { weight: 1, item: 40 },
-                Weighted { weight: 1, item: 41 },
-                Weighted { weight: 1, item: 42 },
-                Weighted { weight: 1, item: 43 },
-                Weighted { weight: 1, item: 44 }],
-           [40, 41, 42, 43, 44]);
-        t!(vec![Weighted { weight: 1, item: 50 },
-                Weighted { weight: 1, item: 51 },
-                Weighted { weight: 1, item: 52 },
-                Weighted { weight: 1, item: 53 },
-                Weighted { weight: 1, item: 54 },
-                Weighted { weight: 1, item: 55 },
-                Weighted { weight: 1, item: 56 }],
-           [50, 51, 52, 53, 54, 55, 56]);
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_weighted_choice_no_items() {
-        WeightedChoice::<isize>::new(&mut []);
-    }
-    #[test]
-    #[should_panic]
-    #[rustfmt_skip]
-    fn test_weighted_choice_zero_weight() {
-        WeightedChoice::new(&mut [Weighted { weight: 0, item: 0 },
-                                  Weighted { weight: 0, item: 1 }]);
-    }
-    #[test]
-    #[should_panic]
-    #[rustfmt_skip]
-    fn test_weighted_choice_weight_overflows() {
-        let x = (!0) as usize / 2; // x + x + 2 is the overflow
-        WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
-                                  Weighted { weight: 1, item: 1 },
-                                  Weighted { weight: x, item: 2 },
-                                  Weighted { weight: 1, item: 3 }]);
-    }
-}
diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs
deleted file mode 100644 (file)
index e1518da..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The normal and derived distributions.
-
-use core::fmt;
-
-#[cfg(not(test))] // only necessary for no_std
-use FloatMath;
-
-use {Open01, Rand, Rng};
-use distributions::{IndependentSample, Sample, ziggurat, ziggurat_tables};
-
-/// A wrapper around an `f64` to generate N(0, 1) random numbers
-/// (a.k.a.  a standard normal, or Gaussian).
-///
-/// See `Normal` for the general normal distribution. That this has to
-/// be unwrapped before use as an `f64` (using either `*` or
-/// `mem::transmute` is safe).
-///
-/// Implemented via the ZIGNOR variant[1] of the Ziggurat method.
-///
-/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
-/// Generate Normal Random
-/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
-/// College, Oxford
-#[derive(Copy, Clone)]
-pub struct StandardNormal(pub f64);
-
-impl Rand for StandardNormal {
-    fn rand<R: Rng>(rng: &mut R) -> StandardNormal {
-        #[inline]
-        fn pdf(x: f64) -> f64 {
-            (-x * x / 2.0).exp()
-        }
-        #[inline]
-        fn zero_case<R: Rng>(rng: &mut R, u: f64) -> f64 {
-            // compute a random number in the tail by hand
-
-            // strange initial conditions, because the loop is not
-            // do-while, so the condition should be true on the first
-            // run, they get overwritten anyway (0 < 1, so these are
-            // good).
-            let mut x = 1.0f64;
-            let mut y = 0.0f64;
-
-            while -2.0 * y < x * x {
-                let Open01(x_) = rng.gen::<Open01<f64>>();
-                let Open01(y_) = rng.gen::<Open01<f64>>();
-
-                x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
-                y = y_.ln();
-            }
-
-            if u < 0.0 {
-                x - ziggurat_tables::ZIG_NORM_R
-            } else {
-                ziggurat_tables::ZIG_NORM_R - x
-            }
-        }
-
-        StandardNormal(ziggurat(rng,
-                                true, // this is symmetric
-                                &ziggurat_tables::ZIG_NORM_X,
-                                &ziggurat_tables::ZIG_NORM_F,
-                                pdf,
-                                zero_case))
-    }
-}
-
-impl fmt::Debug for StandardNormal {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("StandardNormal")
-         .field(&self.0)
-         .finish()
-    }
-}
-
-/// The normal distribution `N(mean, std_dev**2)`.
-///
-/// This uses the ZIGNOR variant of the Ziggurat method, see
-/// `StandardNormal` for more details.
-#[derive(Copy, Clone)]
-pub struct Normal {
-    mean: f64,
-    std_dev: f64,
-}
-
-impl Normal {
-    /// Construct a new `Normal` distribution with the given mean and
-    /// standard deviation.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `std_dev < 0`.
-    pub fn new(mean: f64, std_dev: f64) -> Normal {
-        assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0");
-        Normal {
-            mean,
-            std_dev,
-        }
-    }
-}
-
-impl Sample<f64> for Normal {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for Normal {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        let StandardNormal(n) = rng.gen::<StandardNormal>();
-        self.mean + self.std_dev * n
-    }
-}
-
-impl fmt::Debug for Normal {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Normal")
-         .field("mean", &self.mean)
-         .field("std_dev", &self.std_dev)
-         .finish()
-    }
-}
-
-
-/// The log-normal distribution `ln N(mean, std_dev**2)`.
-///
-/// If `X` is log-normal distributed, then `ln(X)` is `N(mean,
-/// std_dev**2)` distributed.
-#[derive(Copy, Clone)]
-pub struct LogNormal {
-    norm: Normal,
-}
-
-impl LogNormal {
-    /// Construct a new `LogNormal` distribution with the given mean
-    /// and standard deviation.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `std_dev < 0`.
-    pub fn new(mean: f64, std_dev: f64) -> LogNormal {
-        assert!(std_dev >= 0.0, "LogNormal::new called with `std_dev` < 0");
-        LogNormal { norm: Normal::new(mean, std_dev) }
-    }
-}
-
-impl Sample<f64> for LogNormal {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
-        self.ind_sample(rng)
-    }
-}
-
-impl IndependentSample<f64> for LogNormal {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
-        self.norm.ind_sample(rng).exp()
-    }
-}
-
-impl fmt::Debug for LogNormal {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("LogNormal")
-         .field("norm", &self.norm)
-         .finish()
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use distributions::{IndependentSample, Sample};
-    use super::{LogNormal, Normal};
-
-    #[test]
-    fn test_normal() {
-        let mut norm = Normal::new(10.0, 10.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            norm.sample(&mut rng);
-            norm.ind_sample(&mut rng);
-        }
-    }
-    #[test]
-    #[should_panic]
-    fn test_normal_invalid_sd() {
-        Normal::new(10.0, -1.0);
-    }
-
-
-    #[test]
-    fn test_log_normal() {
-        let mut lnorm = LogNormal::new(10.0, 10.0);
-        let mut rng = ::test::rng();
-        for _ in 0..1000 {
-            lnorm.sample(&mut rng);
-            lnorm.ind_sample(&mut rng);
-        }
-    }
-    #[test]
-    #[should_panic]
-    fn test_log_normal_invalid_sd() {
-        LogNormal::new(10.0, -1.0);
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-    use self::test::Bencher;
-    use std::mem::size_of;
-    use distributions::Sample;
-    use super::Normal;
-
-    #[bench]
-    fn rand_normal(b: &mut Bencher) {
-        let mut rng = ::test::weak_rng();
-        let mut normal = Normal::new(-2.71828, 3.14159);
-
-        b.iter(|| {
-            for _ in 0..::RAND_BENCH_N {
-                normal.sample(&mut rng);
-            }
-        });
-        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-    }
-}
diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs
deleted file mode 100644 (file)
index f2f8132..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Generating numbers between two others.
-
-// this is surprisingly complicated to be both generic & correct
-
-use core::fmt;
-use core::marker::Sized;
-use Rng;
-use distributions::{IndependentSample, Sample};
-
-/// Sample values uniformly between two bounds.
-///
-/// This gives a uniform distribution (assuming the RNG used to sample
-/// it is itself uniform & the `SampleRange` implementation for the
-/// given type is correct), even for edge cases like `low = 0`,
-/// `high = 170`, for which a naive modulo operation would return
-/// numbers less than 85 with double the probability to those greater
-/// than 85.
-///
-/// Types should attempt to sample in `[low, high)`, i.e., not
-/// including `high`, but this may be very difficult. All the
-/// primitive integer types satisfy this property, and the float types
-/// normally satisfy it, but rounding may mean `high` can occur.
-pub struct Range<X> {
-    low: X,
-    range: X,
-    accept_zone: X,
-}
-
-impl<X: SampleRange + PartialOrd> Range<X> {
-    /// Create a new `Range` instance that samples uniformly from
-    /// `[low, high)`. Panics if `low >= high`.
-    pub fn new(low: X, high: X) -> Range<X> {
-        assert!(low < high, "Range::new called with `low >= high`");
-        SampleRange::construct_range(low, high)
-    }
-}
-
-impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
-    #[inline]
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup {
-        self.ind_sample(rng)
-    }
-}
-
-impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
-    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
-        SampleRange::sample_range(self, rng)
-    }
-}
-
-impl<X: fmt::Debug> fmt::Debug for Range<X> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Range")
-         .field("low", &self.low)
-         .field("range", &self.range)
-         .field("accept_zone", &self.accept_zone)
-         .finish()
-    }
-}
-
-/// The helper trait for types that have a sensible way to sample
-/// uniformly between two values. This should not be used directly,
-/// and is only to facilitate `Range`.
-#[doc(hidden)]
-pub trait SampleRange: Sized {
-    /// Construct the `Range` object that `sample_range`
-    /// requires. This should not ever be called directly, only via
-    /// `Range::new`, which will check that `low < high`, so this
-    /// function doesn't have to repeat the check.
-    fn construct_range(low: Self, high: Self) -> Range<Self>;
-
-    /// Sample a value from the given `Range` with the given `Rng` as
-    /// a source of randomness.
-    fn sample_range<R: Rng>(r: &Range<Self>, rng: &mut R) -> Self;
-}
-
-macro_rules! integer_impl {
-    ($ty:ident, $unsigned:ident) => {
-        impl SampleRange for $ty {
-            // we play free and fast with unsigned vs signed here
-            // (when $ty is signed), but that's fine, since the
-            // contract of this macro is for $ty and $unsigned to be
-            // "bit-equal", so casting between them is a no-op & a
-            // bijection.
-
-            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
-                let range = (high as $unsigned).wrapping_sub(low as $unsigned);
-                let unsigned_max: $unsigned = $unsigned::max_value();
-
-                // this is the largest number that fits into $unsigned
-                // that `range` divides evenly, so, if we've sampled
-                // `n` uniformly from this region, then `n % range` is
-                // uniform in [0, range)
-                let zone = unsigned_max - unsigned_max % range;
-
-                Range {
-                    low,
-                    range: range as $ty,
-                    accept_zone: zone as $ty
-                }
-            }
-            #[inline]
-            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
-                loop {
-                    // rejection sample
-                    let v = rng.gen::<$unsigned>();
-                    // until we find something that fits into the
-                    // region which r.range evenly divides (this will
-                    // be uniformly distributed)
-                    if v < r.accept_zone as $unsigned {
-                        // and return it, with some adjustments
-                        return r.low.wrapping_add((v % r.range as $unsigned) as $ty);
-                    }
-                }
-            }
-        }
-    }
-}
-
-integer_impl! { i8, u8 }
-integer_impl! { i16, u16 }
-integer_impl! { i32, u32 }
-integer_impl! { i64, u64 }
-integer_impl! { isize, usize }
-integer_impl! { u8, u8 }
-integer_impl! { u16, u16 }
-integer_impl! { u32, u32 }
-integer_impl! { u64, u64 }
-integer_impl! { usize, usize }
-
-macro_rules! float_impl {
-    ($ty:ty) => {
-        impl SampleRange for $ty {
-            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
-                Range {
-                    low,
-                    range: high - low,
-                    accept_zone: 0.0 // unused
-                }
-            }
-            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
-                r.low + r.range * rng.gen::<$ty>()
-            }
-        }
-    }
-}
-
-float_impl! { f32 }
-float_impl! { f64 }
-
-#[cfg(test)]
-mod tests {
-    use distributions::{IndependentSample, Sample};
-    use super::Range;
-
-    #[should_panic]
-    #[test]
-    fn test_range_bad_limits_equal() {
-        Range::new(10, 10);
-    }
-    #[should_panic]
-    #[test]
-    fn test_range_bad_limits_flipped() {
-        Range::new(10, 5);
-    }
-
-    #[test]
-    fn test_integers() {
-        let mut rng = ::test::rng();
-        macro_rules! t {
-            ($($ty:ident),*) => {{
-                $(
-                   let v: &[($ty, $ty)] = &[(0, 10),
-                                            (10, 127),
-                                            ($ty::min_value(), $ty::max_value())];
-                   for &(low, high) in v {
-                        let mut sampler: Range<$ty> = Range::new(low, high);
-                        for _ in 0..1000 {
-                            let v = sampler.sample(&mut rng);
-                            assert!(low <= v && v < high);
-                            let v = sampler.ind_sample(&mut rng);
-                            assert!(low <= v && v < high);
-                        }
-                    }
-                 )*
-            }}
-        }
-        t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize)
-    }
-
-    #[test]
-    fn test_floats() {
-        let mut rng = ::test::rng();
-        macro_rules! t {
-            ($($ty:ty),*) => {{
-                $(
-                   let v: &[($ty, $ty)] = &[(0.0, 100.0),
-                                            (-1e35, -1e25),
-                                            (1e-35, 1e-25),
-                                            (-1e35, 1e35)];
-                   for &(low, high) in v {
-                        let mut sampler: Range<$ty> = Range::new(low, high);
-                        for _ in 0..1000 {
-                            let v = sampler.sample(&mut rng);
-                            assert!(low <= v && v < high);
-                            let v = sampler.ind_sample(&mut rng);
-                            assert!(low <= v && v < high);
-                        }
-                    }
-                 )*
-            }}
-        }
-
-        t!(f32, f64)
-    }
-
-}
diff --git a/src/librand/distributions/ziggurat_tables.rs b/src/librand/distributions/ziggurat_tables.rs
deleted file mode 100644 (file)
index 7dfb0f1..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Tables for distributions which are sampled using the ziggurat
-// algorithm. Autogenerated by `ziggurat_tables.py`.
-
-pub type ZigTable = &'static [f64; 257];
-pub const ZIG_NORM_R: f64 = 3.654152885361008796;
-#[rustfmt_skip]
-pub static ZIG_NORM_X: [f64; 257] =
-    [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
-     3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
-     2.978603279880844834, 2.934366867207854224, 2.894121053612348060, 2.857138730872132548,
-     2.822877396825325125, 2.790921174000785765, 2.760944005278822555, 2.732685359042827056,
-     2.705933656121858100, 2.680514643284522158, 2.656283037575502437, 2.633116393630324570,
-     2.610910518487548515, 2.589575986706995181, 2.569035452680536569, 2.549221550323460761,
-     2.530075232158516929, 2.511544441625342294, 2.493583041269680667, 2.476149939669143318,
-     2.459208374333311298, 2.442725318198956774, 2.426670984935725972, 2.411018413899685520,
-     2.395743119780480601, 2.380822795170626005, 2.366237056715818632, 2.351967227377659952,
-     2.337996148795031370, 2.324308018869623016, 2.310888250599850036, 2.297723348901329565,
-     2.284800802722946056, 2.272108990226823888, 2.259637095172217780, 2.247375032945807760,
-     2.235313384928327984, 2.223443340090905718, 2.211756642882544366, 2.200245546609647995,
-     2.188902771624720689, 2.177721467738641614, 2.166695180352645966, 2.155817819875063268,
-     2.145083634046203613, 2.134487182844320152, 2.124023315687815661, 2.113687150684933957,
-     2.103474055713146829, 2.093379631137050279, 2.083399693996551783, 2.073530263516978778,
-     2.063767547809956415, 2.054107931648864849, 2.044547965215732788, 2.035084353727808715,
-     2.025713947862032960, 2.016433734904371722, 2.007240830558684852, 1.998132471356564244,
-     1.989106007615571325, 1.980158896898598364, 1.971288697931769640, 1.962493064942461896,
-     1.953769742382734043, 1.945116560006753925, 1.936531428273758904, 1.928012334050718257,
-     1.919557336591228847, 1.911164563769282232, 1.902832208548446369, 1.894558525668710081,
-     1.886341828534776388, 1.878180486290977669, 1.870072921069236838, 1.862017605397632281,
-     1.854013059758148119, 1.846057850283119750, 1.838150586580728607, 1.830289919680666566,
-     1.822474540091783224, 1.814703175964167636, 1.806974591348693426, 1.799287584547580199,
-     1.791640986550010028, 1.784033659547276329, 1.776464495522344977, 1.768932414909077933,
-     1.761436365316706665, 1.753975320315455111, 1.746548278279492994, 1.739154261283669012,
-     1.731792314050707216, 1.724461502945775715, 1.717160915015540690, 1.709889657069006086,
-     1.702646854797613907, 1.695431651932238548, 1.688243209434858727, 1.681080704722823338,
-     1.673943330923760353, 1.666830296159286684, 1.659740822855789499, 1.652674147080648526,
-     1.645629517902360339, 1.638606196773111146, 1.631603456932422036, 1.624620582830568427,
-     1.617656869570534228, 1.610711622367333673, 1.603784156023583041, 1.596873794420261339,
-     1.589979870021648534, 1.583101723393471438, 1.576238702733332886, 1.569390163412534456,
-     1.562555467528439657, 1.555733983466554893, 1.548925085471535512, 1.542128153226347553,
-     1.535342571438843118, 1.528567729435024614, 1.521803020758293101, 1.515047842773992404,
-     1.508301596278571965, 1.501563685112706548, 1.494833515777718391, 1.488110497054654369,
-     1.481394039625375747, 1.474683555695025516, 1.467978458615230908, 1.461278162507407830,
-     1.454582081885523293, 1.447889631277669675, 1.441200224845798017, 1.434513276002946425,
-     1.427828197027290358, 1.421144398672323117, 1.414461289772464658, 1.407778276843371534,
-     1.401094763676202559, 1.394410150925071257, 1.387723835686884621, 1.381035211072741964,
-     1.374343665770030531, 1.367648583594317957, 1.360949343030101844, 1.354245316759430606,
-     1.347535871177359290, 1.340820365893152122, 1.334098153216083604, 1.327368577624624679,
-     1.320630975217730096, 1.313884673146868964, 1.307128989027353860, 1.300363230327433728,
-     1.293586693733517645, 1.286798664489786415, 1.279998415710333237, 1.273185207661843732,
-     1.266358287014688333, 1.259516886060144225, 1.252660221891297887, 1.245787495544997903,
-     1.238897891102027415, 1.231990574742445110, 1.225064693752808020, 1.218119375481726552,
-     1.211153726239911244, 1.204166830140560140, 1.197157747875585931, 1.190125515422801650,
-     1.183069142678760732, 1.175987612011489825, 1.168879876726833800, 1.161744859441574240,
-     1.154581450355851802, 1.147388505416733873, 1.140164844363995789, 1.132909248648336975,
-     1.125620459211294389, 1.118297174115062909, 1.110938046009249502, 1.103541679420268151,
-     1.096106627847603487, 1.088631390649514197, 1.081114409698889389, 1.073554065787871714,
-     1.065948674757506653, 1.058296483326006454, 1.050595664586207123, 1.042844313139370538,
-     1.035040439828605274, 1.027181966030751292, 1.019266717460529215, 1.011292417434978441,
-     1.003256679539591412, 0.995156999629943084, 0.986990747093846266, 0.978755155288937750,
-     0.970447311058864615, 0.962064143217605250, 0.953602409875572654, 0.945058684462571130,
-     0.936429340280896860, 0.927710533396234771, 0.918898183643734989, 0.909987953490768997,
-     0.900975224455174528, 0.891855070726792376, 0.882622229578910122, 0.873271068082494550,
-     0.863795545546826915, 0.854189171001560554, 0.844444954902423661, 0.834555354079518752,
-     0.824512208745288633, 0.814306670128064347, 0.803929116982664893, 0.793369058833152785,
-     0.782615023299588763, 0.771654424216739354, 0.760473406422083165, 0.749056662009581653,
-     0.737387211425838629, 0.725446140901303549, 0.713212285182022732, 0.700661841097584448,
-     0.687767892786257717, 0.674499822827436479, 0.660822574234205984, 0.646695714884388928,
-     0.632072236375024632, 0.616896989996235545, 0.601104617743940417, 0.584616766093722262,
-     0.567338257040473026, 0.549151702313026790, 0.529909720646495108, 0.509423329585933393,
-     0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746,
-     0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806,
-     0.000000000000000000];
-#[rustfmt_skip]
-pub static ZIG_NORM_F: [f64; 257] =
-    [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872,
-     0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100,
-     0.011842757857943104, 0.013497450601780807, 0.015177088307982072, 0.016880083152595839,
-     0.018605121275783350, 0.020351096230109354, 0.022117062707379922, 0.023902203305873237,
-     0.025705804008632656, 0.027527235669693315, 0.029365939758230111, 0.031221417192023690,
-     0.033093219458688698, 0.034980941461833073, 0.036884215688691151, 0.038802707404656918,
-     0.040736110656078753, 0.042684144916619378, 0.044646552251446536, 0.046623094902089664,
-     0.048613553216035145, 0.050617723861121788, 0.052635418276973649, 0.054666461325077916,
-     0.056710690106399467, 0.058767952921137984, 0.060838108349751806, 0.062921024437977854,
-     0.065016577971470438, 0.067124653828023989, 0.069245144397250269, 0.071377949059141965,
-     0.073522973714240991, 0.075680130359194964, 0.077849336702372207, 0.080030515814947509,
-     0.082223595813495684, 0.084428509570654661, 0.086645194450867782, 0.088873592068594229,
-     0.091113648066700734, 0.093365311913026619, 0.095628536713353335, 0.097903279039215627,
-     0.100189498769172020, 0.102487158942306270, 0.104796225622867056, 0.107116667775072880,
-     0.109448457147210021, 0.111791568164245583, 0.114145977828255210, 0.116511665626037014,
-     0.118888613443345698, 0.121276805485235437, 0.123676228202051403, 0.126086870220650349,
-     0.128508722280473636, 0.130941777174128166, 0.133386029692162844, 0.135841476571757352,
-     0.138308116449064322, 0.140785949814968309, 0.143274978974047118, 0.145775208006537926,
-     0.148286642733128721, 0.150809290682410169, 0.153343161060837674, 0.155888264725064563,
-     0.158444614156520225, 0.161012223438117663, 0.163591108232982951, 0.166181285765110071,
-     0.168782774801850333, 0.171395595638155623, 0.174019770082499359, 0.176655321444406654,
-     0.179302274523530397, 0.181960655600216487, 0.184630492427504539, 0.187311814224516926,
-     0.190004651671193070, 0.192709036904328807, 0.195425003514885592, 0.198152586546538112,
-     0.200891822495431333, 0.203642749311121501, 0.206405406398679298, 0.209179834621935651,
-     0.211966076307852941, 0.214764175252008499, 0.217574176725178370, 0.220396127481011589,
-     0.223230075764789593, 0.226076071323264877, 0.228934165415577484, 0.231804410825248525,
-     0.234686861873252689, 0.237581574432173676, 0.240488605941449107, 0.243408015423711988,
-     0.246339863502238771, 0.249284212419516704, 0.252241126056943765, 0.255210669955677150,
-     0.258192911338648023, 0.261187919133763713, 0.264195763998317568, 0.267216518344631837,
-     0.270250256366959984, 0.273297054069675804, 0.276356989296781264, 0.279430141762765316,
-     0.282516593084849388, 0.285616426816658109, 0.288729728483353931, 0.291856585618280984,
-     0.294997087801162572, 0.298151326697901342, 0.301319396102034120, 0.304501391977896274,
-     0.307697412505553769, 0.310907558127563710, 0.314131931597630143, 0.317370638031222396,
-     0.320623784958230129, 0.323891482377732021, 0.327173842814958593, 0.330470981380537099,
-     0.333783015832108509, 0.337110066638412809, 0.340452257045945450, 0.343809713148291340,
-     0.347182563958251478, 0.350570941482881204, 0.353974980801569250, 0.357394820147290515,
-     0.360830600991175754, 0.364282468130549597, 0.367750569780596226, 0.371235057669821344,
-     0.374736087139491414, 0.378253817247238111, 0.381788410875031348, 0.385340034841733958,
-     0.388908860020464597, 0.392495061461010764, 0.396098818517547080, 0.399720314981931668,
-     0.403359739222868885, 0.407017284331247953, 0.410693148271983222, 0.414387534042706784,
-     0.418100649839684591, 0.421832709231353298, 0.425583931339900579, 0.429354541031341519,
-     0.433144769114574058, 0.436954852549929273, 0.440785034667769915, 0.444635565397727750,
-     0.448506701509214067, 0.452398706863882505, 0.456311852680773566, 0.460246417814923481,
-     0.464202689050278838, 0.468180961407822172, 0.472181538469883255, 0.476204732721683788,
-     0.480250865911249714, 0.484320269428911598, 0.488413284707712059, 0.492530263646148658,
-     0.496671569054796314, 0.500837575128482149, 0.505028667945828791, 0.509245245998136142,
-     0.513487720749743026, 0.517756517232200619, 0.522052074674794864, 0.526374847174186700,
-     0.530725304406193921, 0.535103932383019565, 0.539511234259544614, 0.543947731192649941,
-     0.548413963257921133, 0.552910490428519918, 0.557437893621486324, 0.561996775817277916,
-     0.566587763258951771, 0.571211506738074970, 0.575868682975210544, 0.580559996103683473,
-     0.585286179266300333, 0.590047996335791969, 0.594846243770991268, 0.599681752622167719,
-     0.604555390700549533, 0.609468064928895381, 0.614420723892076803, 0.619414360609039205,
-     0.624450015550274240, 0.629528779928128279, 0.634651799290960050, 0.639820277456438991,
-     0.645035480824251883, 0.650298743114294586, 0.655611470583224665, 0.660975147780241357,
-     0.666391343912380640, 0.671861719900766374, 0.677388036222513090, 0.682972161648791376,
-     0.688616083008527058, 0.694321916130032579, 0.700091918140490099, 0.705928501336797409,
-     0.711834248882358467, 0.717811932634901395, 0.723864533472881599, 0.729995264565802437,
-     0.736207598131266683, 0.742505296344636245, 0.748892447223726720, 0.755373506511754500,
-     0.761953346841546475, 0.768637315803334831, 0.775431304986138326, 0.782341832659861902,
-     0.789376143571198563, 0.796542330428254619, 0.803849483176389490, 0.811307874318219935,
-     0.818929191609414797, 0.826726833952094231, 0.834716292992930375, 0.842915653118441077,
-     0.851346258465123684, 0.860033621203008636, 0.869008688043793165, 0.878309655816146839,
-     0.887984660763399880, 0.898095921906304051, 0.908726440060562912, 0.919991505048360247,
-     0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
-     1.000000000000000000];
-pub const ZIG_EXP_R: f64 = 7.697117470131050077;
-#[rustfmt_skip]
-pub static ZIG_EXP_X: [f64; 257] =
-    [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
-     6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
-     5.323090505754398016, 5.181487281301500047, 5.054288489981304089, 4.938777085901250530,
-     4.832939741025112035, 4.735242996601741083, 4.644491885420085175, 4.559737061707351380,
-     4.480211746528421912, 4.405287693473573185, 4.334443680317273007, 4.267242480277365857,
-     4.203313713735184365, 4.142340865664051464, 4.084051310408297830, 4.028208544647936762,
-     3.974606066673788796, 3.923062500135489739, 3.873417670399509127, 3.825529418522336744,
-     3.779270992411667862, 3.734528894039797375, 3.691201090237418825, 3.649195515760853770,
-     3.608428813128909507, 3.568825265648337020, 3.530315889129343354, 3.492837654774059608,
-     3.456332821132760191, 3.420748357251119920, 3.386035442460300970, 3.352149030900109405,
-     3.319047470970748037, 3.286692171599068679, 3.255047308570449882, 3.224079565286264160,
-     3.193757903212240290, 3.164053358025972873, 3.134938858084440394, 3.106389062339824481,
-     3.078380215254090224, 3.050890016615455114, 3.023897504455676621, 2.997382949516130601,
-     2.971327759921089662, 2.945714394895045718, 2.920526286512740821, 2.895747768600141825,
-     2.871364012015536371, 2.847360965635188812, 2.823725302450035279, 2.800444370250737780,
-     2.777506146439756574, 2.754899196562344610, 2.732612636194700073, 2.710636095867928752,
-     2.688959688741803689, 2.667573980773266573, 2.646469963151809157, 2.625639026797788489,
-     2.605072938740835564, 2.584763820214140750, 2.564704126316905253, 2.544886627111869970,
-     2.525304390037828028, 2.505950763528594027, 2.486819361740209455, 2.467904050297364815,
-     2.449198932978249754, 2.430698339264419694, 2.412396812688870629, 2.394289099921457886,
-     2.376370140536140596, 2.358635057409337321, 2.341079147703034380, 2.323697874390196372,
-     2.306486858283579799, 2.289441870532269441, 2.272558825553154804, 2.255833774367219213,
-     2.239262898312909034, 2.222842503111036816, 2.206569013257663858, 2.190438966723220027,
-     2.174449009937774679, 2.158595893043885994, 2.142876465399842001, 2.127287671317368289,
-     2.111826546019042183, 2.096490211801715020, 2.081275874393225145, 2.066180819490575526,
-     2.051202409468584786, 2.036338080248769611, 2.021585338318926173, 2.006941757894518563,
-     1.992404978213576650, 1.977972700957360441, 1.963642687789548313, 1.949412758007184943,
-     1.935280786297051359, 1.921244700591528076, 1.907302480018387536, 1.893452152939308242,
-     1.879691795072211180, 1.866019527692827973, 1.852433515911175554, 1.838931967018879954,
-     1.825513128903519799, 1.812175288526390649, 1.798916770460290859, 1.785735935484126014,
-     1.772631179231305643, 1.759600930889074766, 1.746643651946074405, 1.733757834985571566,
-     1.720942002521935299, 1.708194705878057773, 1.695514524101537912, 1.682900062917553896,
-     1.670349953716452118, 1.657862852574172763, 1.645437439303723659, 1.633072416535991334,
-     1.620766508828257901, 1.608518461798858379, 1.596327041286483395, 1.584191032532688892,
-     1.572109239386229707, 1.560080483527888084, 1.548103603714513499, 1.536177455041032092,
-     1.524300908219226258, 1.512472848872117082, 1.500692176842816750, 1.488957805516746058,
-     1.477268661156133867, 1.465623682245745352, 1.454021818848793446, 1.442462031972012504,
-     1.430943292938879674, 1.419464582769983219, 1.408024891569535697, 1.396623217917042137,
-     1.385258568263121992, 1.373929956328490576, 1.362636402505086775, 1.351376933258335189,
-     1.340150580529504643, 1.328956381137116560, 1.317793376176324749, 1.306660610415174117,
-     1.295557131686601027, 1.284481990275012642, 1.273434238296241139, 1.262412929069615330,
-     1.251417116480852521, 1.240445854334406572, 1.229498195693849105, 1.218573192208790124,
-     1.207669893426761121, 1.196787346088403092, 1.185924593404202199, 1.175080674310911677,
-     1.164254622705678921, 1.153445466655774743, 1.142652227581672841, 1.131873919411078511,
-     1.121109547701330200, 1.110358108727411031, 1.099618588532597308, 1.088889961938546813,
-     1.078171191511372307, 1.067461226479967662, 1.056759001602551429, 1.046063435977044209,
-     1.035373431790528542, 1.024687873002617211, 1.014005623957096480, 1.003325527915696735,
-     0.992646405507275897, 0.981967053085062602, 0.971286240983903260, 0.960602711668666509,
-     0.949915177764075969, 0.939222319955262286, 0.928522784747210395, 0.917815182070044311,
-     0.907098082715690257, 0.896370015589889935, 0.885629464761751528, 0.874874866291025066,
-     0.864104604811004484, 0.853317009842373353, 0.842510351810368485, 0.831682837734273206,
-     0.820832606554411814, 0.809957724057418282, 0.799056177355487174, 0.788125868869492430,
-     0.777164609759129710, 0.766170112735434672, 0.755139984181982249, 0.744071715500508102,
-     0.732962673584365398, 0.721810090308756203, 0.710611050909655040, 0.699362481103231959,
-     0.688061132773747808, 0.676703568029522584, 0.665286141392677943, 0.653804979847664947,
-     0.642255960424536365, 0.630634684933490286, 0.618936451394876075, 0.607156221620300030,
-     0.595288584291502887, 0.583327712748769489, 0.571267316532588332, 0.559100585511540626,
-     0.546820125163310577, 0.534417881237165604, 0.521885051592135052, 0.509211982443654398,
-     0.496388045518671162, 0.483401491653461857, 0.470239275082169006, 0.456886840931420235,
-     0.443327866073552401, 0.429543940225410703, 0.415514169600356364, 0.401214678896277765,
-     0.386617977941119573, 0.371692145329917234, 0.356399760258393816, 0.340696481064849122,
-     0.324529117016909452, 0.307832954674932158, 0.290527955491230394, 0.272513185478464703,
-     0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842,
-     0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570,
-     0.000000000000000000];
-#[rustfmt_skip]
-pub static ZIG_EXP_F: [f64; 257] =
-    [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573,
-     0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797,
-     0.004877655983542396, 0.005619642207205489, 0.006381905937319183, 0.007163353183634991,
-     0.007963077438017043, 0.008780314985808977, 0.009614413642502212, 0.010464810181029981,
-     0.011331013597834600, 0.012212592426255378, 0.013109164931254991, 0.014020391403181943,
-     0.014945968011691148, 0.015885621839973156, 0.016839106826039941, 0.017806200410911355,
-     0.018786700744696024, 0.019780424338009740, 0.020787204072578114, 0.021806887504283581,
-     0.022839335406385240, 0.023884420511558174, 0.024942026419731787, 0.026012046645134221,
-     0.027094383780955803, 0.028188948763978646, 0.029295660224637411, 0.030414443910466622,
-     0.031545232172893622, 0.032687963508959555, 0.033842582150874358, 0.035009037697397431,
-     0.036187284781931443, 0.037377282772959382, 0.038578995503074871, 0.039792391023374139,
-     0.041017441380414840, 0.042254122413316254, 0.043502413568888197, 0.044762297732943289,
-     0.046033761076175184, 0.047316792913181561, 0.048611385573379504, 0.049917534282706379,
-     0.051235237055126281, 0.052564494593071685, 0.053905310196046080, 0.055257689676697030,
-     0.056621641283742870, 0.057997175631200659, 0.059384305633420280, 0.060783046445479660,
-     0.062193415408541036, 0.063615431999807376, 0.065049117786753805, 0.066494496385339816,
-     0.067951593421936643, 0.069420436498728783, 0.070901055162371843, 0.072393480875708752,
-     0.073897746992364746, 0.075413888734058410, 0.076941943170480517, 0.078481949201606435,
-     0.080033947542319905, 0.081597980709237419, 0.083174093009632397, 0.084762330532368146,
-     0.086362741140756927, 0.087975374467270231, 0.089600281910032886, 0.091237516631040197,
-     0.092887133556043569, 0.094549189376055873, 0.096223742550432825, 0.097910853311492213,
-     0.099610583670637132, 0.101322997425953631, 0.103048160171257702, 0.104786139306570145,
-     0.106537004050001632, 0.108300825451033755, 0.110077676405185357, 0.111867631670056283,
-     0.113670767882744286, 0.115487163578633506, 0.117316899211555525, 0.119160057175327641,
-     0.121016721826674792, 0.122886979509545108, 0.124770918580830933, 0.126668629437510671,
-     0.128580204545228199, 0.130505738468330773, 0.132445327901387494, 0.134399071702213602,
-     0.136367070926428829, 0.138349428863580176, 0.140346251074862399, 0.142357645432472146,
-     0.144383722160634720, 0.146424593878344889, 0.148480375643866735, 0.150551185001039839,
-     0.152637142027442801, 0.154738369384468027, 0.156854992369365148, 0.158987138969314129,
-     0.161134939917591952, 0.163298528751901734, 0.165478041874935922, 0.167673618617250081,
-     0.169885401302527550, 0.172113535315319977, 0.174358169171353411, 0.176619454590494829,
-     0.178897546572478278, 0.181192603475496261, 0.183504787097767436, 0.185834262762197083,
-     0.188181199404254262, 0.190545769663195363, 0.192928149976771296, 0.195328520679563189,
-     0.197747066105098818, 0.200183974691911210, 0.202639439093708962, 0.205113656293837654,
-     0.207606827724221982, 0.210119159388988230, 0.212650861992978224, 0.215202151075378628,
-     0.217773247148700472, 0.220364375843359439, 0.222975768058120111, 0.225607660116683956,
-     0.228260293930716618, 0.230933917169627356, 0.233628783437433291, 0.236345152457059560,
-     0.239083290262449094, 0.241843469398877131, 0.244625969131892024, 0.247431075665327543,
-     0.250259082368862240, 0.253110290015629402, 0.255985007030415324, 0.258883549749016173,
-     0.261806242689362922, 0.264753418835062149, 0.267725419932044739, 0.270722596799059967,
-     0.273745309652802915, 0.276793928448517301, 0.279868833236972869, 0.282970414538780746,
-     0.286099073737076826, 0.289255223489677693, 0.292439288161892630, 0.295651704281261252,
-     0.298892921015581847, 0.302163400675693528, 0.305463619244590256, 0.308794066934560185,
-     0.312155248774179606, 0.315547685227128949, 0.318971912844957239, 0.322428484956089223,
-     0.325917972393556354, 0.329440964264136438, 0.332998068761809096, 0.336589914028677717,
-     0.340217149066780189, 0.343880444704502575, 0.347580494621637148, 0.351318016437483449,
-     0.355093752866787626, 0.358908472948750001, 0.362762973354817997, 0.366658079781514379,
-     0.370594648435146223, 0.374573567615902381, 0.378595759409581067, 0.382662181496010056,
-     0.386773829084137932, 0.390931736984797384, 0.395136981833290435, 0.399390684475231350,
-     0.403694012530530555, 0.408048183152032673, 0.412454465997161457, 0.416914186433003209,
-     0.421428728997616908, 0.425999541143034677, 0.430628137288459167, 0.435316103215636907,
-     0.440065100842354173, 0.444876873414548846, 0.449753251162755330, 0.454696157474615836,
-     0.459707615642138023, 0.464789756250426511, 0.469944825283960310, 0.475175193037377708,
-     0.480483363930454543, 0.485871987341885248, 0.491343869594032867, 0.496901987241549881,
-     0.502549501841348056, 0.508289776410643213, 0.514126393814748894, 0.520063177368233931,
-     0.526104213983620062, 0.532253880263043655, 0.538516872002862246, 0.544898237672440056,
-     0.551403416540641733, 0.558038282262587892, 0.564809192912400615, 0.571723048664826150,
-     0.578787358602845359, 0.586010318477268366, 0.593400901691733762, 0.600968966365232560,
-     0.608725382079622346, 0.616682180915207878, 0.624852738703666200, 0.633251994214366398,
-     0.641896716427266423, 0.650805833414571433, 0.660000841079000145, 0.669506316731925177,
-     0.679350572264765806, 0.689566496117078431, 0.700192655082788606, 0.711274760805076456,
-     0.722867659593572465, 0.735038092431424039, 0.747868621985195658, 0.761463388849896838,
-     0.775956852040116218, 0.791527636972496285, 0.808421651523009044, 0.826993296643051101,
-     0.847785500623990496, 0.871704332381204705, 0.900469929925747703, 0.938143680862176477,
-     1.000000000000000000];
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
deleted file mode 100644 (file)
index 17ecf79..0000000
+++ /dev/null
@@ -1,746 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The ISAAC random number generator.
-
-#![allow(non_camel_case_types)]
-
-use core::fmt;
-use core::slice;
-use core::iter::repeat;
-use core::num::Wrapping as w;
-
-use {Rand, Rng, SeedableRng};
-
-type w32 = w<u32>;
-type w64 = w<u64>;
-
-const RAND_SIZE_LEN: usize = 8;
-const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
-const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN;
-
-/// A random number generator that uses the ISAAC algorithm[1].
-///
-/// The ISAAC algorithm is generally accepted as suitable for
-/// cryptographic purposes, but this implementation has not be
-/// verified as such. Prefer a generator like `OsRng` that defers to
-/// the operating system for cases that need high security.
-///
-/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
-/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
-#[derive(Copy)]
-pub struct IsaacRng {
-    cnt: u32,
-    rsl: [w32; RAND_SIZE_USIZE],
-    mem: [w32; RAND_SIZE_USIZE],
-    a: w32,
-    b: w32,
-    c: w32,
-}
-
-impl fmt::Debug for IsaacRng {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("IsaacRng")
-         .field("cnt", &self.cnt)
-         .field("rsl", &self.rsl.iter())
-         .field("mem", &self.mem.iter())
-         .field("a", &self.a)
-         .field("b", &self.b)
-         .field("c", &self.c)
-         .finish()
-    }
-}
-
-static EMPTY: IsaacRng = IsaacRng {
-    cnt: 0,
-    rsl: [w(0); RAND_SIZE_USIZE],
-    mem: [w(0); RAND_SIZE_USIZE],
-    a: w(0),
-    b: w(0),
-    c: w(0),
-};
-
-impl IsaacRng {
-    /// Create an ISAAC random number generator using the default
-    /// fixed seed.
-    pub fn new_unseeded() -> IsaacRng {
-        let mut rng = EMPTY;
-        rng.init(false);
-        rng
-    }
-
-    /// Initializes `self`. If `use_rsl` is true, then use the current value
-    /// of `rsl` as a seed, otherwise construct one algorithmically (not
-    /// randomly).
-    fn init(&mut self, use_rsl: bool) {
-        let mut a = w(0x9e3779b9);
-        let mut b = a;
-        let mut c = a;
-        let mut d = a;
-        let mut e = a;
-        let mut f = a;
-        let mut g = a;
-        let mut h = a;
-
-        macro_rules! mix {
-            () => {{
-                a = a ^ (b << 11);
-                d = d + a;
-                b = b + c;
-
-                b = b ^ (c >> 2);
-                e = e + b;
-                c = c + d;
-
-                c = c ^ (d << 8);
-                f = f + c;
-                d = d + e;
-
-                d = d ^ (e >> 16);
-                g = g + d;
-                e = e + f;
-
-                e = e ^ (f << 10);
-                h = h + e;
-                f = f + g;
-
-                f = f ^ (g >> 4);
-                a = a + f;
-                g = g + h;
-
-                g = g ^ (h << 8);
-                b = b + g;
-                h = h + a;
-
-                h = h ^ (a >> 9);
-                c = c + h;
-                a = a + b;
-            }}
-        }
-
-        for _ in 0..4 {
-            mix!();
-        }
-
-        if use_rsl {
-            macro_rules! memloop {
-                ($arr:expr) => {{
-                    for i in (0..RAND_SIZE_USIZE).step_by(8) {
-                        a = a + $arr[i];
-                        b = b + $arr[i + 1];
-                        c = c + $arr[i + 2];
-                        d = d + $arr[i + 3];
-                        e = e + $arr[i + 4];
-                        f = f + $arr[i + 5];
-                        g = g + $arr[i + 6];
-                        h = h + $arr[i + 7];
-                        mix!();
-                        self.mem[i] = a;
-                        self.mem[i + 1] = b;
-                        self.mem[i + 2] = c;
-                        self.mem[i + 3] = d;
-                        self.mem[i + 4] = e;
-                        self.mem[i + 5] = f;
-                        self.mem[i + 6] = g;
-                        self.mem[i + 7] = h;
-                    }
-                }}
-            }
-
-            memloop!(self.rsl);
-            memloop!(self.mem);
-        } else {
-            for i in (0..RAND_SIZE_USIZE).step_by(8) {
-                mix!();
-                self.mem[i] = a;
-                self.mem[i + 1] = b;
-                self.mem[i + 2] = c;
-                self.mem[i + 3] = d;
-                self.mem[i + 4] = e;
-                self.mem[i + 5] = f;
-                self.mem[i + 6] = g;
-                self.mem[i + 7] = h;
-            }
-        }
-
-        self.isaac();
-    }
-
-    /// Refills the output buffer (`self.rsl`)
-    #[inline]
-    fn isaac(&mut self) {
-        self.c = self.c + w(1);
-        // abbreviations
-        let mut a = self.a;
-        let mut b = self.b + self.c;
-
-        const MIDPOINT: usize = RAND_SIZE_USIZE / 2;
-
-        macro_rules! ind {
-            ($x:expr) => (self.mem[($x >> 2).0 as usize & (RAND_SIZE_USIZE - 1)] )
-        }
-
-        let r = [(0, MIDPOINT), (MIDPOINT, 0)];
-        for &(mr_offset, m2_offset) in &r {
-
-            macro_rules! rngstepp {
-                ($j:expr, $shift:expr) => {{
-                    let base = $j;
-                    let mix = a << $shift;
-
-                    let x = self.mem[base  + mr_offset];
-                    a = (a ^ mix) + self.mem[base + m2_offset];
-                    let y = ind!(x) + a + b;
-                    self.mem[base + mr_offset] = y;
-
-                    b = ind!(y >> RAND_SIZE_LEN) + x;
-                    self.rsl[base + mr_offset] = b;
-                }}
-            }
-
-            macro_rules! rngstepn {
-                ($j:expr, $shift:expr) => {{
-                    let base = $j;
-                    let mix = a >> $shift;
-
-                    let x = self.mem[base  + mr_offset];
-                    a = (a ^ mix) + self.mem[base + m2_offset];
-                    let y = ind!(x) + a + b;
-                    self.mem[base + mr_offset] = y;
-
-                    b = ind!(y >> RAND_SIZE_LEN) + x;
-                    self.rsl[base + mr_offset] = b;
-                }}
-            }
-
-            for i in (0..MIDPOINT).step_by(4) {
-                rngstepp!(i + 0, 13);
-                rngstepn!(i + 1, 6);
-                rngstepp!(i + 2, 2);
-                rngstepn!(i + 3, 16);
-            }
-        }
-
-        self.a = a;
-        self.b = b;
-        self.cnt = RAND_SIZE;
-    }
-}
-
-// Cannot be derived because [u32; 256] does not implement Clone
-impl Clone for IsaacRng {
-    fn clone(&self) -> IsaacRng {
-        *self
-    }
-}
-
-impl Rng for IsaacRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        if self.cnt == 0 {
-            // make some more numbers
-            self.isaac();
-        }
-        self.cnt -= 1;
-
-        // self.cnt is at most RAND_SIZE, but that is before the
-        // subtraction above. We want to index without bounds
-        // checking, but this could lead to incorrect code if someone
-        // misrefactors, so we check, sometimes.
-        //
-        // (Changes here should be reflected in Isaac64Rng.next_u64.)
-        debug_assert!(self.cnt < RAND_SIZE);
-
-        // (the % is cheaply telling the optimiser that we're always
-        // in bounds, without unsafe. NB. this is a power of two, so
-        // it optimises to a bitwise mask).
-        self.rsl[(self.cnt % RAND_SIZE) as usize].0
-    }
-}
-
-impl<'a> SeedableRng<&'a [u32]> for IsaacRng {
-    fn reseed(&mut self, seed: &'a [u32]) {
-        // make the seed into [seed[0], seed[1], ..., seed[seed.len()
-        // - 1], 0, 0, ...], to fill rng.rsl.
-        let seed_iter = seed.iter().cloned().chain(repeat(0));
-
-        for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
-            *rsl_elem = w(seed_elem);
-        }
-        self.cnt = 0;
-        self.a = w(0);
-        self.b = w(0);
-        self.c = w(0);
-
-        self.init(true);
-    }
-
-    /// Create an ISAAC random number generator with a seed. This can
-    /// be any length, although the maximum number of elements used is
-    /// 256 and any more will be silently ignored. A generator
-    /// constructed with a given seed will generate the same sequence
-    /// of values as all other generators constructed with that seed.
-    fn from_seed(seed: &'a [u32]) -> IsaacRng {
-        let mut rng = EMPTY;
-        rng.reseed(seed);
-        rng
-    }
-}
-
-impl Rand for IsaacRng {
-    fn rand<R: Rng>(other: &mut R) -> IsaacRng {
-        let mut ret = EMPTY;
-        unsafe {
-            let ptr = ret.rsl.as_mut_ptr() as *mut u8;
-
-            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_USIZE * 4);
-            other.fill_bytes(slice);
-        }
-        ret.cnt = 0;
-        ret.a = w(0);
-        ret.b = w(0);
-        ret.c = w(0);
-
-        ret.init(true);
-        return ret;
-    }
-}
-
-const RAND_SIZE_64_LEN: usize = 8;
-const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN;
-
-/// A random number generator that uses ISAAC-64[1], the 64-bit
-/// variant of the ISAAC algorithm.
-///
-/// The ISAAC algorithm is generally accepted as suitable for
-/// cryptographic purposes, but this implementation has not be
-/// verified as such. Prefer a generator like `OsRng` that defers to
-/// the operating system for cases that need high security.
-///
-/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
-/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
-#[derive(Copy)]
-pub struct Isaac64Rng {
-    cnt: usize,
-    rsl: [w64; RAND_SIZE_64],
-    mem: [w64; RAND_SIZE_64],
-    a: w64,
-    b: w64,
-    c: w64,
-}
-
-impl fmt::Debug for Isaac64Rng {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Isaac64Rng")
-         .field("cnt", &self.cnt)
-         .field("rsl", &self.rsl.iter())
-         .field("mem", &self.mem.iter())
-         .field("a", &self.a)
-         .field("b", &self.b)
-         .field("c", &self.c)
-         .finish()
-    }
-}
-
-static EMPTY_64: Isaac64Rng = Isaac64Rng {
-    cnt: 0,
-    rsl: [w(0); RAND_SIZE_64],
-    mem: [w(0); RAND_SIZE_64],
-    a: w(0),
-    b: w(0),
-    c: w(0),
-};
-
-impl Isaac64Rng {
-    /// Create a 64-bit ISAAC random number generator using the
-    /// default fixed seed.
-    pub fn new_unseeded() -> Isaac64Rng {
-        let mut rng = EMPTY_64;
-        rng.init(false);
-        rng
-    }
-
-    /// Initializes `self`. If `use_rsl` is true, then use the current value
-    /// of `rsl` as a seed, otherwise construct one algorithmically (not
-    /// randomly).
-    fn init(&mut self, use_rsl: bool) {
-        macro_rules! init {
-            ($var:ident) => (
-                let mut $var = w(0x9e3779b97f4a7c13);
-            )
-        }
-        init!(a);
-        init!(b);
-        init!(c);
-        init!(d);
-        init!(e);
-        init!(f);
-        init!(g);
-        init!(h);
-
-        macro_rules! mix {
-            () => {{
-                a = a - e;
-                f = f ^ (h >> 9);
-                h = h + a;
-
-                b = b - f;
-                g = g ^ (a << 9);
-                a = a + b;
-
-                c = c - g;
-                h = h ^ (b >> 23);
-                b = b + c;
-
-                d = d - h;
-                a = a ^ (c << 15);
-                c = c + d;
-
-                e = e - a;
-                b = b ^ (d >> 14);
-                d = d + e;
-
-                f = f - b;
-                c = c ^ (e << 20);
-                e = e + f;
-
-                g = g - c;
-                d = d ^ (f >> 17);
-                f = f + g;
-
-                h = h - d;
-                e = e ^ (g << 14);
-                g = g + h;
-            }}
-        }
-
-        for _ in 0..4 {
-            mix!();
-        }
-
-        if use_rsl {
-            macro_rules! memloop {
-                ($arr:expr) => {{
-                    for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
-                        a = a + $arr[i];
-                        b = b + $arr[i + 1];
-                        c = c + $arr[i + 2];
-                        d = d + $arr[i + 3];
-                        e = e + $arr[i + 4];
-                        f = f + $arr[i + 5];
-                        g = g + $arr[i + 6];
-                        h = h + $arr[i + 7];
-                        mix!();
-                        self.mem[i] = a;
-                        self.mem[i + 1] = b;
-                        self.mem[i + 2] = c;
-                        self.mem[i + 3] = d;
-                        self.mem[i + 4] = e;
-                        self.mem[i + 5] = f;
-                        self.mem[i + 6] = g;
-                        self.mem[i + 7] = h;
-                    }
-                }}
-            }
-
-            memloop!(self.rsl);
-            memloop!(self.mem);
-        } else {
-            for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
-                mix!();
-                self.mem[i] = a;
-                self.mem[i + 1] = b;
-                self.mem[i + 2] = c;
-                self.mem[i + 3] = d;
-                self.mem[i + 4] = e;
-                self.mem[i + 5] = f;
-                self.mem[i + 6] = g;
-                self.mem[i + 7] = h;
-            }
-        }
-
-        self.isaac64();
-    }
-
-    /// Refills the output buffer (`self.rsl`)
-    fn isaac64(&mut self) {
-        self.c = self.c + w(1);
-        // abbreviations
-        let mut a = self.a;
-        let mut b = self.b + self.c;
-        const MIDPOINT: usize = RAND_SIZE_64 / 2;
-        const MP_VEC: [(usize, usize); 2] = [(0, MIDPOINT), (MIDPOINT, 0)];
-        macro_rules! ind {
-            ($x:expr) => {
-                *self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
-            }
-        }
-
-        for &(mr_offset, m2_offset) in &MP_VEC {
-            for base in (0..MIDPOINT / 4).map(|i| i * 4) {
-
-                macro_rules! rngstepp {
-                    ($j:expr, $shift:expr) => {{
-                        let base = base + $j;
-                        let mix = a ^ (a << $shift);
-                        let mix = if $j == 0 {!mix} else {mix};
-
-                        unsafe {
-                            let x = *self.mem.get_unchecked(base + mr_offset);
-                            a = mix + *self.mem.get_unchecked(base + m2_offset);
-                            let y = ind!(x) + a + b;
-                            *self.mem.get_unchecked_mut(base + mr_offset) = y;
-
-                            b = ind!(y >> RAND_SIZE_64_LEN) + x;
-                            *self.rsl.get_unchecked_mut(base + mr_offset) = b;
-                        }
-                    }}
-                }
-
-                macro_rules! rngstepn {
-                    ($j:expr, $shift:expr) => {{
-                        let base = base + $j;
-                        let mix = a ^ (a >> $shift);
-                        let mix = if $j == 0 {!mix} else {mix};
-
-                        unsafe {
-                            let x = *self.mem.get_unchecked(base + mr_offset);
-                            a = mix + *self.mem.get_unchecked(base + m2_offset);
-                            let y = ind!(x) + a + b;
-                            *self.mem.get_unchecked_mut(base + mr_offset) = y;
-
-                            b = ind!(y >> RAND_SIZE_64_LEN) + x;
-                            *self.rsl.get_unchecked_mut(base + mr_offset) = b;
-                        }
-                    }}
-                }
-
-                rngstepp!(0, 21);
-                rngstepn!(1, 5);
-                rngstepp!(2, 12);
-                rngstepn!(3, 33);
-            }
-        }
-
-        self.a = a;
-        self.b = b;
-        self.cnt = RAND_SIZE_64;
-    }
-}
-
-// Cannot be derived because [u32; 256] does not implement Clone
-impl Clone for Isaac64Rng {
-    fn clone(&self) -> Isaac64Rng {
-        *self
-    }
-}
-
-impl Rng for Isaac64Rng {
-    // FIXME(https://github.com/rust-lang/rfcs/issues/628)
-    // having next_u32 like this should be unnecessary
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        self.next_u64() as u32
-    }
-
-    #[inline]
-    fn next_u64(&mut self) -> u64 {
-        if self.cnt == 0 {
-            // make some more numbers
-            self.isaac64();
-        }
-        self.cnt -= 1;
-
-        // See corresponding location in IsaacRng.next_u32 for
-        // explanation.
-        debug_assert!(self.cnt < RAND_SIZE_64);
-        self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
-    }
-}
-
-impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
-    fn reseed(&mut self, seed: &'a [u64]) {
-        // make the seed into [seed[0], seed[1], ..., seed[seed.len()
-        // - 1], 0, 0, ...], to fill rng.rsl.
-        let seed_iter = seed.iter().cloned().chain(repeat(0));
-
-        for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
-            *rsl_elem = w(seed_elem);
-        }
-        self.cnt = 0;
-        self.a = w(0);
-        self.b = w(0);
-        self.c = w(0);
-
-        self.init(true);
-    }
-
-    /// Create an ISAAC random number generator with a seed. This can
-    /// be any length, although the maximum number of elements used is
-    /// 256 and any more will be silently ignored. A generator
-    /// constructed with a given seed will generate the same sequence
-    /// of values as all other generators constructed with that seed.
-    fn from_seed(seed: &'a [u64]) -> Isaac64Rng {
-        let mut rng = EMPTY_64;
-        rng.reseed(seed);
-        rng
-    }
-}
-
-impl Rand for Isaac64Rng {
-    fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
-        let mut ret = EMPTY_64;
-        unsafe {
-            let ptr = ret.rsl.as_mut_ptr() as *mut u8;
-
-            let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8);
-            other.fill_bytes(slice);
-        }
-        ret.cnt = 0;
-        ret.a = w(0);
-        ret.b = w(0);
-        ret.c = w(0);
-
-        ret.init(true);
-        return ret;
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    use std::prelude::v1::*;
-
-    use {Rng, SeedableRng};
-    use super::{Isaac64Rng, IsaacRng};
-
-    #[test]
-    fn test_rng_32_rand_seeded() {
-        let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
-        let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]);
-        let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]);
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-    #[test]
-    fn test_rng_64_rand_seeded() {
-        let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
-        let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]);
-        let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]);
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-
-    #[test]
-    fn test_rng_32_seeded() {
-        let seed: &[_] = &[1, 23, 456, 7890, 12345];
-        let mut ra: IsaacRng = SeedableRng::from_seed(seed);
-        let mut rb: IsaacRng = SeedableRng::from_seed(seed);
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-    #[test]
-    fn test_rng_64_seeded() {
-        let seed: &[_] = &[1, 23, 456, 7890, 12345];
-        let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
-        let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-
-    #[test]
-    fn test_rng_32_reseed() {
-        let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
-        let mut r: IsaacRng = SeedableRng::from_seed(&s[..]);
-        let string1: String = r.gen_ascii_chars().take(100).collect();
-
-        r.reseed(&s);
-
-        let string2: String = r.gen_ascii_chars().take(100).collect();
-        assert_eq!(string1, string2);
-    }
-    #[test]
-    fn test_rng_64_reseed() {
-        let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
-        let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]);
-        let string1: String = r.gen_ascii_chars().take(100).collect();
-
-        r.reseed(&s);
-
-        let string2: String = r.gen_ascii_chars().take(100).collect();
-        assert_eq!(string1, string2);
-    }
-
-    #[test]
-    #[rustfmt_skip]
-    fn test_rng_32_true_values() {
-        let seed: &[_] = &[1, 23, 456, 7890, 12345];
-        let mut ra: IsaacRng = SeedableRng::from_seed(seed);
-        // Regression test that isaac is actually using the above vector
-        let v = (0..10).map(|_| ra.next_u32()).collect::<Vec<_>>();
-        assert_eq!(v,
-                   vec![2558573138, 873787463, 263499565, 2103644246, 3595684709,
-                        4203127393, 264982119, 2765226902, 2737944514, 3900253796]);
-
-        let seed: &[_] = &[12345, 67890, 54321, 9876];
-        let mut rb: IsaacRng = SeedableRng::from_seed(seed);
-        // skip forward to the 10000th number
-        for _ in 0..10000 {
-            rb.next_u32();
-        }
-
-        let v = (0..10).map(|_| rb.next_u32()).collect::<Vec<_>>();
-        assert_eq!(v,
-                   vec![3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
-                        1576568959, 3507990155, 179069555, 141456972, 2478885421]);
-    }
-    #[test]
-    #[rustfmt_skip]
-    fn test_rng_64_true_values() {
-        let seed: &[_] = &[1, 23, 456, 7890, 12345];
-        let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
-        // Regression test that isaac is actually using the above vector
-        let v = (0..10).map(|_| ra.next_u64()).collect::<Vec<_>>();
-        assert_eq!(v,
-                   vec![547121783600835980, 14377643087320773276, 17351601304698403469,
-                        1238879483818134882, 11952566807690396487, 13970131091560099343,
-                        4469761996653280935, 15552757044682284409, 6860251611068737823,
-                        13722198873481261842]);
-
-        let seed: &[_] = &[12345, 67890, 54321, 9876];
-        let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
-        // skip forward to the 10000th number
-        for _ in 0..10000 {
-            rb.next_u64();
-        }
-
-        let v = (0..10).map(|_| rb.next_u64()).collect::<Vec<_>>();
-        assert_eq!(v,
-                   vec![18143823860592706164, 8491801882678285927, 2699425367717515619,
-                        17196852593171130876, 2606123525235546165, 15790932315217671084,
-                        596345674630742204, 9947027391921273664, 11788097613744130851,
-                        10391409374914919106]);
-
-    }
-
-    #[test]
-    fn test_rng_clone() {
-        let seed: &[_] = &[1, 23, 456, 7890, 12345];
-        let mut rng: Isaac64Rng = SeedableRng::from_seed(seed);
-        let mut clone = rng.clone();
-        for _ in 0..16 {
-            assert_eq!(rng.next_u64(), clone.next_u64());
-        }
-    }
-}
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
deleted file mode 100644 (file)
index 82344f0..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-// Copyright 2013-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.
-
-//! Interface to random number generators in Rust.
-//!
-//! This is an experimental library which lives underneath the standard library
-//! in its dependency chain. This library is intended to define the interface
-//! for random number generation and also provide utilities around doing so. It
-//! is not recommended to use this library directly, but rather the official
-//! interface through `std::rand`.
-
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
-       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-       html_root_url = "https://doc.rust-lang.org/nightly/",
-       html_playground_url = "https://play.rust-lang.org/",
-       test(attr(deny(warnings))))]
-#![deny(warnings)]
-#![deny(missing_debug_implementations)]
-#![no_std]
-#![unstable(feature = "rand",
-            reason = "use `rand` from crates.io",
-            issue = "27703")]
-#![feature(core_intrinsics)]
-#![feature(staged_api)]
-#![feature(iterator_step_by)]
-#![feature(custom_attribute)]
-#![feature(specialization)]
-#![allow(unused_attributes)]
-
-#![cfg_attr(not(test), feature(core_float))] // only necessary for no_std
-#![cfg_attr(test, feature(test, rand))]
-
-#![allow(deprecated)]
-
-#[cfg(test)]
-#[macro_use]
-extern crate std;
-
-use core::fmt;
-use core::f64;
-use core::intrinsics;
-use core::marker::PhantomData;
-
-pub use isaac::{Isaac64Rng, IsaacRng};
-pub use chacha::ChaChaRng;
-
-use distributions::{IndependentSample, Range};
-use distributions::range::SampleRange;
-
-#[cfg(test)]
-const RAND_BENCH_N: u64 = 100;
-
-pub mod distributions;
-pub mod isaac;
-pub mod chacha;
-pub mod reseeding;
-mod rand_impls;
-
-// Temporary trait to implement a few floating-point routines
-// needed by librand; this is necessary because librand doesn't
-// depend on libstd.  This will go away when librand is integrated
-// into libstd.
-#[doc(hidden)]
-trait FloatMath: Sized {
-    fn exp(self) -> Self;
-    fn ln(self) -> Self;
-    fn sqrt(self) -> Self;
-    fn powf(self, n: Self) -> Self;
-}
-
-impl FloatMath for f64 {
-    #[inline]
-    fn exp(self) -> f64 {
-        unsafe { intrinsics::expf64(self) }
-    }
-
-    #[inline]
-    fn ln(self) -> f64 {
-        unsafe { intrinsics::logf64(self) }
-    }
-
-    #[inline]
-    fn powf(self, n: f64) -> f64 {
-        unsafe { intrinsics::powf64(self, n) }
-    }
-
-    #[inline]
-    fn sqrt(self) -> f64 {
-        if self < 0.0 {
-            f64::NAN
-        } else {
-            unsafe { intrinsics::sqrtf64(self) }
-        }
-    }
-}
-
-/// A type that can be randomly generated using an `Rng`.
-#[doc(hidden)]
-pub trait Rand: Sized {
-    /// Generates a random instance of this type using the specified source of
-    /// randomness.
-    fn rand<R: Rng>(rng: &mut R) -> Self;
-}
-
-/// A random number generator.
-pub trait Rng: Sized {
-    /// Return the next random u32.
-    ///
-    /// This rarely needs to be called directly, prefer `r.gen()` to
-    /// `r.next_u32()`.
-    // FIXME(https://github.com/rust-lang/rfcs/issues/628)
-    // Should be implemented in terms of next_u64
-    fn next_u32(&mut self) -> u32;
-
-    /// Return the next random u64.
-    ///
-    /// By default this is implemented in terms of `next_u32`. An
-    /// implementation of this trait must provide at least one of
-    /// these two methods. Similarly to `next_u32`, this rarely needs
-    /// to be called directly, prefer `r.gen()` to `r.next_u64()`.
-    fn next_u64(&mut self) -> u64 {
-        ((self.next_u32() as u64) << 32) | (self.next_u32() as u64)
-    }
-
-    /// Return the next random f32 selected from the half-open
-    /// interval `[0, 1)`.
-    ///
-    /// By default this is implemented in terms of `next_u32`, but a
-    /// random number generator which can generate numbers satisfying
-    /// the requirements directly can overload this for performance.
-    /// It is required that the return value lies in `[0, 1)`.
-    ///
-    /// See `Closed01` for the closed interval `[0,1]`, and
-    /// `Open01` for the open interval `(0,1)`.
-    fn next_f32(&mut self) -> f32 {
-        const MANTISSA_BITS: usize = 24;
-        const IGNORED_BITS: usize = 8;
-        const SCALE: f32 = (1u64 << MANTISSA_BITS) as f32;
-
-        // using any more than `MANTISSA_BITS` bits will
-        // cause (e.g.) 0xffff_ffff to correspond to 1
-        // exactly, so we need to drop some (8 for f32, 11
-        // for f64) to guarantee the open end.
-        (self.next_u32() >> IGNORED_BITS) as f32 / SCALE
-    }
-
-    /// Return the next random f64 selected from the half-open
-    /// interval `[0, 1)`.
-    ///
-    /// By default this is implemented in terms of `next_u64`, but a
-    /// random number generator which can generate numbers satisfying
-    /// the requirements directly can overload this for performance.
-    /// It is required that the return value lies in `[0, 1)`.
-    ///
-    /// See `Closed01` for the closed interval `[0,1]`, and
-    /// `Open01` for the open interval `(0,1)`.
-    fn next_f64(&mut self) -> f64 {
-        const MANTISSA_BITS: usize = 53;
-        const IGNORED_BITS: usize = 11;
-        const SCALE: f64 = (1u64 << MANTISSA_BITS) as f64;
-
-        (self.next_u64() >> IGNORED_BITS) as f64 / SCALE
-    }
-
-    /// Fill `dest` with random data.
-    ///
-    /// This has a default implementation in terms of `next_u64` and
-    /// `next_u32`, but should be overridden by implementations that
-    /// offer a more efficient solution than just calling those
-    /// methods repeatedly.
-    ///
-    /// This method does *not* have a requirement to bear any fixed
-    /// relationship to the other methods, for example, it does *not*
-    /// have to result in the same output as progressively filling
-    /// `dest` with `self.gen::<u8>()`, and any such behavior should
-    /// not be relied upon.
-    ///
-    /// This method should guarantee that `dest` is entirely filled
-    /// with new data, and may panic if this is impossible
-    /// (e.g. reading past the end of a file that is being used as the
-    /// source of randomness).
-    fn fill_bytes(&mut self, dest: &mut [u8]) {
-        // this could, in theory, be done by transmuting dest to a
-        // [u64], but this is (1) likely to be undefined behaviour for
-        // LLVM, (2) has to be very careful about alignment concerns,
-        // (3) adds more `unsafe` that needs to be checked, (4)
-        // probably doesn't give much performance gain if
-        // optimisations are on.
-        let mut count = 0;
-        let mut num = 0;
-        for byte in dest {
-            if count == 0 {
-                // we could micro-optimise here by generating a u32 if
-                // we only need a few more bytes to fill the vector
-                // (i.e. at most 4).
-                num = self.next_u64();
-                count = 8;
-            }
-
-            *byte = (num & 0xff) as u8;
-            num >>= 8;
-            count -= 1;
-        }
-    }
-
-    /// Return a random value of a `Rand` type.
-    #[inline(always)]
-    fn gen<T: Rand>(&mut self) -> T {
-        Rand::rand(self)
-    }
-
-    /// Return an iterator that will yield an infinite number of randomly
-    /// generated items.
-    fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
-        Generator {
-            rng: self,
-            _marker: PhantomData,
-        }
-    }
-
-    /// Generate a random value in the range [`low`, `high`).
-    ///
-    /// This is a convenience wrapper around
-    /// `distributions::Range`. If this function will be called
-    /// repeatedly with the same arguments, one should use `Range`, as
-    /// that will amortize the computations that allow for perfect
-    /// uniformity, as they only happen on initialization.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `low >= high`.
-    fn gen_range<T: PartialOrd + SampleRange>(&mut self, low: T, high: T) -> T {
-        assert!(low < high, "Rng.gen_range called with low >= high");
-        Range::new(low, high).ind_sample(self)
-    }
-
-    /// Return a bool with a 1 in n chance of true
-    fn gen_weighted_bool(&mut self, n: usize) -> bool {
-        n <= 1 || self.gen_range(0, n) == 0
-    }
-
-    /// Return an iterator of random characters from the set A-Z,a-z,0-9.
-    fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
-        AsciiGenerator { rng: self }
-    }
-
-    /// Return a random element from `values`.
-    ///
-    /// Return `None` if `values` is empty.
-    fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
-        if values.is_empty() {
-            None
-        } else {
-            Some(&values[self.gen_range(0, values.len())])
-        }
-    }
-
-    /// Shuffle a mutable slice in place.
-    fn shuffle<T>(&mut self, values: &mut [T]) {
-        let mut i = values.len();
-        while i >= 2 {
-            // invariant: elements with index >= i have been locked in place.
-            i -= 1;
-            // lock element i in place.
-            values.swap(i, self.gen_range(0, i + 1));
-        }
-    }
-}
-
-/// Iterator which will generate a stream of random items.
-///
-/// This iterator is created via the `gen_iter` method on `Rng`.
-pub struct Generator<'a, T, R: 'a> {
-    rng: &'a mut R,
-    _marker: PhantomData<T>,
-}
-
-impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        Some(self.rng.gen())
-    }
-}
-
-impl<'a, T, R: fmt::Debug> fmt::Debug for Generator<'a, T, R> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Generator")
-         .field("rng", &self.rng)
-         .finish()
-    }
-}
-
-/// Iterator which will continuously generate random ascii characters.
-///
-/// This iterator is created via the `gen_ascii_chars` method on `Rng`.
-pub struct AsciiGenerator<'a, R: 'a> {
-    rng: &'a mut R,
-}
-
-impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {
-    type Item = char;
-
-    fn next(&mut self) -> Option<char> {
-        const GEN_ASCII_STR_CHARSET: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
-                                                       abcdefghijklmnopqrstuvwxyz\
-                                                       0123456789";
-        Some(*self.rng.choose(GEN_ASCII_STR_CHARSET).unwrap() as char)
-    }
-}
-
-impl<'a, R: fmt::Debug> fmt::Debug for AsciiGenerator<'a, R> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("AsciiGenerator")
-         .field("rng", &self.rng)
-         .finish()
-    }
-}
-
-/// A random number generator that can be explicitly seeded to produce
-/// the same stream of randomness multiple times.
-pub trait SeedableRng<Seed>: Rng {
-    /// Reseed an RNG with the given seed.
-    fn reseed(&mut self, _: Seed);
-
-    /// Create a new RNG with the given seed.
-    fn from_seed(seed: Seed) -> Self;
-}
-
-/// An Xorshift[1] random number
-/// generator.
-///
-/// The Xorshift algorithm is not suitable for cryptographic purposes
-/// but is very fast. If you do not know for sure that it fits your
-/// requirements, use a more secure one such as `IsaacRng` or `OsRng`.
-///
-/// [1]: Marsaglia, George (July 2003). ["Xorshift
-/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
-/// Statistical Software*. Vol. 8 (Issue 14).
-#[derive(Clone, Debug)]
-pub struct XorShiftRng {
-    x: u32,
-    y: u32,
-    z: u32,
-    w: u32,
-}
-
-impl XorShiftRng {
-    /// Creates a new XorShiftRng instance which is not seeded.
-    ///
-    /// The initial values of this RNG are constants, so all generators created
-    /// by this function will yield the same stream of random numbers. It is
-    /// highly recommended that this is created through `SeedableRng` instead of
-    /// this function
-    pub fn new_unseeded() -> XorShiftRng {
-        XorShiftRng {
-            x: 0x193a6754,
-            y: 0xa8a7d469,
-            z: 0x97830e05,
-            w: 0x113ba7bb,
-        }
-    }
-}
-
-impl Rng for XorShiftRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        let x = self.x;
-        let t = x ^ (x << 11);
-        self.x = self.y;
-        self.y = self.z;
-        self.z = self.w;
-        let w = self.w;
-        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
-        self.w
-    }
-}
-
-impl SeedableRng<[u32; 4]> for XorShiftRng {
-    /// Reseed an XorShiftRng. This will panic if `seed` is entirely 0.
-    fn reseed(&mut self, seed: [u32; 4]) {
-        assert!(!seed.iter().all(|&x| x == 0),
-                "XorShiftRng.reseed called with an all zero seed.");
-
-        self.x = seed[0];
-        self.y = seed[1];
-        self.z = seed[2];
-        self.w = seed[3];
-    }
-
-    /// Create a new XorShiftRng. This will panic if `seed` is entirely 0.
-    fn from_seed(seed: [u32; 4]) -> XorShiftRng {
-        assert!(!seed.iter().all(|&x| x == 0),
-                "XorShiftRng::from_seed called with an all zero seed.");
-
-        XorShiftRng {
-            x: seed[0],
-            y: seed[1],
-            z: seed[2],
-            w: seed[3],
-        }
-    }
-}
-
-impl Rand for XorShiftRng {
-    fn rand<R: Rng>(rng: &mut R) -> XorShiftRng {
-        let mut tuple: (u32, u32, u32, u32) = rng.gen();
-        while tuple == (0, 0, 0, 0) {
-            tuple = rng.gen();
-        }
-        let (x, y, z, w) = tuple;
-        XorShiftRng {
-            x,
-            y,
-            z,
-            w,
-        }
-    }
-}
-
-/// A wrapper for generating floating point numbers uniformly in the
-/// open interval `(0,1)` (not including either endpoint).
-///
-/// Use `Closed01` for the closed interval `[0,1]`, and the default
-/// `Rand` implementation for `f32` and `f64` for the half-open
-/// `[0,1)`.
-pub struct Open01<F>(pub F);
-
-impl<F: fmt::Debug> fmt::Debug for Open01<F> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("Open01")
-         .field(&self.0)
-         .finish()
-    }
-}
-
-/// A wrapper for generating floating point numbers uniformly in the
-/// closed interval `[0,1]` (including both endpoints).
-///
-/// Use `Open01` for the closed interval `(0,1)`, and the default
-/// `Rand` implementation of `f32` and `f64` for the half-open
-/// `[0,1)`.
-pub struct Closed01<F>(pub F);
-
-impl<F: fmt::Debug> fmt::Debug for Closed01<F> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("Closed01")
-         .field(&self.0)
-         .finish()
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::__rand as rand;
-
-    pub struct MyRng<R> {
-        inner: R,
-    }
-
-    impl<R: rand::Rng> ::Rng for MyRng<R> {
-        fn next_u32(&mut self) -> u32 {
-            rand::Rng::next_u32(&mut self.inner)
-        }
-    }
-
-    pub fn rng() -> MyRng<rand::ThreadRng> {
-        MyRng { inner: rand::thread_rng() }
-    }
-
-    pub fn weak_rng() -> MyRng<rand::ThreadRng> {
-        MyRng { inner: rand::thread_rng() }
-    }
-}
diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs
deleted file mode 100644 (file)
index b0d824d..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2013-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.
-
-//! The implementations of `Rand` for the built-in types.
-
-use core::char;
-use core::mem;
-
-use {Rand, Rng};
-
-impl Rand for isize {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> isize {
-        if mem::size_of::<isize>() == 4 {
-            rng.gen::<i32>() as isize
-        } else {
-            rng.gen::<i64>() as isize
-        }
-    }
-}
-
-impl Rand for i8 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> i8 {
-        rng.next_u32() as i8
-    }
-}
-
-impl Rand for i16 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> i16 {
-        rng.next_u32() as i16
-    }
-}
-
-impl Rand for i32 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> i32 {
-        rng.next_u32() as i32
-    }
-}
-
-impl Rand for i64 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> i64 {
-        rng.next_u64() as i64
-    }
-}
-
-impl Rand for usize {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> usize {
-        if mem::size_of::<usize>() == 4 {
-            rng.gen::<u32>() as usize
-        } else {
-            rng.gen::<u64>() as usize
-        }
-    }
-}
-
-impl Rand for u8 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> u8 {
-        rng.next_u32() as u8
-    }
-}
-
-impl Rand for u16 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> u16 {
-        rng.next_u32() as u16
-    }
-}
-
-impl Rand for u32 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> u32 {
-        rng.next_u32()
-    }
-}
-
-impl Rand for u64 {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> u64 {
-        rng.next_u64()
-    }
-}
-
-macro_rules! float_impls {
-    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
-        mod $mod_name {
-            use {Rand, Rng, Open01, Closed01};
-
-            const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
-
-            impl Rand for $ty {
-                /// Generate a floating point number in the half-open
-                /// interval `[0,1)`.
-                ///
-                /// See `Closed01` for the closed interval `[0,1]`,
-                /// and `Open01` for the open interval `(0,1)`.
-                #[inline]
-                fn rand<R: Rng>(rng: &mut R) -> $ty {
-                    rng.$method_name()
-                }
-            }
-            impl Rand for Open01<$ty> {
-                #[inline]
-                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
-                    // add a small amount (specifically 2 bits below
-                    // the precision of f64/f32 at 1.0), so that small
-                    // numbers are larger than 0, but large numbers
-                    // aren't pushed to/above 1.
-                    Open01(rng.$method_name() + 0.25 / SCALE)
-                }
-            }
-            impl Rand for Closed01<$ty> {
-                #[inline]
-                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
-                    // rescale so that 1.0 - epsilon becomes 1.0
-                    // precisely.
-                    Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
-                }
-            }
-        }
-    }
-}
-float_impls! { f64_rand_impls, f64, 53, next_f64 }
-float_impls! { f32_rand_impls, f32, 24, next_f32 }
-
-impl Rand for char {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> char {
-        // a char is 21 bits
-        const CHAR_MASK: u32 = 0x001f_ffff;
-        loop {
-            // Rejection sampling. About 0.2% of numbers with at most
-            // 21-bits are invalid codepoints (surrogates), so this
-            // will succeed first go almost every time.
-            if let Some(c) = char::from_u32(rng.next_u32() & CHAR_MASK) {
-                return c;
-            }
-        }
-    }
-}
-
-impl Rand for bool {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> bool {
-        rng.gen::<u8>() & 1 == 1
-    }
-}
-
-macro_rules! tuple_impl {
-    // use variables to indicate the arity of the tuple
-    ($($tyvar:ident),* ) => {
-        // the trailing commas are for the 1 tuple
-        impl<
-            $( $tyvar : Rand ),*
-            > Rand for ( $( $tyvar ),* , ) {
-
-            #[inline]
-            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
-                (
-                    // use the $tyvar's to get the appropriate number of
-                    // repeats (they're not actually needed)
-                    $(
-                        _rng.gen::<$tyvar>()
-                    ),*
-                    ,
-                )
-            }
-        }
-    }
-}
-
-impl Rand for () {
-    #[inline]
-    fn rand<R: Rng>(_: &mut R) -> () {
-        ()
-    }
-}
-tuple_impl!{A}
-tuple_impl!{A, B}
-tuple_impl!{A, B, C}
-tuple_impl!{A, B, C, D}
-tuple_impl!{A, B, C, D, E}
-tuple_impl!{A, B, C, D, E, F}
-tuple_impl!{A, B, C, D, E, F, G}
-tuple_impl!{A, B, C, D, E, F, G, H}
-tuple_impl!{A, B, C, D, E, F, G, H, I}
-tuple_impl!{A, B, C, D, E, F, G, H, I, J}
-tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
-tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
-
-impl<T: Rand> Rand for Option<T> {
-    #[inline]
-    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
-        if rng.gen() { Some(rng.gen()) } else { None }
-    }
-}
diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs
deleted file mode 100644 (file)
index 2821b7a..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A wrapper around another RNG that reseeds it after it
-//! generates a certain number of random bytes.
-
-use core::fmt;
-use {Rng, SeedableRng};
-
-/// How many bytes of entropy the underling RNG is allowed to generate
-/// before it is reseeded.
-const DEFAULT_GENERATION_THRESHOLD: usize = 32 * 1024;
-
-/// A wrapper around any RNG which reseeds the underlying RNG after it
-/// has generated a certain number of random bytes.
-pub struct ReseedingRng<R, Rsdr> {
-    rng: R,
-    generation_threshold: usize,
-    bytes_generated: usize,
-    /// Controls the behavior when reseeding the RNG.
-    pub reseeder: Rsdr,
-}
-
-impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
-    /// Create a new `ReseedingRng` with the given parameters.
-    ///
-    /// # Arguments
-    ///
-    /// * `rng`: the random number generator to use.
-    /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
-    /// * `reseeder`: the reseeding object to use.
-    pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R, Rsdr> {
-        ReseedingRng {
-            rng,
-            generation_threshold,
-            bytes_generated: 0,
-            reseeder,
-        }
-    }
-
-    /// Reseed the internal RNG if the number of bytes that have been
-    /// generated exceed the threshold.
-    pub fn reseed_if_necessary(&mut self) {
-        if self.bytes_generated >= self.generation_threshold {
-            self.reseeder.reseed(&mut self.rng);
-            self.bytes_generated = 0;
-        }
-    }
-}
-
-impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
-    fn next_u32(&mut self) -> u32 {
-        self.reseed_if_necessary();
-        self.bytes_generated += 4;
-        self.rng.next_u32()
-    }
-
-    fn next_u64(&mut self) -> u64 {
-        self.reseed_if_necessary();
-        self.bytes_generated += 8;
-        self.rng.next_u64()
-    }
-
-    fn fill_bytes(&mut self, dest: &mut [u8]) {
-        self.reseed_if_necessary();
-        self.bytes_generated += dest.len();
-        self.rng.fill_bytes(dest)
-    }
-}
-
-impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
-     SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
-    fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
-        self.rng.reseed(seed);
-        self.reseeder = rsdr;
-        self.bytes_generated = 0;
-    }
-
-/// Create a new `ReseedingRng` from the given reseeder and
-/// seed. This uses a default value for `generation_threshold`.
-    fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
-        ReseedingRng {
-            rng: SeedableRng::from_seed(seed),
-            generation_threshold: DEFAULT_GENERATION_THRESHOLD,
-            bytes_generated: 0,
-            reseeder: rsdr,
-        }
-    }
-}
-
-impl<R: fmt::Debug, Rsdr: fmt::Debug> fmt::Debug for ReseedingRng<R, Rsdr> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("ReseedingRng")
-         .field("rng", &self.rng)
-         .field("generation_threshold", &self.generation_threshold)
-         .field("bytes_generated", &self.bytes_generated)
-         .field("reseeder", &self.reseeder)
-         .finish()
-    }
-}
-
-/// Something that can be used to reseed an RNG via `ReseedingRng`.
-pub trait Reseeder<R> {
-    /// Reseed the given RNG.
-    fn reseed(&mut self, rng: &mut R);
-}
-
-/// Reseed an RNG using a `Default` instance. This reseeds by
-/// replacing the RNG with the result of a `Default::default` call.
-#[derive(Copy, Clone, Debug)]
-pub struct ReseedWithDefault;
-
-impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
-    fn reseed(&mut self, rng: &mut R) {
-        *rng = Default::default();
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Default for ReseedWithDefault {
-    /// Creates an instance of `ReseedWithDefault`.
-    fn default() -> ReseedWithDefault {
-        ReseedWithDefault
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use std::prelude::v1::*;
-
-    use super::{ReseedWithDefault, ReseedingRng};
-    use {Rng, SeedableRng};
-
-    struct Counter {
-        i: u32,
-    }
-
-    impl Rng for Counter {
-        fn next_u32(&mut self) -> u32 {
-            self.i += 1;
-            // very random
-            self.i - 1
-        }
-    }
-    impl Default for Counter {
-        /// Constructs a `Counter` with initial value zero.
-        fn default() -> Counter {
-            Counter { i: 0 }
-        }
-    }
-    impl SeedableRng<u32> for Counter {
-        fn reseed(&mut self, seed: u32) {
-            self.i = seed;
-        }
-        fn from_seed(seed: u32) -> Counter {
-            Counter { i: seed }
-        }
-    }
-    type MyRng = ReseedingRng<Counter, ReseedWithDefault>;
-
-    #[test]
-    fn test_reseeding() {
-        let mut rs = ReseedingRng::new(Counter { i: 0 }, 400, ReseedWithDefault);
-
-        let mut i = 0;
-        for _ in 0..1000 {
-            assert_eq!(rs.next_u32(), i % 100);
-            i += 1;
-        }
-    }
-
-    #[test]
-    fn test_rng_seeded() {
-        let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
-        let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
-        assert!(ra.gen_ascii_chars()
-            .take(100)
-            .eq(rb.gen_ascii_chars().take(100)));
-    }
-
-    #[test]
-    fn test_rng_reseed() {
-        let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
-        let string1: String = r.gen_ascii_chars().take(100).collect();
-
-        r.reseed((ReseedWithDefault, 3));
-
-        let string2: String = r.gen_ascii_chars().take(100).collect();
-        assert_eq!(string1, string2);
-    }
-
-    const FILL_BYTES_V_LEN: usize = 13579;
-    #[test]
-    fn test_rng_fill_bytes() {
-        let mut v = vec![0; FILL_BYTES_V_LEN];
-        ::test::rng().fill_bytes(&mut v);
-
-        // Sanity test: if we've gotten here, `fill_bytes` has not infinitely
-        // recursed.
-        assert_eq!(v.len(), FILL_BYTES_V_LEN);
-
-        // To test that `fill_bytes` actually did something, check that the
-        // average of `v` is not 0.
-        let mut sum = 0.0;
-        for &x in &v {
-            sum += x as f64;
-        }
-        assert!(sum / v.len() as f64 != 0.0);
-    }
-}
index 70cfe57d15023b8ba67a38221f116abd6fe443df..b391b353632aad28c1b19b4d5a891c8e7d0c51e9 100644 (file)
@@ -459,10 +459,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // Represents metadata from an extern crate.
     [input] CrateMetadata(CrateNum),
 
-    // Represents some artifact that we save to disk. Note that these
-    // do not have a def-id as part of their identifier.
-    [] WorkProduct(WorkProductId),
-
     // Represents different phases in the compiler.
     [] RegionScopeTree(DefId),
     [eval_always] Coherence,
@@ -473,6 +469,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // Represents the MIR for a fn; also used as the task node for
     // things read/modify that MIR.
     [] MirConstQualif(DefId),
+    [] MirBuilt(DefId),
     [] MirConst(DefId),
     [] MirValidated(DefId),
     [] MirOptimized(DefId),
@@ -481,7 +478,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] BorrowCheckKrate,
     [] BorrowCheck(DefId),
     [] MirBorrowCheck(DefId),
-    [] UnsafetyViolations(DefId),
+    [] UnsafetyCheckResult(DefId),
 
     [] Reachability,
     [] MirKeys,
@@ -537,38 +534,19 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // The set of impls for a given trait.
     [] TraitImpls(DefId),
 
-    [] AllLocalTraitImpls,
-
-    // Trait selection cache is a little funny. Given a trait
-    // reference like `Foo: SomeTrait<Bar>`, there could be
-    // arbitrarily many def-ids to map on in there (e.g., `Foo`,
-    // `SomeTrait`, `Bar`). We could have a vector of them, but it
-    // requires heap-allocation, and trait sel in general can be a
-    // surprisingly hot path. So instead we pick two def-ids: the
-    // trait def-id, and the first def-id in the input types. If there
-    // is no def-id in the input types, then we use the trait def-id
-    // again. So for example:
-    //
-    // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
-    // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
-    // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
-    // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
-    // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
-    // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    //
-    // You can see that we map many trait refs to the same
-    // trait-select node.  This is not a problem, it just means
-    // imprecision in our dep-graph tracking.  The important thing is
-    // that for any given trait-ref, we always map to the **same**
-    // trait-select node.
+    [input] AllLocalTraitImpls,
+
     [anon] TraitSelect,
 
     [] ParamEnv(DefId),
     [] DescribeDef(DefId),
-    [] DefSpan(DefId),
+
+    // FIXME(mw): DefSpans are not really inputs since they are derived from
+    // HIR. But at the moment HIR hashing still contains some hacks that allow
+    // to make type debuginfo to be source location independent. Declaring
+    // DefSpan an input makes sure that changes to these are always detected
+    // regardless of HIR hashing.
+    [input] DefSpan(DefId),
     [] LookupStability(DefId),
     [] LookupDeprecationEntry(DefId),
     [] ItemBodyNestedBodies(DefId),
@@ -588,7 +566,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [eval_always] LintLevels,
     [] Specializes { impl1: DefId, impl2: DefId },
     [input] InScopeTraits(DefIndex),
-    [] ModuleExports(DefId),
+    [input] ModuleExports(DefId),
     [] IsSanitizerRuntime(CrateNum),
     [] IsProfilerRuntime(CrateNum),
     [] GetPanicStrategy(CrateNum),
@@ -598,9 +576,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] NativeLibraries(CrateNum),
     [] PluginRegistrarFn(CrateNum),
     [] DeriveRegistrarFn(CrateNum),
-    [] CrateDisambiguator(CrateNum),
-    [] CrateHash(CrateNum),
-    [] OriginalCrateName(CrateNum),
+    [input] CrateDisambiguator(CrateNum),
+    [input] CrateHash(CrateNum),
+    [input] OriginalCrateName(CrateNum),
 
     [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
     [] AllTraitImplementations(CrateNum),
@@ -608,27 +586,27 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] IsDllimportForeignItem(DefId),
     [] IsStaticallyIncludedForeignItem(DefId),
     [] NativeLibraryKind(DefId),
-    [] LinkArgs,
+    [input] LinkArgs,
 
-    [] NamedRegion(DefIndex),
-    [] IsLateBound(DefIndex),
-    [] ObjectLifetimeDefaults(DefIndex),
+    [input] NamedRegion(DefIndex),
+    [input] IsLateBound(DefIndex),
+    [input] ObjectLifetimeDefaults(DefIndex),
 
     [] Visibility(DefId),
     [] DepKind(CrateNum),
-    [] CrateName(CrateNum),
+    [input] CrateName(CrateNum),
     [] ItemChildren(DefId),
     [] ExternModStmtCnum(DefId),
-    [] GetLangItems,
+    [input] GetLangItems,
     [] DefinedLangItems(CrateNum),
     [] MissingLangItems(CrateNum),
     [] ExternConstBody(DefId),
     [] VisibleParentMap,
     [] MissingExternCrateItem(CrateNum),
     [] UsedCrateSource(CrateNum),
-    [] PostorderCnums,
-    [] HasCloneClosures(CrateNum),
-    [] HasCopyClosures(CrateNum),
+    [input] PostorderCnums,
+    [input] HasCloneClosures(CrateNum),
+    [input] HasCopyClosures(CrateNum),
 
     // This query is not expected to have inputs -- as a result, it's
     // not a good candidate for "replay" because it's essentially a
@@ -638,11 +616,11 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // may save a bit of time.
     [anon] EraseRegionsTy { ty: Ty<'tcx> },
 
-    [] Freevars(DefId),
-    [] MaybeUnusedTraitImport(DefId),
+    [input] Freevars(DefId),
+    [input] MaybeUnusedTraitImport(DefId),
     [] MaybeUnusedExternCrates,
     [] StabilityIndex,
-    [] AllCrateNums,
+    [input] AllCrateNums,
     [] ExportedSymbols(CrateNum),
     [eval_always] CollectAndPartitionTranslationItems,
     [] ExportName(DefId),
@@ -650,7 +628,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] IsTranslatedFunction(DefId),
     [] CodegenUnit(InternedString),
     [] CompileCodegenUnit(InternedString),
-    [] OutputFilenames,
+    [input] OutputFilenames,
     [anon] NormalizeTy,
     // We use this for most things when incr. comp. is turned off.
     [] Null,
@@ -800,16 +778,8 @@ pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId {
             hash: fingerprint
         }
     }
-
-    pub fn to_dep_node(self) -> DepNode {
-        DepNode {
-            kind: DepKind::WorkProduct,
-            hash: self.hash,
-        }
-    }
 }
 
 impl_stable_hash_for!(struct ::dep_graph::WorkProductId {
     hash
 });
-
index 0fb4e354a52d44b93a5f62a5ac709a0ae5941d15..1433fa81f333e711523d8e4209276eec32c24c76 100644 (file)
@@ -328,7 +328,12 @@ pub fn read_index(&self, dep_node_index: DepNodeIndex) {
     }
 
     pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
-        self.fingerprints.borrow()[dep_node]
+        match self.fingerprints.borrow().get(dep_node) {
+            Some(&fingerprint) => fingerprint,
+            None => {
+                bug!("Could not find current fingerprint for {:?}", dep_node)
+            }
+        }
     }
 
     pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
@@ -506,60 +511,67 @@ pub fn try_mark_green(&self,
                     return None
                 }
                 None => {
-                    if dep_dep_node.kind.is_input() {
-                        // This input does not exist anymore.
-                        debug_assert!(dep_dep_node.extract_def_id(tcx).is_none(),
-                                      "Encountered input {:?} without color",
-                                      dep_dep_node);
-                        debug!("try_mark_green({:?}) - END - dependency {:?} \
-                                was deleted input", dep_node, dep_dep_node);
-                        return None;
+                    // We don't know the state of this dependency. If it isn't
+                    // an input node, let's try to mark it green recursively.
+                    if !dep_dep_node.kind.is_input() {
+                         debug!("try_mark_green({:?}) --- state of dependency {:?} \
+                                 is unknown, trying to mark it green", dep_node,
+                                 dep_dep_node);
+
+                        if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
+                            debug!("try_mark_green({:?}) --- managed to MARK \
+                                    dependency {:?} as green", dep_node, dep_dep_node);
+                            current_deps.push(node_index);
+                            continue;
+                        }
+                    } else if cfg!(debug_assertions) {
+                        match dep_dep_node.kind {
+                            DepKind::Hir |
+                            DepKind::HirBody |
+                            DepKind::CrateMetadata => {
+                                assert!(dep_dep_node.extract_def_id(tcx).is_none(),
+                                    "Input {:?} should have been pre-allocated but wasn't.",
+                                    dep_dep_node);
+                            }
+                            _ => {
+                                // For other kinds of inputs it's OK to be
+                                // forced.
+                            }
+                        }
                     }
 
-                    debug!("try_mark_green({:?}) --- state of dependency {:?} \
-                            is unknown, trying to mark it green", dep_node,
-                            dep_dep_node);
-
-                    // We don't know the state of this dependency. Let's try to
-                    // mark it green.
-                    if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
-                        debug!("try_mark_green({:?}) --- managed to MARK \
-                                dependency {:?} as green", dep_node, dep_dep_node);
-                        current_deps.push(node_index);
-                    } else {
-                        // We failed to mark it green, so we try to force the query.
-                        debug!("try_mark_green({:?}) --- trying to force \
-                                dependency {:?}", dep_node, dep_dep_node);
-                        if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
-                            let dep_dep_node_color = data.colors
-                                                         .borrow()
-                                                         .get(dep_dep_node)
-                                                         .cloned();
-                            match dep_dep_node_color {
-                                Some(DepNodeColor::Green(node_index)) => {
-                                    debug!("try_mark_green({:?}) --- managed to \
-                                            FORCE dependency {:?} to green",
-                                            dep_node, dep_dep_node);
-                                    current_deps.push(node_index);
-                                }
-                                Some(DepNodeColor::Red) => {
-                                    debug!("try_mark_green({:?}) - END - \
-                                            dependency {:?} was red after forcing",
-                                           dep_node,
-                                           dep_dep_node);
-                                    return None
-                                }
-                                None => {
-                                    bug!("try_mark_green() - Forcing the DepNode \
-                                          should have set its color")
-                                }
+                    // We failed to mark it green, so we try to force the query.
+                    debug!("try_mark_green({:?}) --- trying to force \
+                            dependency {:?}", dep_node, dep_dep_node);
+                    if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
+                        let dep_dep_node_color = data.colors
+                                                     .borrow()
+                                                     .get(dep_dep_node)
+                                                     .cloned();
+                        match dep_dep_node_color {
+                            Some(DepNodeColor::Green(node_index)) => {
+                                debug!("try_mark_green({:?}) --- managed to \
+                                        FORCE dependency {:?} to green",
+                                        dep_node, dep_dep_node);
+                                current_deps.push(node_index);
+                            }
+                            Some(DepNodeColor::Red) => {
+                                debug!("try_mark_green({:?}) - END - \
+                                        dependency {:?} was red after forcing",
+                                       dep_node,
+                                       dep_dep_node);
+                                return None
+                            }
+                            None => {
+                                bug!("try_mark_green() - Forcing the DepNode \
+                                      should have set its color")
                             }
-                        } else {
-                            // The DepNode could not be forced.
-                            debug!("try_mark_green({:?}) - END - dependency {:?} \
-                                    could not be forced", dep_node, dep_dep_node);
-                            return None
                         }
+                    } else {
+                        // The DepNode could not be forced.
+                        debug!("try_mark_green({:?}) - END - dependency {:?} \
+                                could not be forced", dep_node, dep_dep_node);
+                        return None
                     }
                 }
             }
@@ -772,7 +784,30 @@ pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndex {
             read_set: _,
             reads
         } = popped_node {
-            debug_assert_eq!(node, key);
+            assert_eq!(node, key);
+
+            // If this is an input node, we expect that it either has no
+            // dependencies, or that it just depends on DepKind::CrateMetadata
+            // or DepKind::Krate. This happens for some "thin wrapper queries"
+            // like `crate_disambiguator` which sometimes have zero deps (for
+            // when called for LOCAL_CRATE) or they depend on a CrateMetadata
+            // node.
+            if cfg!(debug_assertions) {
+                if node.kind.is_input() && reads.len() > 0 &&
+                   // FIXME(mw): Special case for DefSpan until Spans are handled
+                   //            better in general.
+                   node.kind != DepKind::DefSpan &&
+                    reads.iter().any(|&i| {
+                        !(self.nodes[i].kind == DepKind::CrateMetadata ||
+                          self.nodes[i].kind == DepKind::Krate)
+                    })
+                {
+                    bug!("Input node {:?} with unexpected reads: {:?}",
+                        node,
+                        reads.iter().map(|&i| self.nodes[i]).collect::<Vec<_>>())
+                }
+            }
+
             self.alloc_node(node, reads)
         } else {
             bug!("pop_task() - Expected regular task to be popped")
@@ -793,6 +828,8 @@ fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex {
             read_set: _,
             reads
         } = popped_node {
+            debug_assert!(!kind.is_input());
+
             let mut fingerprint = self.anon_id_seed;
             let mut hasher = StableHasher::new();
 
index a69d41d16033f4a0c5b657c7e92e4faa685b7ac7..ba89961adc68739c561f664da02a6eec0eaed4a0 100644 (file)
@@ -838,7 +838,10 @@ fn lower_qpath(&mut self,
                         return n;
                     }
                     assert!(!def_id.is_local());
-                    let n = self.cstore.item_generics_cloned_untracked(def_id).regions.len();
+                    let n = self.cstore
+                                .item_generics_cloned_untracked(def_id, self.sess)
+                                .regions
+                                .len();
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
index b30cc0b09c9ac6c316cdea2ba34e49ff46cf3c0d..dfa675f2e93514c768a0d5398375ff321c8293bc 100644 (file)
@@ -314,6 +314,29 @@ pub fn to_string_no_crate(&self) -> String {
 
         s
     }
+
+    /// Return filename friendly string of the DefPah without
+    /// the crate-prefix. This method is useful if you don't have
+    /// a TyCtxt available.
+    pub fn to_filename_friendly_no_crate(&self) -> String {
+        let mut s = String::with_capacity(self.data.len() * 16);
+
+        let mut opt_delimiter = None;
+        for component in &self.data {
+            opt_delimiter.map(|d| s.push(d));
+            opt_delimiter = Some('-');
+            if component.disambiguator == 0 {
+                write!(s, "{}", component.data.as_interned_str()).unwrap();
+            } else {
+                write!(s,
+                       "{}[{}]",
+                       component.data.as_interned_str(),
+                       component.disambiguator)
+                    .unwrap();
+            }
+        }
+        s
+    }
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
index 1236602aecf55ab9c04b4e4c856e1fd900c35666..453d30dde7595382b86e744d499d6f2651a9fda1 100644 (file)
@@ -416,6 +416,12 @@ pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(&self, id: NodeId) -> Option<BodyId> {
         if let Some(entry) = self.find_entry(id) {
+            if self.dep_graph.is_fully_enabled() {
+                let hir_id_owner = self.node_to_hir_id(id).owner;
+                let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
+                self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
+            }
+
             if let Some(body_id) = entry.associated_body() {
                 // For item-like things and closures, the associated
                 // body has its own distinct id, and that is returned
@@ -530,6 +536,12 @@ pub fn find(&self, id: NodeId) -> Option<Node<'hir>> {
     /// from a node to the root of the ast (unless you get the same id back here
     /// that can happen if the id is not in the map itself or is just weird).
     pub fn get_parent_node(&self, id: NodeId) -> NodeId {
+        if self.dep_graph.is_fully_enabled() {
+            let hir_id_owner = self.node_to_hir_id(id).owner;
+            let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
+            self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
+        }
+
         self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
     }
 
index c9b1d70e7b60df57d2ebecc1c137384714a6ad97..39e222230e57764ab1630d429f0c1035f5fa5549 100644 (file)
@@ -1949,7 +1949,7 @@ pub fn descriptive_variant(&self) -> &str {
 }
 
 /// A free variable referred to in a function.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
 pub struct Freevar {
     /// The variable being accessed free.
     pub def: Def,
index 7b4881f5486dc0b756ad233a7a16176a5a10e951..7d0f26ba34d4159770c7f3b0710e4b69b3e95188 100644 (file)
@@ -1254,6 +1254,15 @@ fn print_expr_binary(&mut self,
             Fixity::None => (prec + 1, prec + 1),
         };
 
+        let left_prec = match (&lhs.node, op.node) {
+            // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
+            // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
+            // of `(x as i32) < ...`. We need to convince it _not_ to do that.
+            (&hir::ExprCast { .. }, hir::BinOp_::BiLt) |
+            (&hir::ExprCast { .. }, hir::BinOp_::BiShl) => parser::PREC_FORCE_PAREN,
+            _ => left_prec,
+        };
+
         self.print_expr_maybe_paren(lhs, left_prec)?;
         self.s.space()?;
         self.word_space(op.node.as_str())?;
index d24344e4e2166c9960ccbd3115700f186a1113d9..f204d352842bfe41fc01b0e30bfe668bb6eebe3e 100644 (file)
@@ -227,6 +227,8 @@ pub fn binop_can_panic_at_runtime(&self, binop: hir::BinOp_) -> bool
         match binop {
             hir::BiAdd |
             hir::BiSub |
+            hir::BiShl |
+            hir::BiShr |
             hir::BiMul => self.overflow_checks_enabled,
 
             hir::BiDiv |
@@ -237,8 +239,6 @@ pub fn binop_can_panic_at_runtime(&self, binop: hir::BinOp_) -> bool
             hir::BiBitXor |
             hir::BiBitAnd |
             hir::BiBitOr |
-            hir::BiShl |
-            hir::BiShr |
             hir::BiEq |
             hir::BiLt |
             hir::BiLe |
index f0fe6205fb6d0bfb29624df39c7cd28c64a07103..6b78cd473be8ffc1df38886526e845aeda358474 100644 (file)
@@ -356,33 +356,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             targeted_by_break,
         } = *self;
 
-        let non_item_stmts = || stmts.iter().filter(|stmt| {
-            match stmt.node {
-                hir::StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        // If this is a declaration of a nested item, we don't
-                        // want to leave any trace of it in the hash value, not
-                        // even that it exists. Otherwise changing the position
-                        // of nested items would invalidate the containing item
-                        // even though that does not constitute a semantic
-                        // change.
-                        hir::DeclItem(_) => false,
-                        hir::DeclLocal(_) => true
-                    }
-                }
-                hir::StmtExpr(..) |
-                hir::StmtSemi(..) => true
-            }
-        });
-
-        let count = non_item_stmts().count();
-
-        count.hash_stable(hcx, hasher);
-
-        for stmt in non_item_stmts() {
-            stmt.hash_stable(hcx, hasher);
-        }
-
+        stmts.hash_stable(hcx, hasher);
         expr.hash_stable(hcx, hasher);
         rules.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
index 05436201e7a6e56ab75eca6eb8bd18117cd90ffe..8ae26d81442a2be9c42917afe87ad313a39cb6fd 100644 (file)
@@ -34,6 +34,7 @@
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
 impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
 impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, lint_node_id });
+impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::Terminator<'gcx> {
index ee30db26255198ad1b3b361b17b06fd1ad5aa587..36370e23f216128f6f7e7c9c06eff16e95e464a4 100644 (file)
 use infer::error_reporting::util::AnonymousArgInfo;
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    // This method prints the error message for lifetime errors when both the concerned regions
-    // are anonymous.
-    // Consider a case where we have
-    // fn foo(x: &mut Vec<&u8>, y: &u8)
-    //    { x.push(y); }.
-    // The example gives
-    // fn foo(x: &mut Vec<&u8>, y: &u8) {
-    //                    ---      --- these references are declared with different lifetimes...
-    //            x.push(y);
-    //            ^ ...but data from `y` flows into `x` here
-    // It has been extended for the case of structs too.
-    // Consider the example
-    // struct Ref<'a> { x: &'a u32 }
-    // fn foo(mut x: Vec<Ref>, y: Ref) {
-    //                   ---      --- these structs are declared with different lifetimes...
-    //               x.push(y);
-    //               ^ ...but data from `y` flows into `x` here
-    // }
-    // It will later be extended to trait objects.
+    /// Print the error message for lifetime errors when both the concerned regions are anonymous.
+    ///
+    /// Consider a case where we have
+    ///
+    /// ```no_run
+    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
+    ///     x.push(y);
+    /// }
+    /// ```
+    ///
+    /// The example gives
+    ///
+    /// ```text
+    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
+    ///                    ---      --- these references are declared with different lifetimes...
+    ///     x.push(y);
+    ///     ^ ...but data from `y` flows into `x` here
+    /// ```
+    ///
+    /// It has been extended for the case of structs too.
+    ///
+    /// Consider the example
+    ///
+    /// ```no_run
+    /// struct Ref<'a> { x: &'a u32 }
+    /// ```
+    ///
+    /// ```text
+    /// fn foo(mut x: Vec<Ref>, y: Ref) {
+    ///                   ---      --- these structs are declared with different lifetimes...
+    ///     x.push(y);
+    ///     ^ ...but data from `y` flows into `x` here
+    /// }
+    /// ````
+    ///
+    /// It will later be extended to trait objects.
     pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
         let (span, sub, sup) = match *error {
             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
+            SubSupConflict(_, ref origin, sub, _, sup) => (origin.span(), sub, sup),
             _ => return false, // inapplicable
         };
 
index aac67b528c2d08d3b6a2b28d21d8a38c4bc407e1..e9916bd77e7582ea59880046bd41e4a0fe468653 100644 (file)
@@ -262,6 +262,27 @@ pub fn report_region_errors(&self,
                                 errors: &Vec<RegionResolutionError<'tcx>>) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
+        if self.tcx.sess.opts.debugging_opts.nll {
+            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");
+                    }
+
+                    RegionResolutionError::SubSupConflict(ref rvo, ..) => {
+                        self.tcx.sess.span_warn(
+                            rvo.span(),
+                            "not reporting region error due to -Znll");
+                    }
+                }
+            }
+
+            return;
+        }
+
         // try to pre-process the errors, which will group some of them
         // together into a `ProcessedErrors` group:
         let errors = self.process_errors(errors);
index 80fb4ce8e039260fc7933e0b4bfd37bcc94d2193..e0b8a193ede0c15e27c2be1a7cadffef572e60c7 100644 (file)
 use ty;
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    // This method generates the error message for the case when
-    // the function arguments consist of a named region and an anonymous
-    // region and corresponds to `ConcreteFailure(..)`
+    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
+    /// an anonymous region, emit an descriptive diagnostic error.
     pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
         let (span, sub, sup) = match *error {
             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
+            SubSupConflict(_, ref origin, sub, _, sup) => (origin.span(), sub, sup),
             _ => return false, // inapplicable
         };
 
-        debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})",
-               sub,
-               sup);
+        debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})", sub, sup);
 
         // Determine whether the sub and sup consist of one named region ('a)
         // and one anonymous (elided) region. If so, find the parameter arg
@@ -53,10 +51,8 @@ pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>
             };
 
         debug!("try_report_named_anon_conflict: named = {:?}", named);
-        debug!("try_report_named_anon_conflict: anon_arg_info = {:?}",
-               anon_arg_info);
-        debug!("try_report_named_anon_conflict: region_info = {:?}",
-               region_info);
+        debug!("try_report_named_anon_conflict: anon_arg_info = {:?}", anon_arg_info);
+        debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
 
         let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
                                                                        anon_arg_info.arg_ty,
@@ -101,6 +97,5 @@ pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>
                 .span_label(span, format!("lifetime `{}` required", named))
                 .emit();
         return true;
-
     }
 }
index 47db3f1b7926af1aa38c3b0991edb795cfe6f987..6bcd98a7a6814076552166a450e2256633c96ec0 100644 (file)
@@ -221,6 +221,7 @@ pub fn is_named_region(&self, region: Region<'tcx>) -> bool {
                     _ => false,
                 }
             }
+            ty::ReEarlyBound(_) => true,
             _ => false,
         }
     }
index 49f57d9aef50ec95a2b6a90f63f60d254550d35a..efe364166e4be6c14f7fcf08f5645a492cec8614 100644 (file)
@@ -30,6 +30,7 @@
 
 use std::borrow::Cow;
 use std::collections::hash_map::Entry::Vacant;
+use std::collections::btree_map::BTreeMap;
 use std::env;
 use std::fs::File;
 use std::io;
@@ -124,7 +125,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
 struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     graph_name: String,
     region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
-    map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
+    map: &'a BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
     node_ids: FxHashMap<Node, usize>,
 }
 
@@ -264,7 +265,7 @@ fn target(&self, edge: &Edge<'tcx>) -> Node {
     }
 }
 
-pub type ConstraintMap<'tcx> = FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
+pub type ConstraintMap<'tcx> = BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
 
 fn dump_region_constraints_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
                                               map: &ConstraintMap<'tcx>,
index 8351be490767ae100e44bfd40dc5465a9a435e58..f5327fad312375160855c06850c2323341234cd8 100644 (file)
@@ -28,6 +28,7 @@
 use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
 use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
 
+use std::collections::BTreeMap;
 use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::mem;
@@ -36,7 +37,7 @@
 mod graphviz;
 
 /// A constraint that influences the inference process.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
 pub enum Constraint<'tcx> {
     /// One region variable is subregion of another
     ConstrainVarSubVar(RegionVid, RegionVid),
@@ -186,7 +187,13 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// Constraints of the form `A <= B` introduced by the region
     /// checker.  Here at least one of `A` and `B` must be a region
     /// variable.
-    constraints: RefCell<FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,
+    ///
+    /// Using `BTreeMap` because the order in which we iterate over
+    /// these constraints can affect the way we build the region graph,
+    /// which in turn affects the way that region errors are reported,
+    /// leading to small variations in error output across runs and
+    /// platforms.
+    constraints: RefCell<BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,
 
     /// A "verify" is something that we need to verify after inference is
     /// done, but which does not directly affect inference in any way.
@@ -357,7 +364,7 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
             tcx,
             var_origins: RefCell::new(Vec::new()),
             values: RefCell::new(None),
-            constraints: RefCell::new(FxHashMap()),
+            constraints: RefCell::new(BTreeMap::new()),
             verifys: RefCell::new(Vec::new()),
             givens: RefCell::new(FxHashSet()),
             lubs: RefCell::new(FxHashMap()),
@@ -633,11 +640,15 @@ fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'
 
         debug!("RegionVarBindings: add_constraint({:?})", constraint);
 
-        if self.constraints.borrow_mut().insert(constraint, origin).is_none() {
+        // never overwrite an existing (constraint, origin) - only insert one if it isn't
+        // present in the map yet. This prevents origins from outside the snapshot being
+        // replaced with "less informative" origins e.g. during calls to `can_eq`
+        self.constraints.borrow_mut().entry(constraint).or_insert_with(|| {
             if self.in_snapshot() {
                 self.undo_log.borrow_mut().push(AddConstraint(constraint));
             }
-        }
+            origin
+        });
     }
 
     fn add_verify(&self, verify: Verify<'tcx>) {
index f4ba7890b170da6e3c55a4cfce9a07f1b8ca5bc8..628538b41c5d8ab9812e401ea2badf3475882717 100644 (file)
@@ -273,7 +273,7 @@ pub trait CrateStore {
     fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
     fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
     fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
-    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics;
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
     fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
 
@@ -327,7 +327,7 @@ fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>
         { bug!("crate_data_as_rc_any") }
     // item info
     fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
-    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics
         { bug!("item_generics_cloned") }
 
     // trait/impl-item info
index e62cc2a658a474cf6f1d75da9956ebc627afa813..0383d5ca68232d5b72fcafe9aa381a0ee86c2d3b 100644 (file)
@@ -31,7 +31,7 @@
 use syntax::ast;
 use syntax::ptr::P;
 use syntax_pos::Span;
-use util::nodemap::ItemLocalMap;
+use util::nodemap::ItemLocalSet;
 
 ///////////////////////////////////////////////////////////////////////////
 // The Delegate trait
@@ -279,7 +279,7 @@ pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
                param_env: ty::ParamEnv<'tcx>,
                region_scope_tree: &'a region::ScopeTree,
                tables: &'a ty::TypeckTables<'tcx>,
-               rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
+               rvalue_promotable_map: Option<Rc<ItemLocalSet>>)
                -> Self
     {
         ExprUseVisitor {
index 49a241b86e015046eb318be88fdca0226d101f0d..3bcdc4f7e2c630a860a483c733a9adbe69f95b2d 100644 (file)
@@ -182,6 +182,19 @@ pub fn lub_free_regions<'a, 'gcx>(&self,
         debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
         result
     }
+
+    /// Returns all regions that are known to outlive `r_a`. For
+    /// example, in a function:
+    ///
+    /// ```
+    /// fn foo<'a, 'b: 'a, 'c: 'b>() { .. }
+    /// ```
+    ///
+    /// if `r_a` represents `'a`, this function would return `{'b, 'c}`.
+    pub fn regions_that_outlive<'a, 'gcx>(&self, r_a: Region<'tcx>) -> Vec<&Region<'tcx>> {
+        assert!(is_free(r_a));
+        self.relation.greater_than(&r_a)
+    }
 }
 
 fn is_free(r: Region) -> bool {
index a38b37ff745f7d1b90244358f76ac1fe53518fce..19a43f3b5dd84e454852a3f6661371b59e6abb54 100644 (file)
@@ -229,7 +229,6 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     F32ImplItem,                     "f32",                     f32_impl;
     F64ImplItem,                     "f64",                     f64_impl;
 
-    SendTraitLangItem,               "send",                    send_trait;
     SizedTraitLangItem,              "sized",                   sized_trait;
     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
     CopyTraitLangItem,               "copy",                    copy_trait;
index e0e30f8831676aa28cb69b3a062a156b2a819ea8..4071f81ea51430c2057f97df455743ccf39a8cbe 100644 (file)
@@ -86,9 +86,9 @@
 
 use std::fmt;
 use std::rc::Rc;
-use util::nodemap::ItemLocalMap;
+use util::nodemap::ItemLocalSet;
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Categorization<'tcx> {
     Rvalue(ty::Region<'tcx>),              // temporary val, argument is its scope
     StaticItem,
@@ -109,7 +109,7 @@ pub struct Upvar {
 }
 
 // different kinds of pointers:
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub enum PointerKind<'tcx> {
     /// `Box<T>`
     Unique,
@@ -177,7 +177,7 @@ pub enum Note {
 // dereference, but its type is the type *before* the dereference
 // (`@T`). So use `cmt.ty` to find the type of the value in a consistent
 // fashion. For more details, see the method `cat_pattern`
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct cmt_<'tcx> {
     pub id: ast::NodeId,           // id of expr/pat producing this value
     pub span: Span,                // span of same expr/pat
@@ -286,7 +286,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
     pub region_scope_tree: &'a region::ScopeTree,
     pub tables: &'a ty::TypeckTables<'tcx>,
-    rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>,
+    rvalue_promotable_map: Option<Rc<ItemLocalSet>>,
     infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>,
 }
 
@@ -395,7 +395,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                region_scope_tree: &'a region::ScopeTree,
                tables: &'a ty::TypeckTables<'tcx>,
-               rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
+               rvalue_promotable_map: Option<Rc<ItemLocalSet>>)
                -> MemCategorizationContext<'a, 'tcx, 'tcx> {
         MemCategorizationContext {
             tcx,
@@ -750,12 +750,13 @@ fn cat_upvar(&self,
 
         let kind = match self.node_ty(fn_hir_id)?.sty {
             ty::TyGenerator(..) => ty::ClosureKind::FnOnce,
-            _ => {
+            ty::TyClosure(..) => {
                 match self.tables.closure_kinds().get(fn_hir_id) {
                     Some(&(kind, _)) => kind,
                     None => span_bug!(span, "missing closure kind"),
                 }
             }
+            ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t),
         };
 
         let closure_expr_def_index = self.tcx.hir.local_def_id(fn_node_id).index;
@@ -897,7 +898,7 @@ pub fn cat_rvalue_node(&self,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
         let hir_id = self.tcx.hir.node_to_hir_id(id);
-        let promotable = self.rvalue_promotable_map.as_ref().map(|m| m[&hir_id.local_id])
+        let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id))
                                                             .unwrap_or(false);
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
@@ -1499,41 +1500,6 @@ pub fn descriptive_string(&self, tcx: TyCtxt) -> String {
     }
 }
 
-impl<'tcx> fmt::Debug for cmt_<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{{{:?} id:{} m:{:?} ty:{:?}}}",
-               self.cat,
-               self.id,
-               self.mutbl,
-               self.ty)
-    }
-}
-
-impl<'tcx> fmt::Debug for Categorization<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Categorization::StaticItem => write!(f, "static"),
-            Categorization::Rvalue(r) => { write!(f, "rvalue({:?})", r) }
-            Categorization::Local(id) => {
-               let name = ty::tls::with(|tcx| tcx.hir.name(id));
-               write!(f, "local({})", name)
-            }
-            Categorization::Upvar(upvar) => {
-                write!(f, "upvar({:?})", upvar)
-            }
-            Categorization::Deref(ref cmt, ptr) => {
-                write!(f, "{:?}-{:?}->", cmt.cat, ptr)
-            }
-            Categorization::Interior(ref cmt, interior) => {
-                write!(f, "{:?}.{:?}", cmt.cat, interior)
-            }
-            Categorization::Downcast(ref cmt, _) => {
-                write!(f, "{:?}->(enum)", cmt.cat)
-            }
-        }
-    }
-}
-
 pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
     match ptr {
         Unique => "Box",
@@ -1547,27 +1513,6 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
     }
 }
 
-impl<'tcx> fmt::Debug for PointerKind<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Unique => write!(f, "Box"),
-            BorrowedPtr(ty::ImmBorrow, ref r) |
-            Implicit(ty::ImmBorrow, ref r) => {
-                write!(f, "&{:?}", r)
-            }
-            BorrowedPtr(ty::MutBorrow, ref r) |
-            Implicit(ty::MutBorrow, ref r) => {
-                write!(f, "&{:?} mut", r)
-            }
-            BorrowedPtr(ty::UniqueImmBorrow, ref r) |
-            Implicit(ty::UniqueImmBorrow, ref r) => {
-                write!(f, "&{:?} uniq", r)
-            }
-            UnsafePtr(_) => write!(f, "*")
-        }
-    }
-}
-
 impl fmt::Debug for InteriorKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
index 4c7ce4c09e25b4372b935ad8e4d845f33635d108..ffd06ee8a2e3abad7da087c578e789bbe5423790 100644 (file)
@@ -1001,8 +1001,12 @@ fn visit_segment_parameters(&mut self,
                 &map.object_lifetime_defaults[&id]
             } else {
                 let cstore = self.cstore;
+                let sess = self.sess;
                 self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
-                    cstore.item_generics_cloned_untracked(def_id).types.into_iter().map(|def| {
+                    cstore.item_generics_cloned_untracked(def_id, sess)
+                          .types
+                          .into_iter()
+                          .map(|def| {
                         def.object_lifetime_default
                     }).collect()
                 })
index b30d5e384884e7701df9a0d5f938fb168d8249f6..2f527413432bc16c7496aed3f957f45ed39240bd 100644 (file)
@@ -516,11 +516,13 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
             return;
         }
 
-        let lint_deprecated = |note: Option<Symbol>| {
+        let lint_deprecated = |def_id: DefId, note: Option<Symbol>| {
+            let path = self.item_path_str(def_id);
+
             let msg = if let Some(note) = note {
-                format!("use of deprecated item: {}", note)
+                format!("use of deprecated item '{}': {}", path, note)
             } else {
-                format!("use of deprecated item")
+                format!("use of deprecated item '{}'", path)
             };
 
             self.lint_node(lint::builtin::DEPRECATED, id, span, &msg);
@@ -538,7 +540,7 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
             };
 
             if !skip {
-                lint_deprecated(depr_entry.attr.note);
+                lint_deprecated(def_id, depr_entry.attr.note);
             }
         }
 
@@ -557,7 +559,7 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
         if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, .. }), ..})
                 = stability {
             if id != ast::DUMMY_NODE_ID {
-                lint_deprecated(Some(reason));
+                lint_deprecated(def_id, Some(reason));
             }
         }
 
index 2fc27de137faa13de7c59eb400e13ddc7e510711..cd0176506332aa1a8ee77c2155f3737070e6264a 100644 (file)
@@ -33,6 +33,7 @@
 use std::fmt::{self, Debug, Formatter, Write};
 use std::{iter, u32};
 use std::ops::{Index, IndexMut};
+use std::rc::Rc;
 use std::vec::IntoIter;
 use syntax::ast::{self, Name};
 use syntax_pos::Span;
@@ -266,10 +267,10 @@ pub fn source_info(&self, location: Location) -> &SourceInfo {
         let block = &self[location.block];
         let stmts = &block.statements;
         let idx = location.statement_index;
-        if location.statement_index < stmts.len() {
+        if idx < stmts.len() {
             &stmts[idx].source_info
         } else {
-            assert!(location.statement_index == stmts.len());
+            assert!(idx == stmts.len());
             &block.terminator().source_info
         }
     }
@@ -1683,6 +1684,15 @@ pub struct UnsafetyViolation {
     pub lint_node_id: Option<ast::NodeId>,
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct UnsafetyCheckResult {
+    /// Violations that are propagated *upwards* from this function
+    pub violations: Rc<[UnsafetyViolation]>,
+    /// unsafe blocks in this function, along with whether they are used. This is
+    /// used for the "unused_unsafe" lint.
+    pub unsafe_blocks: Rc<[(ast::NodeId, bool)]>,
+}
+
 /// The layout of generator state
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct GeneratorLayout<'tcx> {
index 47dbcee6394253b167b353541ce51b4d97bc1d9e..00863abc84deeb61b4e5652aadbdb399b34895fc 100644 (file)
@@ -209,7 +209,7 @@ fn visit_source_info(&mut self,
 
             fn visit_ty(&mut self,
                         ty: & $($mutability)* Ty<'tcx>,
-                        _: Lookup) {
+                        _: TyContext) {
                 self.super_ty(ty);
             }
 
@@ -256,8 +256,9 @@ fn visit_const_usize(&mut self,
             }
 
             fn visit_local_decl(&mut self,
+                                local: Local,
                                 local_decl: & $($mutability)* LocalDecl<'tcx>) {
-                self.super_local_decl(local_decl);
+                self.super_local_decl(local, local_decl);
             }
 
             fn visit_local(&mut self,
@@ -291,14 +292,14 @@ macro_rules! basic_blocks {
                     self.visit_visibility_scope_data(scope);
                 }
 
-                let lookup = Lookup::Src(SourceInfo {
+                let lookup = TyContext::SourceInfo(SourceInfo {
                     span: mir.span,
                     scope: ARGUMENT_VISIBILITY_SCOPE,
                 });
                 self.visit_ty(&$($mutability)* mir.return_ty, lookup);
 
-                for local_decl in &$($mutability)* mir.local_decls {
-                    self.visit_local_decl(local_decl);
+                for local in mir.local_decls.indices() {
+                    self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
                 }
 
                 self.visit_span(&$($mutability)* mir.span);
@@ -359,7 +360,8 @@ fn super_statement(&mut self,
                         for operand in lvalues {
                             self.visit_lvalue(& $($mutability)* operand.lval,
                                               LvalueContext::Validate, location);
-                            self.visit_ty(& $($mutability)* operand.ty, Lookup::Loc(location));
+                            self.visit_ty(& $($mutability)* operand.ty,
+                                          TyContext::Location(location));
                         }
                     }
                     StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
@@ -421,7 +423,7 @@ fn super_terminator_kind(&mut self,
                                                 ref values,
                                                 ref targets } => {
                         self.visit_operand(discr, source_location);
-                        self.visit_ty(switch_ty, Lookup::Loc(source_location));
+                        self.visit_ty(switch_ty, TyContext::Location(source_location));
                         for value in &values[..] {
                             self.visit_const_int(value, source_location);
                         }
@@ -545,7 +547,7 @@ fn super_rvalue(&mut self,
                                  ref $($mutability)* operand,
                                  ref $($mutability)* ty) => {
                         self.visit_operand(operand, location);
-                        self.visit_ty(ty, Lookup::Loc(location));
+                        self.visit_ty(ty, TyContext::Location(location));
                     }
 
                     Rvalue::BinaryOp(_bin_op,
@@ -567,7 +569,7 @@ fn super_rvalue(&mut self,
                     }
 
                     Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
-                        self.visit_ty(ty, Lookup::Loc(location));
+                        self.visit_ty(ty, TyContext::Location(location));
                     }
 
                     Rvalue::Aggregate(ref $($mutability)* kind,
@@ -575,7 +577,7 @@ fn super_rvalue(&mut self,
                         let kind = &$($mutability)* **kind;
                         match *kind {
                             AggregateKind::Array(ref $($mutability)* ty) => {
-                                self.visit_ty(ty, Lookup::Loc(location));
+                                self.visit_ty(ty, TyContext::Location(location));
                             }
                             AggregateKind::Tuple => {
                             }
@@ -645,7 +647,7 @@ fn super_static(&mut self,
                     ref $($mutability)* ty,
                 } = *static_;
                 self.visit_def_id(def_id, location);
-                self.visit_ty(ty, Lookup::Loc(location));
+                self.visit_ty(ty, TyContext::Location(location));
             }
 
             fn super_projection(&mut self,
@@ -675,7 +677,7 @@ fn super_projection_elem(&mut self,
                     ProjectionElem::Subslice { from: _, to: _ } => {
                     }
                     ProjectionElem::Field(_field, ref $($mutability)* ty) => {
-                        self.visit_ty(ty, Lookup::Loc(location));
+                        self.visit_ty(ty, TyContext::Location(location));
                     }
                     ProjectionElem::Index(ref $($mutability)* local) => {
                         self.visit_local(local, LvalueContext::Consume, location);
@@ -690,6 +692,7 @@ fn super_projection_elem(&mut self,
             }
 
             fn super_local_decl(&mut self,
+                                local: Local,
                                 local_decl: & $($mutability)* LocalDecl<'tcx>) {
                 let LocalDecl {
                     mutability: _,
@@ -701,7 +704,10 @@ fn super_local_decl(&mut self,
                     is_user_variable: _,
                 } = *local_decl;
 
-                self.visit_ty(ty, Lookup::Src(*source_info));
+                self.visit_ty(ty, TyContext::LocalDecl {
+                    local,
+                    source_info: *source_info,
+                });
                 self.visit_source_info(source_info);
                 self.visit_visibility_scope(lexical_scope);
             }
@@ -725,7 +731,7 @@ fn super_constant(&mut self,
                 } = *constant;
 
                 self.visit_span(span);
-                self.visit_ty(ty, Lookup::Loc(location));
+                self.visit_ty(ty, TyContext::Location(location));
                 self.visit_literal(literal, location);
             }
 
@@ -803,10 +809,21 @@ fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Locatio
 make_mir_visitor!(Visitor,);
 make_mir_visitor!(MutVisitor,mut);
 
+/// Extra information passed to `visit_ty` and friends to give context
+/// about where the type etc appears.
 #[derive(Copy, Clone, Debug)]
-pub enum Lookup {
-    Loc(Location),
-    Src(SourceInfo),
+pub enum TyContext {
+    LocalDecl {
+        /// The index of the local variable we are visiting.
+        local: Local,
+
+        /// The source location where this local variable was declared.
+        source_info: SourceInfo,
+    },
+
+    Location(Location),
+
+    SourceInfo(SourceInfo),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
index c4fc30429e0aabe965516f3fcd8c68d186c57a5f..3f53c89c9d6cbcc862d3d2653ec7458f0926f07f 100644 (file)
@@ -138,6 +138,34 @@ fn shorthand(&self) -> &'static str {
         }
     }
 
+    fn from_shorthand(shorthand: &str) -> Option<Self> {
+        Some(match shorthand {
+             "asm" => OutputType::Assembly,
+             "llvm-ir" => OutputType::LlvmAssembly,
+             "mir" => OutputType::Mir,
+             "llvm-bc" => OutputType::Bitcode,
+             "obj" => OutputType::Object,
+             "metadata" => OutputType::Metadata,
+             "link" => OutputType::Exe,
+             "dep-info" => OutputType::DepInfo,
+            _ => return None,
+        })
+    }
+
+    fn shorthands_display() -> String {
+        format!(
+            "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
+            OutputType::Bitcode.shorthand(),
+            OutputType::Assembly.shorthand(),
+            OutputType::LlvmAssembly.shorthand(),
+            OutputType::Mir.shorthand(),
+            OutputType::Object.shorthand(),
+            OutputType::Metadata.shorthand(),
+            OutputType::Exe.shorthand(),
+            OutputType::DepInfo.shorthand(),
+        )
+    }
+
     pub fn extension(&self) -> &'static str {
         match *self {
             OutputType::Bitcode => "bc",
@@ -368,6 +396,7 @@ pub enum PrintRequest {
     TargetFeatures,
     RelocationModels,
     CodeModels,
+    TlsModels,
     TargetSpec,
     NativeStaticLibs,
 }
@@ -1017,6 +1046,8 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
         "print high-level information about incremental reuse (or the lack thereof)"),
     incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
         "dump hash information in textual format to stdout"),
+    incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
+        "verify incr. comp. hashes of green query instances"),
     dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
           "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -1104,6 +1135,11 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
         "enable ThinLTO when possible"),
     inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "control whether #[inline] functions are in all cgus"),
+    tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
+         "choose the TLS model to use (rustc --print tls-models for details)"),
+    saturating_float_casts: bool = (false, parse_bool, [TRACKED],
+        "make float->int casts UB-free: numbers outside the integer type's range are clipped to \
+         the max/min integer respectively, and NaN is mapped to 0"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1330,7 +1366,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                                print on stdout",
                      "[crate-name|file-names|sysroot|cfg|target-list|\
                        target-cpus|target-features|relocation-models|\
-                       code-models|target-spec-json|native-static-libs]"),
+                       code-models|tls-models|target-spec-json|native-static-libs]"),
         opt::flagmulti_s("g",  "",  "Equivalent to -C debuginfo=2"),
         opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
         opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
@@ -1473,7 +1509,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         })
     });
 
-    let debugging_opts = build_debugging_options(matches, error_format);
+    let mut debugging_opts = build_debugging_options(matches, error_format);
 
     if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
         early_error(ErrorOutputType::Json(false),
@@ -1485,19 +1521,13 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         for list in matches.opt_strs("emit") {
             for output_type in list.split(',') {
                 let mut parts = output_type.splitn(2, '=');
-                let output_type = match parts.next().unwrap() {
-                    "asm" => OutputType::Assembly,
-                    "llvm-ir" => OutputType::LlvmAssembly,
-                    "mir" => OutputType::Mir,
-                    "llvm-bc" => OutputType::Bitcode,
-                    "obj" => OutputType::Object,
-                    "metadata" => OutputType::Metadata,
-                    "link" => OutputType::Exe,
-                    "dep-info" => OutputType::DepInfo,
-                    part => {
-                        early_error(error_format, &format!("unknown emission type: `{}`",
-                                                    part))
-                    }
+                let shorthand = parts.next().unwrap();
+                let output_type = match OutputType::from_shorthand(shorthand) {
+                    Some(output_type) => output_type,
+                    None => early_error(error_format, &format!(
+                        "unknown emission type: `{}` - expected one of: {}",
+                        shorthand, OutputType::shorthands_display(),
+                    )),
                 };
                 let path = parts.next().map(PathBuf::from);
                 output_types.insert(output_type, path);
@@ -1579,6 +1609,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         prints.push(PrintRequest::CodeModels);
         cg.code_model = None;
     }
+    if debugging_opts.tls_model.as_ref().map_or(false, |s| s == "help") {
+        prints.push(PrintRequest::TlsModels);
+        debugging_opts.tls_model = None;
+    }
 
     let cg = cg;
 
@@ -1678,6 +1712,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
             "target-features" => PrintRequest::TargetFeatures,
             "relocation-models" => PrintRequest::RelocationModels,
             "code-models" => PrintRequest::CodeModels,
+            "tls-models" => PrintRequest::TlsModels,
             "native-static-libs" => PrintRequest::NativeStaticLibs,
             "target-spec-json" => {
                 if nightly_options::is_unstable_enabled(matches) {
@@ -2520,6 +2555,10 @@ fn test_codegen_options_tracking_hash() {
         opts.cg.code_model = Some(String::from("code model"));
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
+        opts = reference.clone();
+        opts.debugging_opts.tls_model = Some(String::from("tls model"));
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
         opts = reference.clone();
         opts.cg.metadata = vec![String::from("A"), String::from("B")];
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
index 39cf50787effedeb7353e5fbf462ac03551bf1b0..00a91eeb9c18e17b77dff1de17330814506c49e1 100644 (file)
@@ -164,11 +164,13 @@ enum DiagnosticBuilderMethod {
     // add more variants as needed to support one-time diagnostics
 }
 
-/// Diagnostic message id - used in order to avoid emitting the same message more than once
+/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid
+/// emitting the same message more than once
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub enum DiagnosticMessageId {
+    ErrorId(u16), // EXXXX error code as integer
     LintId(lint::LintId),
-    StabilityId(u32)
+    StabilityId(u32) // issue number
 }
 
 impl Session {
index e2b23c12cf1f357bf2728532f3ce62102a9a6cc1..106b1b08656f2f40e85aa49b37fee9cb84f17bdf 100644 (file)
@@ -36,6 +36,7 @@
 use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
 use std::fmt;
 use syntax::ast;
+use session::DiagnosticMessageId;
 use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
 use ty::error::ExpectedFound;
 use ty::fast_reject;
@@ -219,13 +220,19 @@ fn report_projection_error(&self,
                 }
             }
 
-            let mut diag = struct_span_err!(
-                self.tcx.sess, obligation.cause.span, E0271,
-                "type mismatch resolving `{}`", predicate
-            );
-            self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-            self.note_obligation_cause(&mut diag, obligation);
-            diag.emit();
+            let msg = format!("type mismatch resolving `{}`", predicate);
+            let error_id = (DiagnosticMessageId::ErrorId(271),
+                            Some(obligation.cause.span), msg.clone());
+            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                let mut diag = struct_span_err!(
+                    self.tcx.sess, obligation.cause.span, E0271,
+                    "type mismatch resolving `{}`", predicate
+                );
+                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                self.note_obligation_cause(&mut diag, obligation);
+                diag.emit();
+            }
         });
     }
 
index 1e9816095ea2ec419330dc3b154f20ee5080b869..facd6350e196c2eda53a83343f2efdab64a38c6b 100644 (file)
@@ -23,6 +23,7 @@
 use traits;
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::subst::Substs;
+use ty::util::ExplicitSelf;
 use std::borrow::Cow;
 use syntax::ast;
 
@@ -57,6 +58,10 @@ pub fn error_msg(&self) -> Cow<'static, str> {
                          in its arguments or return type", name).into(),
             ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
                 format!("method `{}` has generic type parameters", name).into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::NonStandardSelfType) =>
+                format!("method `{}` has a non-standard `self` type. Only `&self`, \
+                        `&mut self`, and `Box<Self>` are currently supported \
+                        for trait objects", name).into(),
             ObjectSafetyViolation::AssociatedConst(name) =>
                 format!("the trait cannot contain associated consts like `{}`", name).into(),
         }
@@ -74,6 +79,9 @@ pub enum MethodViolationCode {
 
     /// e.g., `fn foo<A>()`
     Generic,
+
+    /// arbitrary `self` type, e.g. `self: Rc<Self>`
+    NonStandardSelfType,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -260,9 +268,16 @@ fn virtual_call_violation_for_method(self,
             return Some(MethodViolationCode::StaticMethod);
         }
 
+        let sig = self.fn_sig(method.def_id);
+
+        let self_ty = self.mk_self_type();
+        let self_arg_ty = sig.skip_binder().inputs()[0];
+        if let ExplicitSelf::Other = ExplicitSelf::determine(self_arg_ty, |ty| ty == self_ty) {
+            return Some(MethodViolationCode::NonStandardSelfType);
+        }
+
         // The `Self` type is erased, so it should not appear in list of
         // arguments or return type apart from the receiver.
-        let ref sig = self.fn_sig(method.def_id);
         for input_ty in &sig.skip_binder().inputs()[1..] {
             if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                 return Some(MethodViolationCode::ReferencesSelf);
index 94f6efcad4adc7efdee2cd0ed6e47edf74f229f4..16e200d56f9fbe3c4c584225cb3f823b25c83b9a 100644 (file)
@@ -254,7 +254,7 @@ fn verify(&self,
                         }
                     },
                     // `{:1}` and `{}` are not to be used
-                    Position::ArgumentIs(_) => {
+                    Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
                         span_err!(tcx.sess, span, E0231,
                                   "only named substitution \
                                    parameters are allowed");
index 24c19bfc3f3f00f7ab78ad843457db824fde07b9..0fecb5314bf440a640c5f007a2a9ce0f45d32934 100644 (file)
@@ -151,9 +151,23 @@ pub fn try_push_visible_item_path<T>(self, buffer: &mut T, external_def_id: DefI
                 }
             }
 
-            cur_path.push(self.def_key(cur_def)
-                              .disambiguated_data.data.get_opt_name().unwrap_or_else(||
-                Symbol::intern("<unnamed>").as_str()));
+            let mut cur_def_key = self.def_key(cur_def);
+
+            // For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
+            if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
+                let parent = DefId {
+                    krate: cur_def.krate,
+                    index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
+                };
+
+                cur_def_key = self.def_key(parent);
+            }
+
+            let data = cur_def_key.disambiguated_data.data;
+            let symbol =
+                data.get_opt_name().unwrap_or_else(|| Symbol::intern("<unnamed>").as_str());
+            cur_path.push(symbol);
+
             match visible_parent_map.get(&cur_def) {
                 Some(&def) => cur_def = def,
                 None => return false,
index 7d8586741fb156557ea7bdd3de6a7afdb26c0b52..320f65148498712c3b5cbfdcc87cf914f845e54b 100644 (file)
@@ -37,7 +37,7 @@
 use ty::layout::{Layout, LayoutError};
 use ty::steal::Steal;
 use ty::subst::Substs;
-use util::nodemap::{DefIdSet, DefIdMap, ItemLocalMap};
+use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
 use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
     /// the value isn't known except to the pass itself.
     [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Rc<IdxSetBuf<mir::Local>>),
 
+    /// Fetch the MIR for a given def-id right after it's built - this includes
+    /// unreachable code.
+    [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
+
     /// Fetch the MIR for a given def-id up till the point where it is
     /// ready for const evaluation.
     ///
     /// expression defining the closure.
     [] fn closure_kind: ClosureKind(DefId) -> ty::ClosureKind,
 
-    /// Unsafety violations for this def ID.
-    [] fn unsafety_violations: UnsafetyViolations(DefId)
-        -> Rc<[mir::UnsafetyViolation]>,
+    /// The result of unsafety-checking this def-id.
+    [] fn unsafety_check_result: UnsafetyCheckResult(DefId) -> mir::UnsafetyCheckResult,
 
     /// The signature of functions and closures.
     [] fn fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>,
     [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
     [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
     [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
-    [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Rc<ItemLocalMap<bool>>,
+    [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Rc<ItemLocalSet>,
     [] fn is_mir_available: IsMirAvailable(DefId) -> bool,
     [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
                           -> Rc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>,
index 26581501234af1b67f0449861d52e408e7db4bc2..24ce8fb2995983de53543d5488dfb8ffc7d04299 100644 (file)
@@ -165,7 +165,7 @@ impl<'a> CacheDecoder<'a> {
     fn find_filemap_prev_bytepos(&self,
                                  prev_bytepos: BytePos)
                                  -> Option<(BytePos, StableFilemapId)> {
-        for (start, id) in self.prev_filemap_starts.range(BytePos(0) ... prev_bytepos).rev() {
+        for (start, id) in self.prev_filemap_starts.range(BytePos(0) ..= prev_bytepos).rev() {
             return Some((*start, *id))
         }
 
index cc698cf03da98913131c6d88a51551d8510e8984..590d5b8e62f1a056268e0632041703a207b0e69c 100644 (file)
@@ -327,7 +327,8 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                         return Self::load_from_disk_and_cache_in_memory(tcx,
                                                                         key,
                                                                         span,
-                                                                        dep_node_index)
+                                                                        dep_node_index,
+                                                                        &dep_node)
                     }
                 }
 
@@ -372,7 +373,8 @@ fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
             fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                                                   key: $K,
                                                   span: Span,
-                                                  dep_node_index: DepNodeIndex)
+                                                  dep_node_index: DepNodeIndex,
+                                                  dep_node: &DepNode)
                                                   -> Result<$V, CycleError<'a, $tcx>>
             {
                 debug_assert!(tcx.dep_graph.is_green(dep_node_index));
@@ -390,6 +392,32 @@ fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                     })
                 })?;
 
+                // If -Zincremental-verify-ich is specified, re-hash results from
+                // the cache and make sure that they have the expected fingerprint.
+                if tcx.sess.opts.debugging_opts.incremental_verify_ich {
+                    use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+                    use ich::Fingerprint;
+
+                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node)) ==
+                            tcx.dep_graph.prev_fingerprint_of(dep_node),
+                            "Fingerprint for green query instance not loaded \
+                             from cache: {:?}", dep_node);
+
+                    debug!("BEGIN verify_ich({:?})", dep_node);
+                    let mut hcx = tcx.create_stable_hashing_context();
+                    let mut hasher = StableHasher::new();
+
+                    result.hash_stable(&mut hcx, &mut hasher);
+
+                    let new_hash: Fingerprint = hasher.finish();
+                    debug!("END verify_ich({:?})", dep_node);
+
+                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node);
+
+                    assert!(new_hash == old_hash, "Found unstable fingerprints \
+                        for {:?}", dep_node);
+                }
+
                 if tcx.sess.opts.debugging_opts.query_dep_graph {
                     tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
                 }
@@ -693,9 +721,8 @@ macro_rules! force {
         DepKind::EraseRegionsTy |
         DepKind::NormalizeTy |
 
-        // These are just odd
-        DepKind::Null |
-        DepKind::WorkProduct => {
+        // This one should never occur in this context
+        DepKind::Null => {
             bug!("force_from_dep_node() - Encountered {:?}", dep_node.kind)
         }
 
@@ -712,6 +739,7 @@ macro_rules! force {
             force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
         },
         DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
+        DepKind::MirBuilt => { force!(mir_built, def_id!()); }
         DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
         DepKind::MirConst => { force!(mir_const, def_id!()); }
         DepKind::MirValidated => { force!(mir_validated, def_id!()); }
@@ -719,7 +747,7 @@ macro_rules! force {
 
         DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
         DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
-        DepKind::UnsafetyViolations => { force!(unsafety_violations, def_id!()); }
+        DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
         DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
         DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
         DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
@@ -852,4 +880,3 @@ macro_rules! force {
 
     true
 }
-
index d0ac7d0183a582da6385c9cc8c2b3490bd349714..a60cad0de9f76b32fdbb9cc09097816c385bb6a6 100644 (file)
@@ -760,7 +760,7 @@ pub fn is_self(&self) -> bool {
 /// is the outer fn.
 ///
 /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy, PartialOrd, Ord)]
 pub struct DebruijnIndex {
     /// We maintain the invariant that this is never 0. So 1 indicates
     /// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
@@ -825,7 +825,7 @@ pub struct DebruijnIndex {
 ///
 /// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     // Region bound in a type or fn declaration which will be
     // substituted 'early' -- that is, at the same time when type
@@ -871,7 +871,7 @@ pub enum RegionKind {
 
 impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, PartialOrd, Ord)]
 pub struct EarlyBoundRegion {
     pub def_id: DefId,
     pub index: u32,
@@ -893,12 +893,12 @@ pub struct FloatVid {
     pub index: u32,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, PartialOrd, Ord)]
 pub struct RegionVid {
     pub index: u32,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub struct SkolemizedRegionVid {
     pub index: u32,
 }
index 39842a543b54bf6b6fd781c478ac642bfa9f0a9f..d12a973017d9bd64856bf89b4d7e14f8598c7195 100644 (file)
@@ -12,6 +12,7 @@
 
 use hir::def_id::{DefId, LOCAL_CRATE};
 use hir::map::DefPathData;
+use hir;
 use ich::NodeIdHashingMode;
 use middle::const_val::ConstVal;
 use traits::{self, Reveal};
@@ -1178,6 +1179,58 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     layout
 }
 
+pub enum ExplicitSelf<'tcx> {
+    ByValue,
+    ByReference(ty::Region<'tcx>, hir::Mutability),
+    ByBox,
+    Other
+}
+
+impl<'tcx> ExplicitSelf<'tcx> {
+    /// Categorizes an explicit self declaration like `self: SomeType`
+    /// into either `self`, `&self`, `&mut self`, `Box<self>`, or
+    /// `Other`.
+    /// This is mainly used to require the arbitrary_self_types feature
+    /// in the case of `Other`, to improve error messages in the common cases,
+    /// and to make `Other` non-object-safe.
+    ///
+    /// Examples:
+    ///
+    /// ```
+    /// impl<'a> Foo for &'a T {
+    ///     // Legal declarations:
+    ///     fn method1(self: &&'a T); // ExplicitSelf::ByReference
+    ///     fn method2(self: &'a T); // ExplicitSelf::ByValue
+    ///     fn method3(self: Box<&'a T>); // ExplicitSelf::ByBox
+    ///     fn method4(self: Rc<&'a T>); // ExplicitSelf::Other
+    ///
+    ///     // Invalid cases will be caught by `check_method_receiver`:
+    ///     fn method_err1(self: &'a mut T); // ExplicitSelf::Other
+    ///     fn method_err2(self: &'static T) // ExplicitSelf::ByValue
+    ///     fn method_err3(self: &&T) // ExplicitSelf::ByReference
+    /// }
+    /// ```
+    ///
+    pub fn determine<P>(
+        self_arg_ty: Ty<'tcx>,
+        is_self_ty: P
+    ) -> ExplicitSelf<'tcx>
+    where
+        P: Fn(Ty<'tcx>) -> bool
+    {
+        use self::ExplicitSelf::*;
+
+        match self_arg_ty.sty {
+            _ if is_self_ty(self_arg_ty) => ByValue,
+            ty::TyRef(region, ty::TypeAndMut { ty, mutbl}) if is_self_ty(ty) => {
+                ByReference(region, mutbl)
+            }
+            ty::TyAdt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox,
+            _ => Other
+        }
+    }
+}
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     *providers = ty::maps::Providers {
         is_copy_raw,
index c397371c5c7672021fcca82928b05eb20ad49199..674f67d5cd2f188b6dc7d89dc849de8c5c4969dc 100644 (file)
 
 pub type NodeSet = FxHashSet<ast::NodeId>;
 pub type DefIdSet = FxHashSet<DefId>;
+pub type ItemLocalSet = FxHashSet<ItemLocalId>;
 
 pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
 pub fn DefIdMap<T>() -> DefIdMap<T> { FxHashMap() }
 pub fn ItemLocalMap<T>() -> ItemLocalMap<T> { FxHashMap() }
 pub fn NodeSet() -> NodeSet { FxHashSet() }
 pub fn DefIdSet() -> DefIdSet { FxHashSet() }
+pub fn ItemLocalSet() -> ItemLocalSet { FxHashSet() }
 
index 9e348f622232961aa01152112d6908fc17f6881f..09c9cecdceee6ffa016aa62af12dfa598be33ae8 100644 (file)
@@ -96,7 +96,7 @@ pub fn and<T>(self, value: T) -> StatusAnd<T> {
 }
 
 impl<T> StatusAnd<T> {
-    fn map<F: FnOnce(T) -> U, U>(self, f: F) -> StatusAnd<U> {
+    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> StatusAnd<U> {
         StatusAnd {
             status: self.status,
             value: f(self.value),
@@ -378,7 +378,7 @@ fn copy_sign(self, rhs: Self) -> Self {
     fn from_bits(input: u128) -> Self;
     fn from_i128_r(input: i128, round: Round) -> StatusAnd<Self> {
         if input < 0 {
-            Self::from_u128_r(-input as u128, -round).map(|r| -r)
+            Self::from_u128_r(input.wrapping_neg() as u128, -round).map(|r| -r)
         } else {
             Self::from_u128_r(input as u128, round)
         }
index 730abc54568e1364e12747db4329b8caea0acd1d..92b024b67d4cc3227d8e15e24fc5c2f2aa577a28 100644 (file)
@@ -12,6 +12,7 @@ crate-type = ["dylib"]
 syntax = { path = "../libsyntax" }
 serialize = { path = "../libserialize" }
 log = "0.3"
+rand = "0.3"
 
 [features]
 jemalloc = []
index 6a9833d3784a487c637661e9f98312b179aec187..d67de123415f2ddfd2a8d1c7cbe7cb2551b2fc6b 100644 (file)
 #![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(libc)]
-#![feature(rand)]
-#![cfg_attr(test, feature(rand))]
 
 extern crate syntax;
 extern crate libc;
+extern crate rand;
 extern crate serialize;
 #[macro_use] extern crate log;
 
index a56d067815819c9df04f2f814917a2c9caf00af3..8fd4aad89c643d4cec7a775794a33c00f816a845 100644 (file)
@@ -311,6 +311,9 @@ pub struct TargetOptions {
     pub relocation_model: String,
     /// Code model to use. Corresponds to `llc -code-model=$code_model`. Defaults to "default".
     pub code_model: String,
+    /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
+    /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
+    pub tls_model: String,
     /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
     pub disable_redzone: bool,
     /// Eliminate frame pointers from stack frames if possible. Defaults to true.
@@ -450,6 +453,7 @@ fn default() -> TargetOptions {
             executables: false,
             relocation_model: "pic".to_string(),
             code_model: "default".to_string(),
+            tls_model: "global-dynamic".to_string(),
             disable_redzone: false,
             eliminate_frame_pointer: true,
             function_sections: true,
@@ -696,6 +700,7 @@ macro_rules! key {
         key!(executables, bool);
         key!(relocation_model);
         key!(code_model);
+        key!(tls_model);
         key!(disable_redzone, bool);
         key!(eliminate_frame_pointer, bool);
         key!(function_sections, bool);
@@ -888,6 +893,7 @@ macro_rules! target_option_val {
         target_option_val!(executables);
         target_option_val!(relocation_model);
         target_option_val!(code_model);
+        target_option_val!(tls_model);
         target_option_val!(disable_redzone);
         target_option_val!(eliminate_frame_pointer);
         target_option_val!(function_sections);
index 8ffaddd7c29f2634cfd44c6a5fbbdc503b2409e6..1a2515366224c04cb585884fc110c90e1dd40073 100644 (file)
@@ -12,7 +12,7 @@
 use std::io::{self, Error, ErrorKind};
 use std::fs;
 use std::path::{self, PathBuf, Path};
-use std::__rand::{thread_rng, Rng};
+use rand::{thread_rng, Rng};
 
 /// A wrapper for a path to temporary directory implementing automatic
 /// scope-based deletion.
index e6a04c9c57a6c05eba0cf2b049b28beb37546a67..98ed8d99fda70973fb5a00bfbc7de6d3ea5b2b8d 100644 (file)
@@ -260,7 +260,14 @@ fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
                 "refutable pattern in {}: `{}` not covered",
                 origin, pattern_string
             );
-            diag.span_label(pat.span, format!("pattern `{}` not covered", pattern_string));
+            let label_msg = match pat.node {
+                PatKind::Path(hir::QPath::Resolved(None, ref path))
+                        if path.segments.len() == 1 && path.segments[0].parameters.is_none() => {
+                    format!("interpreted as a {} pattern, not new variable", path.def.kind_name())
+                }
+                _ => format!("pattern `{}` not covered", pattern_string),
+            };
+            diag.span_label(pat.span, label_msg);
             diag.emit();
         });
     }
index b67048939e43eb1592bc6c378aeeb02634b207a2..9d820ea8cbed2990e91ab163aee9416840f8e8b1 100644 (file)
@@ -203,3 +203,11 @@ fn neg(self) -> Self {
         ConstFloat { bits, ty: self.ty }
     }
 }
+
+/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this
+/// are rounded to infinity when converted to `f32`.
+///
+/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP)
+/// shifted by the maximum exponent (accounting for normalization).
+pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
+                                        << (Single::MAX_EXP - Single::PRECISION as i16);
index e8f9a6720872d5ec21374e0b8fbba97865400ee4..94edaa746f915b08a6d2f83f77888288e4affd72 100644 (file)
@@ -145,7 +145,7 @@ pub struct BitMatrix {
 }
 
 impl BitMatrix {
-    // Create a new `rows x columns` matrix, initially empty.
+    /// Create a new `rows x columns` matrix, initially empty.
     pub fn new(rows: usize, columns: usize) -> BitMatrix {
         // For every element, we need one bit for every other
         // element. Round up to an even number of u64s.
@@ -163,9 +163,13 @@ fn range(&self, row: usize) -> (usize, usize) {
         (start, start + u64s_per_row)
     }
 
-    pub fn add(&mut self, source: usize, target: usize) -> bool {
-        let (start, _) = self.range(source);
-        let (word, mask) = word_mask(target);
+    /// Sets the cell at `(row, column)` to true. Put another way, add
+    /// `column` to the bitset for `row`.
+    ///
+    /// Returns true if this changed the matrix, and false otherwies.
+    pub fn add(&mut self, row: usize, column: usize) -> bool {
+        let (start, _) = self.range(row);
+        let (word, mask) = word_mask(column);
         let vector = &mut self.vector[..];
         let v1 = vector[start + word];
         let v2 = v1 | mask;
@@ -173,19 +177,19 @@ pub fn add(&mut self, source: usize, target: usize) -> bool {
         v1 != v2
     }
 
-    /// Do the bits from `source` contain `target`?
-    ///
-    /// Put another way, if the matrix represents (transitive)
-    /// reachability, can `source` reach `target`?
-    pub fn contains(&self, source: usize, target: usize) -> bool {
-        let (start, _) = self.range(source);
-        let (word, mask) = word_mask(target);
+    /// Do the bits from `row` contain `column`? Put another way, is
+    /// the matrix cell at `(row, column)` true?  Put yet another way,
+    /// if the matrix represents (transitive) reachability, can
+    /// `row` reach `column`?
+    pub fn contains(&self, row: usize, column: usize) -> bool {
+        let (start, _) = self.range(row);
+        let (word, mask) = word_mask(column);
         (self.vector[start + word] & mask) != 0
     }
 
-    /// Returns those indices that are reachable from both `a` and
-    /// `b`. This is an O(n) operation where `n` is the number of
-    /// elements (somewhat independent from the actual size of the
+    /// Returns those indices that are true in rows `a` and `b`.  This
+    /// is an O(n) operation where `n` is the number of elements
+    /// (somewhat independent from the actual size of the
     /// intersection, in particular).
     pub fn intersection(&self, a: usize, b: usize) -> Vec<usize> {
         let (a_start, a_end) = self.range(a);
@@ -206,7 +210,7 @@ pub fn intersection(&self, a: usize, b: usize) -> Vec<usize> {
         result
     }
 
-    /// Add the bits from `read` to the bits from `write`,
+    /// Add the bits from row `read` to the bits from row `write`,
     /// return true if anything changed.
     ///
     /// This is used when computing transitive reachability because if
@@ -227,6 +231,8 @@ pub fn merge(&mut self, read: usize, write: usize) -> bool {
         changed
     }
 
+    /// Iterates through all the columns set to true in a given row of
+    /// the matrix.
     pub fn iter<'a>(&'a self, row: usize) -> BitVectorIter<'a> {
         let (start, end) = self.range(row);
         BitVectorIter {
index 7cb386b019798d3ecce2a1f015d4a867d3fb1d79..933e08811ce5d6a647de68f4f8e08e6b855a9d15 100644 (file)
@@ -134,12 +134,12 @@ pub fn contains(&self, a: &T, b: &T) -> bool {
         }
     }
 
-    /// Returns a vector of all things less than `a`.
+    /// Returns a vector of all things greater than `a`.
     ///
     /// Really this probably ought to be `impl Iterator<Item=&T>`, but
     /// I'm too lazy to make that work, and -- given the caching
     /// strategy -- it'd be a touch tricky anyhow.
-    pub fn less_than(&self, a: &T) -> Vec<&T> {
+    pub fn greater_than(&self, a: &T) -> Vec<&T> {
         match self.index(a) {
             Some(a) => self.with_closure(|closure| {
                 closure.iter(a.0).map(|i| &self.elements[i]).collect()
index fc503f4eb4be16ac33422a19e07da7f61f76d358..c5cce70c945663393d38cdd27756c55bce9cda02 100644 (file)
@@ -177,6 +177,7 @@ pub mod back {
         pub mod write {
             pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
             pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
+            pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = [];
         }
     }
 }
@@ -797,6 +798,13 @@ fn print_crate_info(sess: &Session,
                     }
                     println!("");
                 }
+                PrintRequest::TlsModels => {
+                    println!("Available TLS models:");
+                    for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){
+                        println!("    {}", name);
+                    }
+                    println!("");
+                }
                 PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
                     rustc_trans::print(*req, sess);
                 }
index 2d70de89355ee2a729d2e30885e45811c273fd1f..c7e9c8268f0b32d977cf5c33afdde49a1d253901 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use CodeSuggestion;
+use SubstitutionPart;
 use Substitution;
 use Level;
 use RenderSpan;
@@ -217,9 +218,11 @@ pub fn span_help<S: Into<MultiSpan>>(&mut self,
     /// See `CodeSuggestion` for more information.
     pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
-            substitution_parts: vec![Substitution {
-                span: sp,
-                substitutions: vec![suggestion],
+            substitutions: vec![Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet: suggestion,
+                    span: sp,
+                }],
             }],
             msg: msg.to_owned(),
             show_code_when_inline: false,
@@ -245,9 +248,11 @@ pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String)
     /// See `CodeSuggestion` for more information.
     pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
-            substitution_parts: vec![Substitution {
-                span: sp,
-                substitutions: vec![suggestion],
+            substitutions: vec![Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet: suggestion,
+                    span: sp,
+                }],
             }],
             msg: msg.to_owned(),
             show_code_when_inline: true,
@@ -258,10 +263,12 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &m
     /// Prints out a message with multiple suggested edits of the code.
     pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
-            substitution_parts: vec![Substitution {
-                span: sp,
-                substitutions: suggestions,
-            }],
+            substitutions: suggestions.into_iter().map(|snippet| Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet,
+                    span: sp,
+                }],
+            }).collect(),
             msg: msg.to_owned(),
             show_code_when_inline: true,
         });
index 6c43c60686ee424e2aa458ff70ac6ea212438c21..0e39f29204d1e2cf8a0b69aa75f6fc39728addc2 100644 (file)
@@ -38,15 +38,15 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
 
         if let Some((sugg, rest)) = db.suggestions.split_first() {
             if rest.is_empty() &&
-               // don't display multipart suggestions as labels
-               sugg.substitution_parts.len() == 1 &&
                // don't display multi-suggestions as labels
-               sugg.substitutions() == 1 &&
+               sugg.substitutions.len() == 1 &&
+               // don't display multipart suggestions as labels
+               sugg.substitutions[0].parts.len() == 1 &&
                // don't display long messages as labels
                sugg.msg.split_whitespace().count() < 10 &&
                // don't display multiline suggestions as labels
-               sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
-                let substitution = &sugg.substitution_parts[0].substitutions[0];
+               !sugg.substitutions[0].parts[0].snippet.contains('\n') {
+                let substitution = &sugg.substitutions[0].parts[0].snippet;
                 let msg = if substitution.len() == 0 || !sugg.show_code_when_inline {
                     // This substitution is only removal or we explicitly don't want to show the
                     // code inline, don't show it
@@ -54,7 +54,7 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
                 } else {
                     format!("help: {}: `{}`", sugg.msg, substitution)
                 };
-                primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
+                primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
             } else {
                 // if there are multiple suggestions, print them all in full
                 // to be consistent. We could try to figure out if we can
@@ -1098,14 +1098,10 @@ fn emit_suggestion_default(&mut self,
                                -> io::Result<()> {
         use std::borrow::Borrow;
 
-        let primary_sub = &suggestion.substitution_parts[0];
         if let Some(ref cm) = self.cm {
             let mut buffer = StyledBuffer::new();
 
-            let lines = cm.span_to_lines(primary_sub.span).unwrap();
-
-            assert!(!lines.lines.is_empty());
-
+            // Render the suggestion message
             buffer.append(0, &level.to_string(), Style::Level(level.clone()));
             buffer.append(0, ": ", Style::HeaderMsg);
             self.msg_to_buffer(&mut buffer,
@@ -1114,14 +1110,22 @@ fn emit_suggestion_default(&mut self,
                                "suggestion",
                                Some(Style::HeaderMsg));
 
+            // Render the replacements for each suggestion
             let suggestions = suggestion.splice_lines(cm.borrow());
-            let span_start_pos = cm.lookup_char_pos(primary_sub.span.lo());
-            let line_start = span_start_pos.line;
-            draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
+
             let mut row_num = 2;
-            for (&(ref complete, show_underline), ref sub) in suggestions
-                    .iter().zip(primary_sub.substitutions.iter()).take(MAX_SUGGESTIONS)
-            {
+            for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
+                let show_underline = parts.len() == 1
+                    && complete.lines().count() == 1
+                    && parts[0].snippet.trim() != complete.trim();
+
+                let lines = cm.span_to_lines(parts[0].span).unwrap();
+
+                assert!(!lines.lines.is_empty());
+
+                let span_start_pos = cm.lookup_char_pos(parts[0].span.lo());
+                let line_start = span_start_pos.line;
+                draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
                 let mut line_pos = 0;
                 // Only show underline if there's a single suggestion and it is a single line
                 let mut lines = complete.lines();
@@ -1136,21 +1140,22 @@ fn emit_suggestion_default(&mut self,
                     buffer.append(row_num, line, Style::NoStyle);
                     line_pos += 1;
                     row_num += 1;
-                    // Only show an underline in the suggestions if the suggestion is not the
-                    // entirety of the code being shown and the displayed code is not multiline.
-                    if show_underline {
-                        draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                        let sub_len = sub.trim_right().len();
-                        let underline_start = span_start_pos.col.0;
-                        let underline_end = span_start_pos.col.0 + sub_len;
-                        for p in underline_start..underline_end {
-                            buffer.putc(row_num,
-                                        max_line_num_len + 3 + p,
-                                        '^',
-                                        Style::UnderlinePrimary);
-                        }
-                        row_num += 1;
+                }
+                // Only show an underline in the suggestions if the suggestion is not the
+                // entirety of the code being shown and the displayed code is not multiline.
+                if show_underline {
+                    draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
+                    let start = parts[0].snippet.len() - parts[0].snippet.trim_left().len();
+                    let sub_len = parts[0].snippet.trim().len();
+                    let underline_start = span_start_pos.col.0 + start;
+                    let underline_end = span_start_pos.col.0 + sub_len;
+                    for p in underline_start..underline_end {
+                        buffer.putc(row_num,
+                                    max_line_num_len + 3 + p,
+                                    '^',
+                                    Style::UnderlinePrimary);
                     }
+                    row_num += 1;
                 }
 
                 // if we elided some lines, add an ellipsis
index b30ee7016ab1cee7a7dbb1d237b0719ba58a5613..7bf64d2432571ae8fc02f0b2c95177d1ebd8a9fa 100644 (file)
@@ -76,17 +76,20 @@ pub struct CodeSuggestion {
     ///
     /// ```
     /// vec![
-    ///     (0..3, vec!["a", "x"]),
-    ///     (4..7, vec!["b", "y"]),
+    ///     Substitution { parts: vec![(0..3, "a"), (4..7, "b")] },
+    ///     Substitution { parts: vec![(0..3, "x"), (4..7, "y")] },
     /// ]
     /// ```
     ///
     /// or by replacing the entire span:
     ///
     /// ```
-    /// vec![(0..7, vec!["a.b", "x.y"])]
+    /// vec![
+    ///     Substitution { parts: vec![(0..7, "a.b")] },
+    ///     Substitution { parts: vec![(0..7, "x.y")] },
+    /// ]
     /// ```
-    pub substitution_parts: Vec<Substitution>,
+    pub substitutions: Vec<Substitution>,
     pub msg: String,
     pub show_code_when_inline: bool,
 }
@@ -94,8 +97,13 @@ pub struct CodeSuggestion {
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 /// See the docs on `CodeSuggestion::substitutions`
 pub struct Substitution {
+    pub parts: Vec<SubstitutionPart>,
+}
+
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub struct SubstitutionPart {
     pub span: Span,
-    pub substitutions: Vec<String>,
+    pub snippet: String,
 }
 
 pub trait CodeMapper {
@@ -109,18 +117,8 @@ pub trait CodeMapper {
 }
 
 impl CodeSuggestion {
-    /// Returns the number of substitutions
-    fn substitutions(&self) -> usize {
-        self.substitution_parts[0].substitutions.len()
-    }
-
-    /// Returns the number of substitutions
-    fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
-        self.substitution_parts.iter().map(|sub| sub.span)
-    }
-
-    /// Returns the assembled code suggestions and wether they should be shown with an underline.
-    pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, bool)> {
+    /// Returns the assembled code suggestions and whether they should be shown with an underline.
+    pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, Vec<SubstitutionPart>)> {
         use syntax_pos::{CharPos, Loc, Pos};
 
         fn push_trailing(buf: &mut String,
@@ -142,60 +140,42 @@ fn push_trailing(buf: &mut String,
             }
         }
 
-        if self.substitution_parts.is_empty() {
-            return vec![(String::new(), false)];
-        }
-
-        let mut primary_spans: Vec<_> = self.substitution_parts
-            .iter()
-            .map(|sub| (sub.span, &sub.substitutions))
-            .collect();
-
-        // Assumption: all spans are in the same file, and all spans
-        // are disjoint. Sort in ascending order.
-        primary_spans.sort_by_key(|sp| sp.0.lo());
-
-        // Find the bounding span.
-        let lo = primary_spans.iter().map(|sp| sp.0.lo()).min().unwrap();
-        let hi = primary_spans.iter().map(|sp| sp.0.hi()).min().unwrap();
-        let bounding_span = Span::new(lo, hi, NO_EXPANSION);
-        let lines = cm.span_to_lines(bounding_span).unwrap();
-        assert!(!lines.lines.is_empty());
-
-        // To build up the result, we do this for each span:
-        // - push the line segment trailing the previous span
-        //   (at the beginning a "phantom" span pointing at the start of the line)
-        // - push lines between the previous and current span (if any)
-        // - if the previous and current span are not on the same line
-        //   push the line segment leading up to the current span
-        // - splice in the span substitution
-        //
-        // Finally push the trailing line segment of the last span
-        let fm = &lines.file;
-        let mut prev_hi = cm.lookup_char_pos(bounding_span.lo());
-        prev_hi.col = CharPos::from_usize(0);
-
-        let mut prev_line = fm.get_line(lines.lines[0].line_index);
-        let mut bufs = vec![(String::new(), false); self.substitutions()];
-
-        for (sp, substitutes) in primary_spans {
-            let cur_lo = cm.lookup_char_pos(sp.lo());
-            for (&mut (ref mut buf, ref mut underline), substitute) in bufs.iter_mut()
-                                                                           .zip(substitutes) {
+        assert!(!self.substitutions.is_empty());
+
+        self.substitutions.iter().cloned().map(|mut substitution| {
+            // Assumption: all spans are in the same file, and all spans
+            // are disjoint. Sort in ascending order.
+            substitution.parts.sort_by_key(|part| part.span.lo());
+
+            // Find the bounding span.
+            let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap();
+            let hi = substitution.parts.iter().map(|part| part.span.hi()).min().unwrap();
+            let bounding_span = Span::new(lo, hi, NO_EXPANSION);
+            let lines = cm.span_to_lines(bounding_span).unwrap();
+            assert!(!lines.lines.is_empty());
+
+            // To build up the result, we do this for each span:
+            // - push the line segment trailing the previous span
+            //   (at the beginning a "phantom" span pointing at the start of the line)
+            // - push lines between the previous and current span (if any)
+            // - if the previous and current span are not on the same line
+            //   push the line segment leading up to the current span
+            // - splice in the span substitution
+            //
+            // Finally push the trailing line segment of the last span
+            let fm = &lines.file;
+            let mut prev_hi = cm.lookup_char_pos(bounding_span.lo());
+            prev_hi.col = CharPos::from_usize(0);
+
+            let mut prev_line = fm.get_line(lines.lines[0].line_index);
+            let mut buf = String::new();
+
+            for part in &substitution.parts {
+                let cur_lo = cm.lookup_char_pos(part.span.lo());
                 if prev_hi.line == cur_lo.line {
-                    push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
-
-                    // Only show an underline in the suggestions if the suggestion is not the
-                    // entirety of the code being shown and the displayed code is not multiline.
-                    if prev_line.as_ref().unwrap().trim().len() > 0
-                        && !substitute.ends_with('\n')
-                        && substitute.lines().count() == 1
-                    {
-                        *underline = true;
-                    }
+                    push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
                 } else {
-                    *underline = false;
-                    push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
+                    push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
                     // push lines between the previous and current span (if any)
                     for idx in prev_hi.line..(cur_lo.line - 1) {
                         if let Some(line) = fm.get_line(idx) {
@@ -207,22 +187,20 @@ fn push_trailing(buf: &mut String,
                         buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
                     }
                 }
-                buf.push_str(substitute);
+                buf.push_str(&part.snippet);
+                prev_hi = cm.lookup_char_pos(part.span.hi());
+                prev_line = fm.get_line(prev_hi.line - 1);
             }
-            prev_hi = cm.lookup_char_pos(sp.hi());
-            prev_line = fm.get_line(prev_hi.line - 1);
-        }
-        for &mut (ref mut buf, _) in &mut bufs {
             // if the replacement already ends with a newline, don't print the next line
             if !buf.ends_with('\n') {
-                push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
+                push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
             }
             // remove trailing newlines
             while buf.ends_with('\n') {
                 buf.pop();
             }
-        }
-        bufs
+            (buf, substitution.parts)
+        }).collect()
     }
 }
 
index 7bf2efa4b885f8eef332581957e4a84f795f75c8..b40a1b7c0cb7d7daff9a2c440133a886122e118c 100644 (file)
@@ -10,9 +10,10 @@ crate-type = ["dylib"]
 
 [dependencies]
 graphviz = { path = "../libgraphviz" }
+log = "0.3"
+rand = "0.3"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
-log = "0.3"
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index e82c2897d21325da73b07d053c8b89c6e5a45660..5eaf8553ee3d391882af3663c7603375268dd359 100644 (file)
@@ -15,7 +15,6 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(rand)]
 #![feature(conservative_impl_trait)]
 #![feature(i128_type)]
 #![feature(inclusive_range_syntax)]
@@ -25,6 +24,7 @@
 #[macro_use] extern crate rustc;
 extern crate rustc_data_structures;
 extern crate serialize as rustc_serialize;
+extern crate rand;
 
 #[macro_use] extern crate log;
 extern crate syntax;
index 458f47a1602c7454c4b421a4baa20b2a7581fcd4..4141137a7db963aaef97ccc459c7876f5c0bfc2c 100644 (file)
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::time::{UNIX_EPOCH, SystemTime, Duration};
-use std::__rand::{thread_rng, Rng};
+
+use rand::{thread_rng, Rng};
 
 const LOCK_FILE_EXT: &'static str = ".lock";
 const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
index 3399bf2acd8917c88bab7b3f4a337bc3a2a9ff7e..ac0e4dde0c1024e95bbc2f3c91ad49e96a1423c3 100644 (file)
@@ -359,6 +359,17 @@ pub struct ThinLTOModule {
     pub len: usize,
 }
 
+/// LLVMThreadLocalMode
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ThreadLocalMode {
+  NotThreadLocal,
+  GeneralDynamic,
+  LocalDynamic,
+  InitialExec,
+  LocalExec
+}
+
 // Opaque pointer types
 #[allow(missing_copy_implementations)]
 pub enum Module_opaque {}
@@ -709,6 +720,7 @@ pub fn LLVMConstInlineAsm(Ty: TypeRef,
     pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
     pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
     pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
+    pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode);
     pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
     pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
     pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
index 98172bca1778625da8ce88b02513b4788055a9b8..5ccce8de7063995ccb2e9378a83f7a96bae4234c 100644 (file)
@@ -172,6 +172,11 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
         LLVMSetThreadLocal(global, is_thread_local as Bool);
     }
 }
+pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
+    unsafe {
+        LLVMSetThreadLocalMode(global, mode);
+    }
+}
 
 impl Attribute {
     pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
index cfc8d271327fbef3d4ace880a683b3e94de5dff1..155097cdbe26c5e452e915afe17bef36c4cfde4d 100644 (file)
@@ -258,14 +258,15 @@ fn register_crate(&mut self,
         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
 
         let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
-            crate_root.def_path_table.decode(&metadata)
+            crate_root.def_path_table.decode((&metadata, self.sess))
         });
 
-        let exported_symbols = crate_root.exported_symbols.decode(&metadata).collect();
-
+        let exported_symbols = crate_root.exported_symbols
+                                         .decode((&metadata, self.sess))
+                                         .collect();
         let trait_impls = crate_root
             .impls
-            .decode(&metadata)
+            .decode((&metadata, self.sess))
             .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
             .collect();
 
@@ -298,7 +299,7 @@ fn register_crate(&mut self,
         let dllimports: FxHashSet<_> = cmeta
             .root
             .native_libraries
-            .decode(&cmeta)
+            .decode((&cmeta, self.sess))
             .filter(|lib| relevant_lib(self.sess, lib) &&
                           lib.kind == cstore::NativeLibraryKind::NativeUnknown)
             .flat_map(|lib| {
@@ -685,14 +686,15 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
                                                           "needs_panic_runtime");
 
+        let sess = self.sess;
         self.cstore.iter_crate_data(|cnum, data| {
             needs_panic_runtime = needs_panic_runtime ||
-                                  data.needs_panic_runtime();
-            if data.is_panic_runtime() {
+                                  data.needs_panic_runtime(sess);
+            if data.is_panic_runtime(sess) {
                 // Inject a dependency from all #![needs_panic_runtime] to this
                 // #![panic_runtime] crate.
                 self.inject_dependency_if(cnum, "a panic runtime",
-                                          &|data| data.needs_panic_runtime());
+                                          &|data| data.needs_panic_runtime(sess));
                 runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
             }
         });
@@ -728,7 +730,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
-        if !data.is_panic_runtime() {
+        if !data.is_panic_runtime(self.sess) {
             self.sess.err(&format!("the crate `{}` is not a panic runtime",
                                    name));
         }
@@ -740,7 +742,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
 
         self.sess.injected_panic_runtime.set(Some(cnum));
         self.inject_dependency_if(cnum, "a panic runtime",
-                                  &|data| data.needs_panic_runtime());
+                                  &|data| data.needs_panic_runtime(self.sess));
     }
 
     fn inject_sanitizer_runtime(&mut self) {
@@ -835,7 +837,7 @@ fn inject_sanitizer_runtime(&mut self) {
                                        PathKind::Crate, dep_kind);
 
                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
-                if !data.is_sanitizer_runtime() {
+                if !data.is_sanitizer_runtime(self.sess) {
                     self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
                                            name));
                 }
@@ -856,7 +858,7 @@ fn inject_profiler_runtime(&mut self) {
                                    PathKind::Crate, dep_kind);
 
             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
-            if !data.is_profiler_runtime() {
+            if !data.is_profiler_runtime(self.sess) {
                 self.sess.err(&format!("the crate `profiler_builtins` is not \
                                         a profiler runtime"));
             }
@@ -875,7 +877,7 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         let mut needs_allocator = attr::contains_name(&krate.attrs,
                                                       "needs_allocator");
         self.cstore.iter_crate_data(|_, data| {
-            needs_allocator = needs_allocator || data.needs_allocator();
+            needs_allocator = needs_allocator || data.needs_allocator(self.sess);
         });
         if !needs_allocator {
             return
@@ -997,7 +999,7 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
             Some(data) => {
                 // We have an allocator. We detect separately what kind it is, to allow for some
                 // flexibility in misconfiguration.
-                let attrs = data.get_item_attrs(CRATE_DEF_INDEX);
+                let attrs = data.get_item_attrs(CRATE_DEF_INDEX, self.sess);
                 let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind")
                     .map(Symbol::as_str);
                 let kind_str = kind_interned
index c688b4c408a352e61632b2d486658e6fbaeda65f..a86b55e269d418720b77f572feb29993b885327e 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
-use rustc::session::CrateDisambiguator;
+use rustc::session::{Session, CrateDisambiguator};
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
@@ -176,8 +176,8 @@ pub fn disambiguator(&self) -> CrateDisambiguator {
         self.root.disambiguator
     }
 
-    pub fn needs_allocator(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn needs_allocator(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "needs_allocator")
     }
 
@@ -189,43 +189,43 @@ pub fn has_default_lib_allocator(&self) -> bool {
         self.root.has_default_lib_allocator.clone()
     }
 
-    pub fn is_panic_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_panic_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "panic_runtime")
     }
 
-    pub fn needs_panic_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn needs_panic_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "needs_panic_runtime")
     }
 
-    pub fn is_compiler_builtins(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_compiler_builtins(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "compiler_builtins")
     }
 
-    pub fn is_sanitizer_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_sanitizer_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "sanitizer_runtime")
     }
 
-    pub fn is_profiler_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_profiler_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "profiler_runtime")
     }
 
-    pub fn is_no_builtins(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_no_builtins(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "no_builtins")
     }
 
-     pub fn has_copy_closures(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+     pub fn has_copy_closures(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_feature_attr(&attrs, "copy_closures")
     }
 
-    pub fn has_clone_closures(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn has_clone_closures(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_feature_attr(&attrs, "clone_closures")
     }
 
index 97c00aede90cfd229b3948d14d618fb37395df19..8dcfb4c34b5b247a7eed442a948bacc17530716e 100644 (file)
@@ -99,11 +99,13 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
 
 provide! { <'tcx> tcx, def_id, other, cdata,
     type_of => { cdata.get_type(def_id.index, tcx) }
-    generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) }
+    generics_of => {
+        tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
+    }
     predicates_of => { cdata.get_predicates(def_id.index, tcx) }
     super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
     trait_def => {
-        tcx.alloc_trait_def(cdata.get_trait_def(def_id.index))
+        tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
     }
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
     adt_destructor => {
@@ -153,7 +155,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     lookup_deprecation_entry => {
         cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
     }
-    item_attrs => { cdata.get_item_attrs(def_id.index) }
+    item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) }
     // FIXME(#38501) We've skipped a `read` on the `HirBody` of
     // a `fn` when encoding, so the dep-tracking wouldn't work.
     // This is only used by rustdoc anyway, which shouldn't have
@@ -171,17 +173,17 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
 
     dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats()) }
-    is_panic_runtime => { cdata.is_panic_runtime() }
-    is_compiler_builtins => { cdata.is_compiler_builtins() }
+    is_panic_runtime => { cdata.is_panic_runtime(tcx.sess) }
+    is_compiler_builtins => { cdata.is_compiler_builtins(tcx.sess) }
     has_global_allocator => { cdata.has_global_allocator() }
-    is_sanitizer_runtime => { cdata.is_sanitizer_runtime() }
-    is_profiler_runtime => { cdata.is_profiler_runtime() }
+    is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
+    is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
     panic_strategy => { cdata.panic_strategy() }
     extern_crate => { Rc::new(cdata.extern_crate.get()) }
-    is_no_builtins => { cdata.is_no_builtins() }
+    is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
     impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
     exported_symbol_ids => { Rc::new(cdata.get_exported_symbols()) }
-    native_libraries => { Rc::new(cdata.get_native_libraries()) }
+    native_libraries => { Rc::new(cdata.get_native_libraries(tcx.sess)) }
     plugin_registrar_fn => {
         cdata.root.plugin_registrar_fn.map(|index| {
             DefId { krate: def_id.krate, index }
@@ -237,8 +239,8 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
 
     used_crate_source => { Rc::new(cdata.source.clone()) }
 
-    has_copy_closures => { cdata.has_copy_closures() }
-    has_clone_closures => { cdata.has_clone_closures() }
+    has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
+    has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
 }
 
 pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
@@ -358,8 +360,8 @@ fn visibility_untracked(&self, def: DefId) -> ty::Visibility {
         self.get_crate_data(def.krate).get_visibility(def.index)
     }
 
-    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics {
-        self.get_crate_data(def.krate).get_generics(def.index)
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
+        self.get_crate_data(def.krate).get_generics(def.index, sess)
     }
 
     fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
@@ -454,7 +456,7 @@ fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         let body = filemap_to_stream(&sess.parse_sess, filemap, None);
 
         // Mark the attrs as used
-        let attrs = data.get_item_attrs(id.index);
+        let attrs = data.get_item_attrs(id.index, sess);
         for attr in attrs.iter() {
             attr::mark_used(attr);
         }
index 603e79155fb726d859c4c0d9995cc83f73eaba02..e63037f4da1efbe8f06ec441f839611fdc15aeda 100644 (file)
@@ -87,6 +87,20 @@ fn raw_bytes(self) -> &'a [u8] {
     }
 }
 
+
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'a Session) {
+    fn raw_bytes(self) -> &'a [u8] {
+        let (blob, _) = self;
+        &blob.0
+    }
+
+    fn sess(self) -> Option<&'a Session> {
+        let (_, sess) = self;
+        Some(sess)
+    }
+}
+
+
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
     fn raw_bytes(self) -> &'a [u8] {
         self.blob.raw_bytes()
@@ -291,7 +305,7 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
         let sess = if let Some(sess) = self.sess {
             sess
         } else {
-            return Ok(Span::new(lo, hi, NO_EXPANSION));
+            bug!("Cannot decode Span without Session.")
         };
 
         let (lo, hi) = if lo > hi {
@@ -313,7 +327,8 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
             // originate from the same filemap.
             let last_filemap = &imported_filemaps[self.last_filemap_index];
 
-            if lo >= last_filemap.original_start_pos && lo <= last_filemap.original_end_pos &&
+            if lo >= last_filemap.original_start_pos &&
+               lo <= last_filemap.original_end_pos &&
                hi >= last_filemap.original_start_pos &&
                hi <= last_filemap.original_end_pos {
                 last_filemap
@@ -335,8 +350,8 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
             }
         };
 
-        let lo = (lo - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
-        let hi = (hi - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
+        let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
+        let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
 
         Ok(Span::new(lo, hi, NO_EXPANSION))
     }
@@ -521,9 +536,9 @@ pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
         }
     }
 
-    pub fn get_trait_def(&self, item_id: DefIndex) -> ty::TraitDef {
+    pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
         let data = match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode(self),
+            EntryKind::Trait(data) => data.decode((self, sess)),
             _ => bug!(),
         };
 
@@ -607,8 +622,11 @@ pub fn get_super_predicates(&self,
         }
     }
 
-    pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics {
-        self.entry(item_id).generics.unwrap().decode(self)
+    pub fn get_generics(&self,
+                        item_id: DefIndex,
+                        sess: &Session)
+                        -> ty::Generics {
+        self.entry(item_id).generics.unwrap().decode((self, sess))
     }
 
     pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
@@ -908,7 +926,7 @@ pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
         }
     }
 
-    pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
+    pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Rc<[ast::Attribute]> {
         let (node_as, node_index) =
             (node_id.address_space().index(), node_id.as_array_index());
         if self.is_proc_macro(node_id) {
@@ -928,7 +946,7 @@ pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
         if def_key.disambiguated_data.data == DefPathData::StructCtor {
             item = self.entry(def_key.parent.unwrap());
         }
-        let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item));
+        let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item, sess));
         let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
         if vec_.len() < node_index + 1 {
             vec_.resize(node_index + 1, None);
@@ -945,9 +963,9 @@ pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
             .collect()
     }
 
-    fn get_attributes(&self, item: &Entry<'tcx>) -> Vec<ast::Attribute> {
+    fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<ast::Attribute> {
         item.attributes
-            .decode(self)
+            .decode((self, sess))
             .map(|mut attr| {
                 // Need new unique IDs: old thread-local IDs won't map to new threads.
                 attr.id = attr::mk_attr_id();
@@ -1013,8 +1031,8 @@ pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
     }
 
 
-    pub fn get_native_libraries(&self) -> Vec<NativeLibrary> {
-        self.root.native_libraries.decode(self).collect()
+    pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
+        self.root.native_libraries.decode((self, sess)).collect()
     }
 
     pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
index 2cb1a23ef5a15cfb4f8cc289c997a87ec631563c..b723b86776b11cab5c2830cfd3a801630068f02d 100644 (file)
 use dataflow::{MoveDataParamEnv};
 use dataflow::{BitDenotation, BlockSets, DataflowResults, DataflowResultsConsumer};
 use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
+use dataflow::{MovingOutStatements};
 use dataflow::{Borrows, BorrowData, BorrowIndex};
 use dataflow::move_paths::{MoveError, IllegalMoveOriginKind};
-use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult, MoveOutIndex};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
 use self::MutateMode::{JustWrite, WriteAndRead};
@@ -129,6 +130,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
                                    MaybeUninitializedLvals::new(tcx, mir, &mdpe),
                                    |bd, i| &bd.move_data().move_paths[i]);
+    let flow_move_outs = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                     MovingOutStatements::new(tcx, mir, &mdpe),
+                                     |bd, i| &bd.move_data().moves[i]);
 
     let mut mbcx = MirBorrowckCtxt {
         tcx: tcx,
@@ -141,7 +145,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 
     let mut state = InProgress::new(flow_borrows,
                                     flow_inits,
-                                    flow_uninits);
+                                    flow_uninits,
+                                    flow_move_outs);
 
     mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
 }
@@ -161,6 +166,7 @@ pub struct InProgress<'b, 'gcx: 'tcx, 'tcx: 'b> {
     borrows: FlowInProgress<Borrows<'b, 'gcx, 'tcx>>,
     inits: FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
     uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
+    move_outs: FlowInProgress<MovingOutStatements<'b, 'gcx, 'tcx>>,
 }
 
 struct FlowInProgress<BD> where BD: BitDenotation {
@@ -185,7 +191,8 @@ fn mir(&self) -> &'b Mir<'tcx> { self.mir }
     fn reset_to_entry_of(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) {
         flow_state.each_flow(|b| b.reset_to_entry_of(bb),
                              |i| i.reset_to_entry_of(bb),
-                             |u| u.reset_to_entry_of(bb));
+                             |u| u.reset_to_entry_of(bb),
+                             |m| m.reset_to_entry_of(bb));
     }
 
     fn reconstruct_statement_effect(&mut self,
@@ -193,7 +200,8 @@ fn reconstruct_statement_effect(&mut self,
                                     flow_state: &mut Self::FlowState) {
         flow_state.each_flow(|b| b.reconstruct_statement_effect(location),
                              |i| i.reconstruct_statement_effect(location),
-                             |u| u.reconstruct_statement_effect(location));
+                             |u| u.reconstruct_statement_effect(location),
+                             |m| m.reconstruct_statement_effect(location));
     }
 
     fn apply_local_effect(&mut self,
@@ -201,7 +209,8 @@ fn apply_local_effect(&mut self,
                           flow_state: &mut Self::FlowState) {
         flow_state.each_flow(|b| b.apply_local_effect(),
                              |i| i.apply_local_effect(),
-                             |u| u.apply_local_effect());
+                             |u| u.apply_local_effect(),
+                             |m| m.apply_local_effect());
     }
 
     fn reconstruct_terminator_effect(&mut self,
@@ -209,7 +218,8 @@ fn reconstruct_terminator_effect(&mut self,
                                      flow_state: &mut Self::FlowState) {
         flow_state.each_flow(|b| b.reconstruct_terminator_effect(location),
                              |i| i.reconstruct_terminator_effect(location),
-                             |u| u.reconstruct_terminator_effect(location));
+                             |u| u.reconstruct_terminator_effect(location),
+                             |m| m.reconstruct_terminator_effect(location));
     }
 
     fn visit_block_entry(&mut self,
@@ -671,6 +681,7 @@ fn check_if_path_is_moved(&mut self,
         let lvalue = self.base_path(lvalue_span.0);
 
         let maybe_uninits = &flow_state.uninits;
+        let curr_move_outs = &flow_state.move_outs.curr_state;
 
         // Bad scenarios:
         //
@@ -712,7 +723,9 @@ fn check_if_path_is_moved(&mut self,
         match self.move_path_closest_to(lvalue) {
             Ok(mpi) => {
                 if maybe_uninits.curr_state.contains(&mpi) {
-                    self.report_use_of_moved(context, desired_action, lvalue_span);
+                    self.report_use_of_moved_or_uninitialized(context, desired_action,
+                                                              lvalue_span, mpi,
+                                                              curr_move_outs);
                     return; // don't bother finding other problems.
                 }
             }
@@ -737,8 +750,10 @@ fn check_if_path_is_moved(&mut self,
 
         debug!("check_if_path_is_moved part2 lvalue: {:?}", lvalue);
         if let Some(mpi) = self.move_path_for_lvalue(lvalue) {
-            if let Some(_) = maybe_uninits.has_any_child_of(mpi) {
-                self.report_use_of_moved(context, desired_action, lvalue_span);
+            if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) {
+                self.report_use_of_moved_or_uninitialized(context, desired_action,
+                                                          lvalue_span, child_mpi,
+                                                          curr_move_outs);
                 return; // don't bother finding other problems.
             }
         }
@@ -1083,17 +1098,47 @@ fn next(&mut self) -> Option<Self::Item> {
 }
 
 impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
-    fn report_use_of_moved(&mut self,
+    fn report_use_of_moved_or_uninitialized(&mut self,
                            _context: Context,
                            desired_action: &str,
-                           (lvalue, span): (&Lvalue, Span)) {
-        self.tcx.cannot_act_on_uninitialized_variable(span,
-                                                      desired_action,
-                                                      &self.describe_lvalue(lvalue),
-                                                      Origin::Mir)
-                .span_label(span, format!("use of possibly uninitialized `{}`",
-                                          self.describe_lvalue(lvalue)))
-                .emit();
+                           (lvalue, span): (&Lvalue, Span),
+                           mpi: MovePathIndex,
+                           curr_move_out: &IdxSetBuf<MoveOutIndex>) {
+
+        let mois = self.move_data.path_map[mpi].iter().filter(
+            |moi| curr_move_out.contains(moi)).collect::<Vec<_>>();
+
+        if mois.is_empty() {
+            self.tcx.cannot_act_on_uninitialized_variable(span,
+                                                          desired_action,
+                                                          &self.describe_lvalue(lvalue),
+                                                          Origin::Mir)
+                    .span_label(span, format!("use of possibly uninitialized `{}`",
+                                              self.describe_lvalue(lvalue)))
+                    .emit();
+        } else {
+            let msg = ""; //FIXME: add "partially " or "collaterally "
+
+            let mut err = self.tcx.cannot_act_on_moved_value(span,
+                                                             desired_action,
+                                                             msg,
+                                                             &self.describe_lvalue(lvalue),
+                                                             Origin::Mir);
+            err.span_label(span, format!("value {} here after move", desired_action));
+            for moi in mois {
+                let move_msg = ""; //FIXME: add " (into closure)"
+                let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span;
+                if span == move_span {
+                    err.span_label(span,
+                                   format!("value moved{} here in previous iteration of loop",
+                                           move_msg));
+                } else {
+                    err.span_label(move_span, format!("value moved{} here", move_msg));
+                };
+            }
+            //FIXME: add note for closure
+            err.emit();
+        }
     }
 
     fn report_move_out_while_borrowed(&mut self,
@@ -1124,8 +1169,72 @@ fn report_use_while_mutably_borrowed(&mut self,
         err.emit();
     }
 
+    /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of
+    /// the local assigned at `location`.
+    /// This is done by searching in statements succeeding `location`
+    /// and originating from `maybe_closure_span`.
+    fn find_closure_span(
+        &self,
+        maybe_closure_span: Span,
+        location: Location,
+    ) -> Option<(Span, Span)> {
+        use rustc::hir::ExprClosure;
+        use rustc::mir::AggregateKind;
+
+        let local = if let StatementKind::Assign(Lvalue::Local(local), _) =
+            self.mir[location.block].statements[location.statement_index].kind
+        {
+            local
+        } else {
+            return None;
+        };
+
+        for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
+            if maybe_closure_span != stmt.source_info.span {
+                break;
+            }
+
+            if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref lvs)) = stmt.kind {
+                if let AggregateKind::Closure(def_id, _) = **kind {
+                    debug!("find_closure_span: found closure {:?}", lvs);
+
+                    return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                        let args_span = if let ExprClosure(_, _, _, span, _) =
+                            self.tcx.hir.expect_expr(node_id).node
+                        {
+                            span
+                        } else {
+                            return None;
+                        };
+
+                        self.tcx
+                            .with_freevars(node_id, |freevars| {
+                                for (v, lv) in freevars.iter().zip(lvs) {
+                                    if let Operand::Consume(Lvalue::Local(l)) = *lv {
+                                        if local == l {
+                                            debug!(
+                                                "find_closure_span: found captured local {:?}",
+                                                l
+                                            );
+                                            return Some(v.span);
+                                        }
+                                    }
+                                }
+                                None
+                            })
+                            .map(|var_span| (args_span, var_span))
+                    } else {
+                        None
+                    };
+                }
+            }
+        }
+
+        None
+    }
+
     fn report_conflicting_borrow(&mut self,
-                                 _context: Context,
+                                 context: Context,
                                  common_prefix: &Lvalue,
                                  (lvalue, span): (&Lvalue, Span),
                                  gen_borrow_kind: BorrowKind,
@@ -1138,38 +1247,60 @@ fn report_conflicting_borrow(&mut self,
 
         let issued_span = self.retrieve_borrow_span(issued_borrow);
 
+        let new_closure_span = self.find_closure_span(span, context.loc);
+        let span = new_closure_span.map(|(args, _)| args).unwrap_or(span);
+        let old_closure_span = self.find_closure_span(issued_span, issued_borrow.location);
+        let issued_span = old_closure_span.map(|(args, _)| args).unwrap_or(issued_span);
+
+        let desc_lvalue = self.describe_lvalue(lvalue);
+
         // FIXME: supply non-"" `opt_via` when appropriate
         let mut err = match (gen_borrow_kind, "immutable", "mutable",
                              issued_borrow.kind, "immutable", "mutable") {
             (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
             (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) =>
                 self.tcx.cannot_reborrow_already_borrowed(
-                    span, &self.describe_lvalue(lvalue), "", lft, issued_span,
+                    span, &desc_lvalue, "", lft, issued_span,
                     "it", rgt, "", end_issued_loan_span, Origin::Mir),
 
             (BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) =>
                 self.tcx.cannot_mutably_borrow_multiply(
-                    span, &self.describe_lvalue(lvalue), "", issued_span,
+                    span, &desc_lvalue, "", issued_span,
                     "", end_issued_loan_span, Origin::Mir),
 
             (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) =>
                 self.tcx.cannot_uniquely_borrow_by_two_closures(
-                    span, &self.describe_lvalue(lvalue), issued_span,
+                    span, &desc_lvalue, issued_span,
                     end_issued_loan_span, Origin::Mir),
 
             (BorrowKind::Unique, _, _, _, _, _) =>
                 self.tcx.cannot_uniquely_borrow_by_one_closure(
-                    span, &self.describe_lvalue(lvalue), "",
+                    span, &desc_lvalue, "",
                     issued_span, "it", "", end_issued_loan_span, Origin::Mir),
 
             (_, _, _, BorrowKind::Unique, _, _) =>
                 self.tcx.cannot_reborrow_already_uniquely_borrowed(
-                    span, &self.describe_lvalue(lvalue), "it", "",
+                    span, &desc_lvalue, "it", "",
                     issued_span, "", end_issued_loan_span, Origin::Mir),
 
             (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) =>
                 unreachable!(),
         };
+
+        if let Some((_, var_span)) = old_closure_span {
+            err.span_label(
+                var_span,
+                format!("previous borrow occurs due to use of `{}` in closure", desc_lvalue),
+            );
+        }
+
+        if let Some((_, var_span)) = new_closure_span {
+            err.span_label(
+                var_span,
+                format!("borrow occurs due to use of `{}` in closure", desc_lvalue),
+            );
+        }
+
         err.emit();
     }
 
@@ -1396,26 +1527,31 @@ fn new(self, loc: Location) -> Context { Context { kind: self, loc: loc } }
 impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
     pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'gcx, 'tcx>>,
                       inits: DataflowResults<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
-                      uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>)
+                      uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
+                      move_out: DataflowResults<MovingOutStatements<'b, 'gcx, 'tcx>>)
                       -> Self {
         InProgress {
             borrows: FlowInProgress::new(borrows),
             inits: FlowInProgress::new(inits),
             uninits: FlowInProgress::new(uninits),
+            move_outs: FlowInProgress::new(move_out)
         }
     }
 
-    fn each_flow<XB, XI, XU>(&mut self,
-                             mut xform_borrows: XB,
-                             mut xform_inits: XI,
-                             mut xform_uninits: XU) where
+    fn each_flow<XB, XI, XU, XM>(&mut self,
+                                 mut xform_borrows: XB,
+                                 mut xform_inits: XI,
+                                 mut xform_uninits: XU,
+                                 mut xform_move_outs: XM) where
         XB: FnMut(&mut FlowInProgress<Borrows<'b, 'gcx, 'tcx>>),
         XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>),
         XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>),
+        XM: FnMut(&mut FlowInProgress<MovingOutStatements<'b, 'gcx, 'tcx>>),
     {
         xform_borrows(&mut self.borrows);
         xform_inits(&mut self.inits);
         xform_uninits(&mut self.uninits);
+        xform_move_outs(&mut self.move_outs);
     }
 
     fn summary(&self) -> String {
@@ -1461,6 +1597,17 @@ fn summary(&self) -> String {
                 &self.uninits.base_results.operator().move_data().move_paths[mpi_uninit];
             s.push_str(&format!("{}", move_path));
         });
+        s.push_str("] ");
+
+        s.push_str("move_out: [");
+        let mut saw_one = false;
+        self.move_outs.each_state_bit(|mpi_move_out| {
+            if saw_one { s.push_str(", "); };
+            saw_one = true;
+            let move_out =
+                &self.move_outs.base_results.operator().move_data().moves[mpi_move_out];
+            s.push_str(&format!("{:?}", move_out));
+        });
         s.push_str("]");
 
         return s;
index 77496c7b8f218b922e9991ea3cc540cf8034c311..2073d49530061fc728d97a44cec2e4409a97c5d5 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::middle::region;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
-use rustc::mir::visit::{MutVisitor, Lookup};
+use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeMap;
@@ -165,7 +165,7 @@ struct GlobalizeMir<'a, 'gcx: 'a> {
 }
 
 impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         if let Some(lifted) = self.tcx.lift(ty) {
             *ty = lifted;
         } else {
index 17aa8c054181e4a904a0ca7566cbccf9633a243f..e8bf543b70b6a1d443151888d81290cef66722ee 100644 (file)
@@ -38,7 +38,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     location_map: FxHashMap<Location, BorrowIndex>,
     region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
     region_span_map: FxHashMap<RegionKind, Span>,
-    nonlexical_regioncx: Option<&'a RegionInferenceContext>,
+    nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>,
 }
 
 // temporarily allow some dead fields: `kind` and `region` will be
@@ -69,7 +69,7 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
 impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               nonlexical_regioncx: Option<&'a RegionInferenceContext>)
+               nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
                -> Self {
         let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
                                           location_map: FxHashMap(),
@@ -139,11 +139,21 @@ fn kill_loans_out_of_scope_at_location(&self,
                                            location: Location) {
         if let Some(regioncx) = self.nonlexical_regioncx {
             for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
-                let borrow_region = regioncx.region_value(borrow_data.region.to_region_index());
-                if !borrow_region.may_contain(location) && location != borrow_data.location {
-                    debug!("kill_loans_out_of_scope_at_location: kill{:?} \
-                           location={:?} borrow_data={:?}", borrow_index, location, borrow_data);
-                    sets.kill(&borrow_index);
+                let borrow_region = borrow_data.region.to_region_index();
+                if !regioncx.region_contains_point(borrow_region, location) {
+                    // The region checker really considers the borrow
+                    // to start at the point **after** the location of
+                    // the borrow, but the borrow checker puts the gen
+                    // directly **on** the location of the
+                    // borrow. This results in a gen/kill both being
+                    // generated for same point if we are not
+                    // careful. Probably we should change the point of
+                    // the gen, but for now we hackily account for the
+                    // mismatch here by not generating a kill for the
+                    // location on the borrow itself.
+                    if location != borrow_data.location {
+                        sets.kill(&borrow_index);
+                    }
                 }
             }
         }
index af99706be811d21770f975921ebc29affe62337e..dad96dc3a6ffeb2c47ae66f8d0d918f49a13cd2e 100644 (file)
 
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
+use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
 use rustc_data_structures::bitslice::{BitwiseOperator};
 use rustc_data_structures::indexed_set::{IdxSet};
+use rustc_data_structures::indexed_vec::Idx;
 
 use super::MoveDataParamEnv;
 use util::elaborate_drops::DropFlagState;
 
-use super::move_paths::{HasMoveData, MoveData, MovePathIndex};
+use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
+use super::move_paths::LookupResult;
 use super::{BitDenotation, BlockSets, DataflowOperator};
 
 use super::drop_flag_effects_for_function_entry;
@@ -205,6 +208,40 @@ impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'g
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
+/// `MovingOutStatements` tracks the statements that perform moves out
+/// of particular l-values. More precisely, it tracks whether the
+/// *effect* of such moves (namely, the uninitialization of the
+/// l-value in question) can reach some point in the control-flow of
+/// the function, or if that effect is "killed" by some intervening
+/// operation reinitializing that l-value.
+///
+/// The resulting dataflow is a more enriched version of
+/// `MaybeUninitializedLvals`. Both structures on their own only tell
+/// you if an l-value *might* be uninitialized at a given point in the
+/// control flow. But `MovingOutStatements` also includes the added
+/// data of *which* particular statement causing the deinitialization
+/// that the borrow checker's error message may need to report.
+#[allow(dead_code)]
+pub struct MovingOutStatements<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
+}
+
+impl<'a, 'gcx: 'tcx, 'tcx: 'a> MovingOutStatements<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
+               -> Self
+    {
+        MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 impl<'a, 'gcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
@@ -399,6 +436,128 @@ fn propagate_call_return(&self,
     }
 }
 
+impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
+    type Idx = MoveOutIndex;
+    fn name() -> &'static str { "moving_out" }
+    fn bits_per_block(&self) -> usize {
+        self.move_data().moves.len()
+    }
+
+    fn start_block_effect(&self, _sets: &mut BlockSets<MoveOutIndex>) {
+        // no move-statements have been executed prior to function
+        // execution, so this method has no effect on `_sets`.
+    }
+    fn statement_effect(&self,
+                        sets: &mut BlockSets<MoveOutIndex>,
+                        location: Location) {
+        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
+        let stmt = &mir[location.block].statements[location.statement_index];
+        let loc_map = &move_data.loc_map;
+        let path_map = &move_data.path_map;
+        let rev_lookup = &move_data.rev_lookup;
+
+        debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
+               stmt, location, &loc_map[location]);
+        for move_index in &loc_map[location] {
+            // Every path deinitialized by a *particular move*
+            // has corresponding bit, "gen'ed" (i.e. set)
+            // here, in dataflow vector
+            zero_to_one(sets.gen_set.words_mut(), *move_index);
+        }
+        let bits_per_block = self.bits_per_block();
+        match stmt.kind {
+            mir::StatementKind::SetDiscriminant { .. } => {
+                span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
+            }
+            mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
+                // assigning into this `lvalue` kills all
+                // MoveOuts from it, and *also* all MoveOuts
+                // for children and associated fragment sets.
+                match rvalue.initialization_state() {
+                    mir::tcx::RvalueInitializationState::Shallow => {
+                        if let LookupResult::Exact(mpi) = rev_lookup.find(lvalue) {
+                             for moi in &path_map[mpi] {
+                                 assert!(moi.index() < bits_per_block);
+                                 sets.kill_set.add(&moi);
+                             }
+                        }
+                    }
+                    mir::tcx::RvalueInitializationState::Deep => {
+                        on_lookup_result_bits(tcx,
+                                              mir,
+                                              move_data,
+                                              rev_lookup.find(lvalue),
+                                              |mpi| for moi in &path_map[mpi] {
+                                                  assert!(moi.index() < bits_per_block);
+                                                  sets.kill_set.add(&moi);
+                                              });
+                    }
+                }
+            }
+            mir::StatementKind::StorageLive(_) |
+            mir::StatementKind::StorageDead(_) |
+            mir::StatementKind::InlineAsm { .. } |
+            mir::StatementKind::EndRegion(_) |
+            mir::StatementKind::Validate(..) |
+            mir::StatementKind::Nop => {}
+        }
+    }
+
+    fn terminator_effect(&self,
+                         sets: &mut BlockSets<MoveOutIndex>,
+                         location: Location)
+    {
+        let (mir, move_data) = (self.mir, self.move_data());
+        let term = mir[location.block].terminator();
+        let loc_map = &move_data.loc_map;
+        debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
+               term, location, &loc_map[location]);
+        let bits_per_block = self.bits_per_block();
+        for move_index in &loc_map[location] {
+            assert!(move_index.index() < bits_per_block);
+            zero_to_one(sets.gen_set.words_mut(), *move_index);
+        }
+        match term.kind {
+            mir::TerminatorKind::DropAndReplace { ref location, .. } => {
+                on_lookup_result_bits(self.tcx,
+                                      mir,
+                                      move_data,
+                                      move_data.rev_lookup.find(location),
+                                      |mpi| for moi in &move_data.path_map[mpi] {
+                                          assert!(moi.index() < bits_per_block);
+                                          sets.kill_set.add(&moi);
+                                      });
+            }
+            _ => {}
+        }
+    }
+
+    fn propagate_call_return(&self,
+                             in_out: &mut IdxSet<MoveOutIndex>,
+                             _call_bb: mir::BasicBlock,
+                             _dest_bb: mir::BasicBlock,
+                             dest_lval: &mir::Lvalue) {
+        let move_data = self.move_data();
+        let bits_per_block = self.bits_per_block();
+
+        let path_map = &move_data.path_map;
+        on_lookup_result_bits(self.tcx,
+                              self.mir,
+                              move_data,
+                              move_data.rev_lookup.find(dest_lval),
+                              |mpi| for moi in &path_map[mpi] {
+                                  assert!(moi.index() < bits_per_block);
+                                  in_out.remove(&moi);
+                              });
+    }
+}
+
+fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) {
+    let retval = bitvec.set_bit(move_index.index());
+    assert!(retval);
+}
+
+
 impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
@@ -420,6 +579,13 @@ fn join(&self, pred1: usize, pred2: usize) -> usize {
     }
 }
 
+impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> {
+    #[inline]
+    fn join(&self, pred1: usize, pred2: usize) -> usize {
+        pred1 | pred2 // moves from both preds are in scope
+    }
+}
+
 // The way that dataflow fixed point iteration works, you want to
 // start at bottom and work your way to a fixed point. Control-flow
 // merges will apply the `join` operator to each block entry's current
@@ -450,3 +616,10 @@ fn bottom_value() -> bool {
         true // bottom = initialized (start_block_effect counters this at outset)
     }
 }
+
+impl<'a, 'gcx, 'tcx> DataflowOperator for MovingOutStatements<'a, 'gcx, 'tcx> {
+    #[inline]
+    fn bottom_value() -> bool {
+        false // bottom = no loans in scope by default
+    }
+}
index f5517096e3abae49ed72a96614759e4983d474d1..bca9324d5b0aaaf8df44dc5459f88f91e833b389 100644 (file)
@@ -26,7 +26,7 @@
 
 pub use self::impls::{MaybeStorageLive};
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
-pub use self::impls::{DefinitelyInitializedLvals};
+pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements};
 pub use self::impls::borrows::{Borrows, BorrowData, BorrowIndex};
 pub(crate) use self::drop_flag_effects::*;
 
index 80c8f22c1029e0c60ce2873ee54285cdd5aa4983..53a4b2551fd13e189b27910dcea80a60d9ac4a9e 100644 (file)
@@ -34,6 +34,7 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     used_unsafe: FxHashSet<ast::NodeId>,
+    inherited_blocks: Vec<(ast::NodeId, bool)>,
 }
 
 impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
@@ -52,6 +53,7 @@ fn new(mir: &'a Mir<'tcx>,
             tcx,
             param_env,
             used_unsafe: FxHashSet(),
+            inherited_blocks: vec![],
         }
     }
 }
@@ -75,7 +77,7 @@ fn visit_terminator(&mut self,
             TerminatorKind::Return |
             TerminatorKind::Unreachable |
             TerminatorKind::FalseEdges { .. } => {
-                                // safe (at least as emitted during MIR construction)
+                // safe (at least as emitted during MIR construction)
             }
 
             TerminatorKind::Call { ref func, .. } => {
@@ -117,12 +119,20 @@ fn visit_rvalue(&mut self,
                     rvalue: &Rvalue<'tcx>,
                     location: Location)
     {
-        if let &Rvalue::Aggregate(
-            box AggregateKind::Closure(def_id, _),
-            _
-        ) = rvalue {
-            let unsafety_violations = self.tcx.unsafety_violations(def_id);
-            self.register_violations(&unsafety_violations);
+        if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue {
+            match aggregate {
+                &AggregateKind::Array(..) |
+                &AggregateKind::Tuple |
+                &AggregateKind::Adt(..) => {}
+                &AggregateKind::Closure(def_id, _) |
+                &AggregateKind::Generator(def_id, _, _) => {
+                    let UnsafetyCheckResult {
+                        violations, unsafe_blocks
+                    } = self.tcx.unsafety_check_result(def_id);
+                    self.inherited_blocks.extend(unsafe_blocks.iter().cloned());
+                    self.register_violations(&violations, &unsafe_blocks);
+                }
+            }
         }
         self.super_rvalue(rvalue, location);
     }
@@ -189,7 +199,7 @@ fn visit_lvalue(&mut self,
                         source_info,
                         description: "use of extern static",
                         lint_node_id: Some(lint_root)
-                    }]);
+                    }], &[]);
                 }
             }
         }
@@ -222,41 +232,49 @@ fn require_unsafe(&mut self,
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info, description, lint_node_id: None
-        }]);
+        }], &[]);
     }
 
-    fn register_violations(&mut self, violations: &[UnsafetyViolation]) {
-        match self.visibility_scope_info[self.source_info.scope].safety {
+    fn register_violations(&mut self,
+                           violations: &[UnsafetyViolation],
+                           unsafe_blocks: &[(ast::NodeId, bool)]) {
+        let within_unsafe = match self.visibility_scope_info[self.source_info.scope].safety {
             Safety::Safe => {
                 for violation in violations {
                     if !self.violations.contains(violation) {
                         self.violations.push(violation.clone())
                     }
                 }
+
+                false
             }
-            Safety::BuiltinUnsafe | Safety::FnUnsafe => {}
+            Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
             Safety::ExplicitUnsafe(node_id) => {
                 if !violations.is_empty() {
                     self.used_unsafe.insert(node_id);
                 }
+                true
             }
-        }
+        };
+        self.inherited_blocks.extend(unsafe_blocks.iter().map(|&(node_id, is_used)| {
+            (node_id, is_used && !within_unsafe)
+        }));
     }
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
-        unsafety_violations,
+        unsafety_check_result,
         ..*providers
     };
 }
 
-struct UnusedUnsafeVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    used_unsafe: FxHashSet<ast::NodeId>
+struct UnusedUnsafeVisitor<'a> {
+    used_unsafe: &'a FxHashSet<ast::NodeId>,
+    unsafe_blocks: &'a mut Vec<(ast::NodeId, bool)>,
 }
 
-impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a, 'tcx> {
+impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
     fn nested_visit_map<'this>(&'this mut self) ->
         hir::intravisit::NestedVisitorMap<'this, 'tcx>
     {
@@ -267,50 +285,15 @@ fn visit_block(&mut self, block: &'tcx hir::Block) {
         hir::intravisit::walk_block(self, block);
 
         if let hir::UnsafeBlock(hir::UserProvided) = block.rules {
-            if !self.used_unsafe.contains(&block.id) {
-                self.report_unused_unsafe(block);
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx> UnusedUnsafeVisitor<'a, 'tcx> {
-    /// Return the NodeId for an enclosing scope that is also `unsafe`
-    fn is_enclosed(&self, id: ast::NodeId) -> Option<(String, ast::NodeId)> {
-        let parent_id = self.tcx.hir.get_parent_node(id);
-        if parent_id != id {
-            if self.used_unsafe.contains(&parent_id) {
-                Some(("block".to_string(), parent_id))
-            } else if let Some(hir::map::NodeItem(&hir::Item {
-                node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
-                ..
-            })) = self.tcx.hir.find(parent_id) {
-                Some(("fn".to_string(), parent_id))
-            } else {
-                self.is_enclosed(parent_id)
-            }
-        } else {
-            None
-        }
-    }
-
-    fn report_unused_unsafe(&self, block: &'tcx hir::Block) {
-        let mut db = self.tcx.struct_span_lint_node(UNUSED_UNSAFE,
-                                                    block.id,
-                                                    block.span,
-                                                    "unnecessary `unsafe` block");
-        db.span_label(block.span, "unnecessary `unsafe` block");
-        if let Some((kind, id)) = self.is_enclosed(block.id) {
-            db.span_note(self.tcx.hir.span(id),
-                         &format!("because it's nested under this `unsafe` {}", kind));
+            self.unsafe_blocks.push((block.id, self.used_unsafe.contains(&block.id)));
         }
-        db.emit();
     }
 }
 
 fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  def_id: DefId,
-                                 used_unsafe: FxHashSet<ast::NodeId>)
+                                 used_unsafe: &FxHashSet<ast::NodeId>,
+                                 unsafe_blocks: &'a mut Vec<(ast::NodeId, bool)>)
 {
     let body_id =
         tcx.hir.as_local_node_id(def_id).and_then(|node_id| {
@@ -328,25 +311,27 @@ fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})",
            def_id, body, used_unsafe);
 
-    hir::intravisit::Visitor::visit_body(
-        &mut UnusedUnsafeVisitor { tcx, used_unsafe },
-        body);
+    let mut visitor =  UnusedUnsafeVisitor { used_unsafe, unsafe_blocks };
+    hir::intravisit::Visitor::visit_body(&mut visitor, body);
 }
 
-fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ->
-    Rc<[UnsafetyViolation]>
+fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+                                   -> UnsafetyCheckResult
 {
     debug!("unsafety_violations({:?})", def_id);
 
     // NB: this borrow is valid because all the consumers of
-    // `mir_const` force this.
-    let mir = &tcx.mir_const(def_id).borrow();
+    // `mir_built` force this.
+    let mir = &tcx.mir_built(def_id).borrow();
 
     let visibility_scope_info = match mir.visibility_scope_info {
         ClearOnDecode::Set(ref data) => data,
         ClearOnDecode::Clear => {
             debug!("unsafety_violations: {:?} - remote, skipping", def_id);
-            return Rc::new([])
+            return UnsafetyCheckResult {
+                violations: Rc::new([]),
+                unsafe_blocks: Rc::new([])
+            }
         }
     };
 
@@ -355,8 +340,43 @@ fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ->
         mir, visibility_scope_info, tcx, param_env);
     checker.visit_mir(mir);
 
-    check_unused_unsafe(tcx, def_id, checker.used_unsafe);
-    checker.violations.into()
+    check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
+    UnsafetyCheckResult {
+        violations: checker.violations.into(),
+        unsafe_blocks: checker.inherited_blocks.into()
+    }
+}
+
+/// Return the NodeId for an enclosing scope that is also `unsafe`
+fn is_enclosed(tcx: TyCtxt,
+               used_unsafe: &FxHashSet<ast::NodeId>,
+               id: ast::NodeId) -> Option<(String, ast::NodeId)> {
+    let parent_id = tcx.hir.get_parent_node(id);
+    if parent_id != id {
+        if used_unsafe.contains(&parent_id) {
+            Some(("block".to_string(), parent_id))
+        } else if let Some(hir::map::NodeItem(&hir::Item {
+            node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
+            ..
+        })) = tcx.hir.find(parent_id) {
+            Some(("fn".to_string(), parent_id))
+        } else {
+            is_enclosed(tcx, used_unsafe, parent_id)
+        }
+    } else {
+        None
+    }
+}
+
+fn report_unused_unsafe(tcx: TyCtxt, used_unsafe: &FxHashSet<ast::NodeId>, id: ast::NodeId) {
+    let span = tcx.hir.span(id);
+    let mut db = tcx.struct_span_lint_node(UNUSED_UNSAFE, id, span, "unnecessary `unsafe` block");
+    db.span_label(span, "unnecessary `unsafe` block");
+    if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) {
+        db.span_note(tcx.hir.span(id),
+                     &format!("because it's nested under this `unsafe` {}", kind));
+    }
+    db.emit();
 }
 
 pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
@@ -367,9 +387,14 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
         _ => {}
     };
 
+    let UnsafetyCheckResult {
+        violations,
+        unsafe_blocks
+    } = tcx.unsafety_check_result(def_id);
+
     for &UnsafetyViolation {
         source_info, description, lint_node_id
-    } in &*tcx.unsafety_violations(def_id) {
+    } in violations.iter() {
         // Report an error.
         if let Some(lint_node_id) = lint_node_id {
             tcx.lint_node(SAFE_EXTERN_STATICS,
@@ -385,4 +410,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                 .emit();
         }
     }
+
+    let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
+    unsafe_blocks.sort();
+    let used_unsafe: FxHashSet<_> = unsafe_blocks.iter()
+        .flat_map(|&&(id, used)| if used { Some(id) } else { None })
+        .collect();
+    for &(block_id, is_used) in unsafe_blocks {
+        if !is_used {
+            report_unused_unsafe(tcx, &used_unsafe, block_id);
+        }
+    }
 }
index a6750f400ba939ca4d1e9d903a1aa533ce40104d..d356d3b5a850874da1acd393a1968b37d19b680d 100644 (file)
@@ -24,7 +24,7 @@
 use rustc::middle::region;
 use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
-use rustc::mir::visit::{MutVisitor, Visitor, Lookup};
+use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
 use rustc::ty::{Ty, RegionKind, TyCtxt};
 
 pub struct CleanEndRegions;
@@ -67,7 +67,7 @@ fn visit_rvalue(&mut self,
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_ty(&mut self, ty: &Ty<'tcx>, _: Lookup) {
+    fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
         // Gather regions that occur in types
         for re in ty.walk().flat_map(|t| t.regions()) {
             match *re {
index ac8ebd306d321e844b2beda2cca17d3a7517ac33..a730fc30615b46bc42489581b4d861b9e524a799 100644 (file)
@@ -69,10 +69,14 @@ fn run_pass<'a, 'tcx>(&self,
             return;
         }
 
+        let mut def_use_analysis = DefUseAnalysis::new(mir);
         loop {
-            let mut def_use_analysis = DefUseAnalysis::new(mir);
             def_use_analysis.analyze(mir);
 
+            if eliminate_self_assignments(mir, &def_use_analysis) {
+                def_use_analysis.analyze(mir);
+            }
+
             let mut changed = false;
             for dest_local in mir.local_decls.indices() {
                 debug!("Considering destination local: {:?}", dest_local);
@@ -99,9 +103,14 @@ fn run_pass<'a, 'tcx>(&self,
                                dest_local);
                         continue
                     }
-                    let dest_lvalue_def = dest_use_info.defs_and_uses.iter().filter(|lvalue_def| {
-                        lvalue_def.context.is_mutating_use() && !lvalue_def.context.is_drop()
-                    }).next().unwrap();
+                    // Conservatively gives up if the dest is an argument,
+                    // because there may be uses of the original argument value.
+                    if mir.local_kind(dest_local) == LocalKind::Arg {
+                        debug!("  Can't copy-propagate local: dest {:?} (argument)",
+                            dest_local);
+                        continue;
+                    }
+                    let dest_lvalue_def = dest_use_info.defs_not_including_drop().next().unwrap();
                     location = dest_lvalue_def.location;
 
                     let basic_block = &mir[location.block];
@@ -151,6 +160,39 @@ fn run_pass<'a, 'tcx>(&self,
     }
 }
 
+fn eliminate_self_assignments<'tcx>(
+    mir: &mut Mir<'tcx>,
+    def_use_analysis: &DefUseAnalysis<'tcx>,
+) -> bool {
+    let mut changed = false;
+
+    for dest_local in mir.local_decls.indices() {
+        let dest_use_info = def_use_analysis.local_info(dest_local);
+
+        for def in dest_use_info.defs_not_including_drop() {
+            let location = def.location;
+            if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
+                match stmt.kind {
+                    StatementKind::Assign(
+                        Lvalue::Local(local),
+                        Rvalue::Use(Operand::Consume(Lvalue::Local(src_local))),
+                    ) if local == dest_local && dest_local == src_local => {}
+                    _ => {
+                        continue;
+                    }
+                }
+            } else {
+                continue;
+            }
+            debug!("Deleting a self-assignment for {:?}", dest_local);
+            mir.make_statement_nop(location);
+            changed = true;
+        }
+    }
+
+    changed
+}
+
 enum Action<'tcx> {
     PropagateLocalCopy(Local),
     PropagateConstant(Constant<'tcx>),
index dc18cdd8f0dd6006e2270974f8cae06240319d0e..08ca20e50eb7f8eef5f021ad82678a234bb10aec 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::mir::*;
-use rustc::mir::visit::{MutVisitor, Lookup};
+use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::mir::transform::{MirPass, MirSource};
 
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
@@ -35,7 +35,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
 }
 
 impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         if !self.in_validation_statement {
             *ty = self.tcx.erase_regions(ty);
         }
index f2453d3946172f40241d39d8bd46f74316c93546..95e9c8f6df882a5244aa3b9c192c5efb745fbbd4 100644 (file)
@@ -37,7 +37,7 @@
 
 pub struct Inline;
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 struct CallSite<'tcx> {
     callee: DefId,
     substs: &'tcx Substs<'tcx>,
@@ -113,7 +113,9 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
         loop {
             local_change = false;
             while let Some(callsite) = callsites.pop_front() {
+                debug!("checking whether to inline callsite {:?}", callsite);
                 if !self.tcx.is_mir_available(callsite.callee) {
+                    debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite);
                     continue;
                 }
 
@@ -133,10 +135,12 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
                 };
 
                 let start = caller_mir.basic_blocks().len();
-
+                debug!("attempting to inline callsite {:?} - mir={:?}", callsite, callee_mir);
                 if !self.inline_call(callsite, caller_mir, callee_mir) {
+                    debug!("attempting to inline callsite {:?} - failure", callsite);
                     continue;
                 }
+                debug!("attempting to inline callsite {:?} - success", callsite);
 
                 // Add callsites from inlined function
                 for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
@@ -180,16 +184,19 @@ fn should_inline(&self,
                      callee_mir: &Mir<'tcx>)
                      -> bool
     {
+        debug!("should_inline({:?})", callsite);
         let tcx = self.tcx;
 
         // Don't inline closures that have captures
         // FIXME: Handle closures better
         if callee_mir.upvar_decls.len() > 0 {
+            debug!("    upvar decls present - not inlining");
             return false;
         }
 
         // Cannot inline generators which haven't been transformed yet
         if callee_mir.yield_ty.is_some() {
+            debug!("    yield ty present - not inlining");
             return false;
         }
 
@@ -201,7 +208,10 @@ fn should_inline(&self,
             // there are cases that prevent inlining that we
             // need to check for first.
             attr::InlineAttr::Always => true,
-            attr::InlineAttr::Never => return false,
+            attr::InlineAttr::Never => {
+                debug!("#[inline(never)] present - not inlining");
+                return false
+            }
             attr::InlineAttr::Hint => true,
             attr::InlineAttr::None => false,
         };
@@ -211,6 +221,7 @@ fn should_inline(&self,
         // reference unexported symbols
         if callsite.callee.is_local() {
             if callsite.substs.types().count() == 0 && !hinted {
+                debug!("    callee is an exported function - not inlining");
                 return false;
             }
         }
@@ -232,6 +243,7 @@ fn should_inline(&self,
         if callee_mir.basic_blocks().len() <= 3 {
             threshold += threshold / 4;
         }
+        debug!("    final inline threshold = {}", threshold);
 
         // FIXME: Give a bonus to functions with only a single caller
 
@@ -327,12 +339,17 @@ fn should_inline(&self,
             }
         }
 
-        debug!("Inline cost for {:?} is {}", callsite.callee, cost);
-
         if let attr::InlineAttr::Always = hint {
+            debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost);
             true
         } else {
-            cost <= threshold
+            if cost <= threshold {
+                debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold);
+                true
+            } else {
+                debug!("NOT inlining {:?} [cost={} > threshold={}]", callsite, cost, threshold);
+                false
+            }
         }
     }
 
index 322f46cf02b6332b6877c29617eae386875fd858..34cc3a289d18949b3a043dd8d77f651383594057 100644 (file)
@@ -50,6 +50,7 @@ pub(crate) fn provide(providers: &mut Providers) {
     self::check_unsafety::provide(providers);
     *providers = Providers {
         mir_keys,
+        mir_built,
         mir_const,
         mir_validated,
         optimized_mir,
@@ -103,9 +104,17 @@ fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
     Rc::new(set)
 }
 
+fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+    let mir = build::mir_build(tcx, def_id);
+    tcx.alloc_steal_mir(mir)
+}
+
 fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
-    let mut mir = build::mir_build(tcx, def_id);
+    // Unsafety check uses the raw mir, so make sure it is run
+    let _ = tcx.unsafety_check_result(def_id);
+
     let source = MirSource::from_local_def_id(tcx, def_id);
+    let mut mir = tcx.mir_built(def_id).steal();
     transform::run_suite(tcx, source, MIR_CONST, &mut mir);
     tcx.alloc_steal_mir(mir)
 }
@@ -117,7 +126,6 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
         // this point, before we steal the mir-const result.
         let _ = tcx.mir_const_qualif(def_id);
     }
-    let _ = tcx.unsafety_violations(def_id);
 
     let mut mir = tcx.mir_const(def_id).steal();
     transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
index a7570c610d8d34a1b07f0f6e897bd9f1d2c6612f..a2f9bbb174eb737b2b6a91e8a51615b350650c0e 100644 (file)
@@ -29,7 +29,7 @@
 
 pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    regioncx: &mut RegionInferenceContext,
+    regioncx: &mut RegionInferenceContext<'tcx>,
     mir: &Mir<'tcx>,
     mir_source: MirSource,
     liveness: &LivenessResults,
@@ -45,7 +45,7 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
 
 struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-    regioncx: &'cx mut RegionInferenceContext,
+    regioncx: &'cx mut RegionInferenceContext<'tcx>,
     mir: &'cx Mir<'tcx>,
     liveness: &'cx LivenessResults,
     mir_source: MirSource,
@@ -191,6 +191,7 @@ fn add_borrow_constraint(
         _borrowed_lv: &Lvalue<'tcx>,
     ) {
         let tcx = self.infcx.tcx;
+        let span = self.mir.source_info(location).span;
         let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
 
         let destination_region = match destination_ty.sty {
@@ -198,7 +199,8 @@ fn add_borrow_constraint(
             _ => bug!()
         };
 
-        self.regioncx.add_outlives(borrow_region.to_region_index(),
+        self.regioncx.add_outlives(span,
+                                   borrow_region.to_region_index(),
                                    destination_region.to_region_index(),
                                    location.successor_within_block());
     }
@@ -226,7 +228,9 @@ fn add_reborrow_constraint(
                         },
                     }
 
-                    self.regioncx.add_outlives(base_region.to_region_index(),
+                    let span = self.mir.source_info(location).span;
+                    self.regioncx.add_outlives(span,
+                                               base_region.to_region_index(),
                                                borrow_region.to_region_index(),
                                                location.successor_within_block());
                 }
@@ -259,8 +263,9 @@ fn visit_statement(&mut self,
             let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
             let rv_ty = rv.ty(self.mir, tcx);
 
+            let span = self.mir.source_info(location).span;
             for (a, b) in subtype::outlives_pairs(tcx, rv_ty, destination_ty) {
-                self.regioncx.add_outlives(a, b, location.successor_within_block());
+                self.regioncx.add_outlives(span, a, b, location.successor_within_block());
             }
         }
 
diff --git a/src/librustc_mir/transform/nll/free_regions.rs b/src/librustc_mir/transform/nll/free_regions.rs
new file mode 100644 (file)
index 0000000..006a2f9
--- /dev/null
@@ -0,0 +1,88 @@
+// 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.
+
+//! Code to extract the free regions declared on a function and the
+//! relationships between them. For example:
+//!
+//! ```
+//! fn foo<'a, 'b, 'c: 'b>() { }
+//! ```
+//!
+//! here we would be returning a map assigning each of `{'a, 'b, 'c}`
+//! to an index, as well as the `FreeRegionMap` which can compute
+//! relationships between them.
+//!
+//! The code in this file doesn't *do anything* with those results; it
+//! just returns them for other code to use.
+
+use rustc::infer::InferCtxt;
+use rustc::middle::free_region::FreeRegionMap;
+use rustc::mir::transform::MirSource;
+use rustc::ty;
+use rustc::ty::subst::Substs;
+use rustc::util::nodemap::FxHashMap;
+
+#[derive(Debug)]
+pub struct FreeRegions<'tcx> {
+    /// Given a free region defined on this function (either early- or
+    /// late-bound), this maps it to its internal region index. The
+    /// corresponding variable will be "capped" so that it cannot
+    /// grow.
+    pub indices: FxHashMap<ty::Region<'tcx>, usize>,
+
+    /// The map from the typeck tables telling us how to relate free regions.
+    pub free_region_map: &'tcx FreeRegionMap<'tcx>,
+}
+
+pub fn free_regions<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    source: MirSource,
+) -> FreeRegions<'tcx> {
+    debug!("free_regions(source={:?})", source);
+
+    let item_id = source.item_id();
+    let item_def_id = infcx.tcx.hir.local_def_id(item_id);
+
+    let mut indices = FxHashMap();
+
+    // Extract the early regions.
+    let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
+    for item_subst in item_substs {
+        if let Some(region) = item_subst.as_region() {
+            insert_free_region(&mut indices, region);
+        }
+    }
+
+    // Extract the late-bound regions. Use the liberated fn sigs,
+    // where the late-bound regions will have been converted into free
+    // regions, and add them to the map.
+    let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id);
+    let tables = infcx.tcx.typeck_tables_of(item_def_id);
+    let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone();
+    infcx
+        .tcx
+        .for_each_free_region(&fn_sig.inputs_and_output, |region| {
+            if let ty::ReFree(_) = *region {
+                insert_free_region(&mut indices, region);
+            }
+        });
+
+    debug!("free_regions: indices={:#?}", indices);
+
+    FreeRegions { indices, free_region_map: &tables.free_region_map }
+}
+
+fn insert_free_region<'tcx>(
+    free_regions: &mut FxHashMap<ty::Region<'tcx>, usize>,
+    region: ty::Region<'tcx>,
+) {
+    let len = free_regions.len();
+    free_regions.entry(region).or_insert(len);
+}
index d4938dc40bf25689463cedc6c22541944c29adb3..e24def2292ec6e0656f328696cb10c65e79fdb11 100644 (file)
@@ -9,19 +9,19 @@
 // except according to those terms.
 
 use rustc::ty::{self, RegionKind};
-use rustc::mir::{Location, Mir};
+use rustc::mir::Mir;
 use rustc::mir::transform::MirSource;
 use rustc::infer::InferCtxt;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use std::collections::BTreeSet;
-use std::fmt;
 use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
 
 use util as mir_util;
 use self::mir_util::PassWhere;
 
 mod constraint_generation;
+mod free_regions;
 mod subtype;
 
 pub(crate) mod region_infer;
@@ -36,9 +36,12 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     source: MirSource,
     mir: &mut Mir<'tcx>,
-) -> RegionInferenceContext {
+) -> RegionInferenceContext<'tcx> {
+    // Compute named region information.
+    let free_regions = &free_regions::free_regions(infcx, source);
+
     // Replace all regions with fresh inference variables.
-    let num_region_variables = renumber::renumber_mir(infcx, mir);
+    let num_region_variables = renumber::renumber_mir(infcx, free_regions, mir);
 
     // Compute what is live where.
     let liveness = &LivenessResults {
@@ -61,11 +64,9 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
 
     // Create the region inference context, generate the constraints,
     // and then solve them.
-    let mut regioncx = RegionInferenceContext::new(num_region_variables);
+    let mut regioncx = RegionInferenceContext::new(free_regions, num_region_variables, mir);
     constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, source, liveness);
-    let errors = regioncx.solve(infcx, &mir);
-
-    assert!(errors.is_empty(), "FIXME: report region inference failures");
+    regioncx.solve(infcx, &mir);
 
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests.
@@ -149,27 +150,6 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     });
 }
 
-#[derive(Clone, Default, PartialEq, Eq)]
-pub struct Region {
-    points: BTreeSet<Location>,
-}
-
-impl fmt::Debug for Region {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        write!(formatter, "{:?}", self.points)
-    }
-}
-
-impl Region {
-    pub fn add_point(&mut self, point: Location) -> bool {
-        self.points.insert(point)
-    }
-
-    pub fn may_contain(&self, point: Location) -> bool {
-        self.points.contains(&point)
-    }
-}
-
 newtype_index!(RegionIndex {
     DEBUG_FORMAT = "'_#{}r",
 });
index c23d73e784ae9d04b4325e244feab9f66d95b5ef..553d5ad4a320ab687aea1c9d8f6a115b2914f7a2 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Region, RegionIndex};
-use std::mem;
+use super::RegionIndex;
+use super::free_regions::FreeRegions;
 use rustc::infer::InferCtxt;
 use rustc::mir::{Location, Mir};
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc::ty;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::fx::FxHashSet;
+use std::collections::BTreeSet;
+use std::fmt;
+use syntax_pos::Span;
 
-pub struct RegionInferenceContext {
+pub struct RegionInferenceContext<'tcx> {
     /// Contains the definition for every region variable.  Region
     /// variables are identified by their index (`RegionIndex`). The
     /// definition contains information about where the region came
     /// from as well as its final inferred value.
-    definitions: IndexVec<RegionIndex, RegionDefinition>,
+    definitions: IndexVec<RegionIndex, RegionDefinition<'tcx>>,
+
+    /// The indices of all "free regions" in scope. These are the
+    /// lifetime parameters (anonymous and named) declared in the
+    /// function signature:
+    ///
+    ///     fn foo<'a, 'b>(x: &Foo<'a, 'b>)
+    ///            ^^  ^^     ^
+    ///
+    /// These indices will be from 0..N, as it happens, but we collect
+    /// them into a vector for convenience.
+    free_regions: Vec<RegionIndex>,
 
     /// The constraints we have accumulated and used during solving.
     constraints: Vec<Constraint>,
+}
+
+#[derive(Default)]
+struct RegionDefinition<'tcx> {
+    /// If this is a free-region, then this is `Some(X)` where `X` is
+    /// the name of the region.
+    name: Option<ty::Region<'tcx>>,
+
+    /// If true, this is a constant region which cannot grow larger.
+    /// This is used for named regions as well as `'static`.
+    constant: bool,
+
+    /// The current value of this inference variable. This starts out
+    /// empty, but grows as we add constraints. The final value is
+    /// determined when `solve()` is executed.
+    value: Region,
+}
 
-    /// List of errors we have accumulated as we add constraints.
-    /// After solving is done, this is replaced with an empty vector.
-    errors: Vec<InferenceError>,
+/// The value of an individual region variable. Region variables
+/// consist of a set of points in the CFG as well as a set of "free
+/// regions", which are sometimes written as `end(R)`. These
+/// correspond to the named lifetimes and refer to portions of the
+/// caller's control-flow graph -- specifically some portion that can
+/// be reached after we return.
+#[derive(Clone, Default, PartialEq, Eq)]
+struct Region {
+    points: BTreeSet<Location>,
+    free_regions: BTreeSet<RegionIndex>,
 }
 
-pub struct InferenceError {
-    pub constraint_point: Location,
-    pub name: (), // FIXME(nashenas88) RegionName
+impl fmt::Debug for Region {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        formatter
+            .debug_set()
+            .entries(&self.points)
+            .entries(&self.free_regions)
+            .finish()
+    }
 }
 
-#[derive(Default)]
-struct RegionDefinition {
-    name: (), // FIXME(nashenas88) RegionName
-    value: Region,
-    capped: bool,
+impl Region {
+    fn add_point(&mut self, point: Location) -> bool {
+        self.points.insert(point)
+    }
+
+    fn add_free_region(&mut self, region: RegionIndex) -> bool {
+        self.free_regions.insert(region)
+    }
+
+    fn contains_point(&self, point: Location) -> bool {
+        self.points.contains(&point)
+    }
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Constraint {
-    sub: RegionIndex,
+    /// Where did this constraint arise?
+    span: Span,
+
+    /// The region SUP must outlive SUB...
     sup: RegionIndex,
+
+    /// Region that must be outlived.
+    sub: RegionIndex,
+
+    /// At this location.
     point: Location,
 }
 
-impl RegionInferenceContext {
-    pub fn new(num_region_variables: usize) -> Self {
-        Self {
+impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
+    /// Creates a new region inference context with a total of
+    /// `num_region_variables` valid inference variables; the first N
+    /// of those will be constant regions representing the free
+    /// regions defined in `free_regions`.
+    pub fn new(
+        free_regions: &FreeRegions<'tcx>,
+        num_region_variables: usize,
+        mir: &Mir<'tcx>,
+    ) -> Self {
+        let mut result = Self {
             definitions: (0..num_region_variables)
                 .map(|_| RegionDefinition::default())
                 .collect(),
             constraints: Vec::new(),
-            errors: Vec::new(),
-        }
+            free_regions: Vec::new(),
+        };
+
+        result.init_free_regions(free_regions, mir);
+
+        result
     }
 
+    /// Initializes the region variables for each free region
+    /// (lifetime parameter). The first N variables always correspond
+    /// to the free regions appearing in the function signature (both
+    /// named and anonymous) and where clauses. This function iterates
+    /// over those regions and initializes them with minimum values.
+    ///
+    /// For example:
+    ///
+    ///     fn foo<'a, 'b>(..) where 'a: 'b
+    ///
+    /// would initialize two variables like so:
+    ///
+    ///     R0 = { CFG, R0 } // 'a
+    ///     R1 = { CFG, R0, R1 } // 'b
+    ///
+    /// Here, R0 represents `'a`, and it contains (a) the entire CFG
+    /// and (b) any free regions that it outlives, which in this case
+    /// is just itself. R1 (`'b`) in contrast also outlives `'a` and
+    /// hence contains R0 and R1.
+    fn init_free_regions(&mut self, free_regions: &FreeRegions<'tcx>, mir: &Mir<'tcx>) {
+        let &FreeRegions {
+            ref indices,
+            ref free_region_map,
+        } = free_regions;
+
+        // For each free region X:
+        for (free_region, index) in indices {
+            let variable = RegionIndex::new(*index);
+
+            self.free_regions.push(variable);
+
+            // Initialize the name and a few other details.
+            self.definitions[variable].name = Some(free_region);
+            self.definitions[variable].constant = true;
+
+            // Add all nodes in the CFG to `definition.value`.
+            for (block, block_data) in mir.basic_blocks().iter_enumerated() {
+                let definition = &mut self.definitions[variable];
+                for statement_index in 0..block_data.statements.len() + 1 {
+                    let location = Location {
+                        block,
+                        statement_index,
+                    };
+                    definition.value.add_point(location);
+                }
+            }
+
+            // Add `end(X)` into the set for X.
+            self.definitions[variable].value.add_free_region(variable);
+
+            // Go through each region Y that outlives X (i.e., where
+            // Y: X is true). Add `end(X)` into the set for `Y`.
+            for superregion in free_region_map.regions_that_outlive(&free_region) {
+                let superregion_index = RegionIndex::new(indices[superregion]);
+                self.definitions[superregion_index]
+                    .value
+                    .add_free_region(variable);
+            }
+
+            debug!(
+                "init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`",
+                free_region,
+                variable,
+                self.definitions[variable].value
+            );
+        }
+    }
 
     /// Returns an iterator over all the region indices.
     pub fn regions(&self) -> impl Iterator<Item = RegionIndex> {
         self.definitions.indices()
     }
 
-    /// Returns the inferred value for the region `r`.
+    /// Returns true if the region `r` contains the point `p`.
     ///
     /// Until `solve()` executes, this value is not particularly meaningful.
-    pub fn region_value(&self, r: RegionIndex) -> &Region {
-        &self.definitions[r].value
+    pub fn region_contains_point(&self, r: RegionIndex, p: Location) -> bool {
+        self.definitions[r].value.contains_point(p)
     }
 
-    /// Flags a region as being "capped" -- this means that if its
-    /// value is required to grow as a result of some constraint
-    /// (e.g., `add_live_point` or `add_outlives`), that indicates an
-    /// error. This is used for the regions representing named
-    /// lifetime parameters on a function: they get initialized to
-    /// their complete value, and then "capped" so that they can no
-    /// longer grow.
-    #[allow(dead_code)]
-    pub(super) fn cap_var(&mut self, v: RegionIndex) {
-        self.definitions[v].capped = true;
+    /// Returns access to the value of `r` for debugging purposes.
+    pub(super) fn region_value(&self, r: RegionIndex) -> &fmt::Debug {
+        &self.definitions[r].value
     }
 
+    /// Indicates that the region variable `v` is live at the point `point`.
     pub(super) fn add_live_point(&mut self, v: RegionIndex, point: Location) {
         debug!("add_live_point({:?}, {:?})", v, point);
         let definition = &mut self.definitions[v];
-        if definition.value.add_point(point) {
-            if definition.capped {
-                self.errors.push(InferenceError {
-                    constraint_point: point,
-                    name: definition.name,
-                });
-            }
+        if !definition.constant {
+            definition.value.add_point(point);
+        } else {
+            // Constants are used for free regions, which already
+            // contain all the points in the control-flow graph.
+            assert!(definition.value.contains_point(point));
         }
     }
 
-    pub(super) fn add_outlives(&mut self, sup: RegionIndex, sub: RegionIndex, point: Location) {
+    /// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
+    pub(super) fn add_outlives(
+        &mut self,
+        span: Span,
+        sup: RegionIndex,
+        sub: RegionIndex,
+        point: Location,
+    ) {
         debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
-        self.constraints.push(Constraint { sup, sub, point });
+        self.constraints.push(Constraint {
+            span,
+            sup,
+            sub,
+            point,
+        });
     }
 
     /// Perform region inference.
-    pub(super) fn solve<'a, 'gcx, 'tcx>(
+    pub(super) fn solve(&mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, mir: &Mir<'tcx>) {
+        let errors = self.propagate_constraints(mir);
+
+        // worst error msg ever
+        for (fr1, span, fr2) in errors {
+            infcx.tcx.sess.span_err(
+                span,
+                &format!(
+                    "free region `{}` does not outlive `{}`",
+                    self.definitions[fr1].name.unwrap(),
+                    self.definitions[fr2].name.unwrap()
+                ),
+            );
+        }
+    }
+
+    /// Propagate the region constraints: this will grow the values
+    /// for each region variable until all the constraints are
+    /// satisfied. Note that some values may grow **too** large to be
+    /// feasible, but we check this later.
+    fn propagate_constraints(
         &mut self,
-        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-        mir: &'a Mir<'tcx>,
-    ) -> Vec<InferenceError>
-    where
-        'gcx: 'tcx + 'a,
-        'tcx: 'a,
-    {
+        mir: &Mir<'tcx>,
+    ) -> Vec<(RegionIndex, Span, RegionIndex)> {
         let mut changed = true;
-        let mut dfs = Dfs::new(infcx, mir);
+        let mut dfs = Dfs::new(mir);
+        let mut error_regions = FxHashSet();
+        let mut errors = vec![];
         while changed {
             changed = false;
             for constraint in &self.constraints {
+                debug!("constraint: {:?}", constraint);
                 let sub = &self.definitions[constraint.sub].value.clone();
                 let sup_def = &mut self.definitions[constraint.sup];
-                debug!("constraint: {:?}", constraint);
+
                 debug!("    sub (before): {:?}", sub);
                 debug!("    sup (before): {:?}", sup_def.value);
 
-                if dfs.copy(sub, &mut sup_def.value, constraint.point) {
-                    changed = true;
-                    if sup_def.capped {
-                        // This is kind of a hack, but when we add a
-                        // constraint, the "point" is always the point
-                        // AFTER the action that induced the
-                        // constraint. So report the error on the
-                        // action BEFORE that.
-                        assert!(constraint.point.statement_index > 0);
-                        let p = Location {
-                            block: constraint.point.block,
-                            statement_index: constraint.point.statement_index - 1,
-                        };
-
-                        self.errors.push(InferenceError {
-                            constraint_point: p,
-                            name: sup_def.name,
-                        });
+                if !sup_def.constant {
+                    // If this is not a constant, then grow the value as needed to
+                    // accommodate the outlives constraint.
+
+                    if dfs.copy(sub, &mut sup_def.value, constraint.point) {
+                        changed = true;
                     }
-                }
 
-                debug!("    sup (after) : {:?}", sup_def.value);
-                debug!("    changed     : {:?}", changed);
+                    debug!("    sup (after) : {:?}", sup_def.value);
+                    debug!("    changed     : {:?}", changed);
+                } else {
+                    // If this is a constant, check whether it *would
+                    // have* to grow in order for the constraint to be
+                    // satisfied. If so, create an error.
+
+                    let mut sup_value = sup_def.value.clone();
+                    if dfs.copy(sub, &mut sup_value, constraint.point) {
+                        // Constant values start out with the entire
+                        // CFG, so it must be some new free region
+                        // that was added. Find one.
+                        let &new_region = sup_value
+                            .free_regions
+                            .difference(&sup_def.value.free_regions)
+                            .next()
+                            .unwrap();
+                        debug!("    new_region : {:?}", new_region);
+                        if error_regions.insert(constraint.sup) {
+                            errors.push((constraint.sup, constraint.span, new_region));
+                        }
+                    }
+                }
             }
             debug!("\n");
         }
-
-        mem::replace(&mut self.errors, Vec::new())
+        errors
     }
 }
 
-struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
-    #[allow(dead_code)] infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+struct Dfs<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
 }
 
-impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> {
-    fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        Self { infcx, mir }
+impl<'a, 'tcx> Dfs<'a, 'tcx> {
+    fn new(mir: &'a Mir<'tcx>) -> Self {
+        Self { mir }
     }
 
     fn copy(
@@ -180,7 +347,7 @@ fn copy(
         while let Some(p) = stack.pop() {
             debug!("        dfs: p={:?}", p);
 
-            if !from_region.may_contain(p) {
+            if !from_region.contains_point(p) {
                 debug!("            not in from-region");
                 continue;
             }
@@ -215,19 +382,14 @@ fn copy(
             };
 
             if successor_points.is_empty() {
-                // FIXME handle free regions
                 // If we reach the END point in the graph, then copy
                 // over any skolemized end points in the `from_region`
                 // and make sure they are included in the `to_region`.
-                // for region_decl in self.infcx.tcx.tables.borrow().free_region_map() {
-                //     // FIXME(nashenas88) figure out skolemized_end points
-                //     let block = self.env.graph.skolemized_end(region_decl.name);
-                //     let skolemized_end_point = Location {
-                //         block,
-                //         statement_index: 0,
-                //     };
-                //     changed |= to_region.add_point(skolemized_end_point);
-                // }
+
+                debug!("        dfs: free_regions={:?}", from_region.free_regions);
+                for &fr in &from_region.free_regions {
+                    changed |= to_region.free_regions.insert(fr);
+                }
             } else {
                 stack.extend(successor_points);
             }
index 589179c2066854ef05e451a6967acb333eec0454..a3ff7a041ca0714bd2d963274d377cd4ab03f18b 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::TypeFoldable;
+use rustc_data_structures::indexed_vec::Idx;
 use rustc::ty::subst::{Kind, Substs};
-use rustc::ty::{Ty, ClosureSubsts, RegionVid, RegionKind};
-use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
-use rustc::mir::visit::{MutVisitor, Lookup};
+use rustc::ty::{self, ClosureSubsts, RegionKind, RegionVid, Ty, TypeFoldable};
+use rustc::mir::{BasicBlock, Local, Location, Mir, Rvalue, Statement, StatementKind};
+use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{self as rustc_infer, InferCtxt};
 use syntax_pos::DUMMY_SP;
 use std::collections::HashMap;
 
+use super::free_regions::FreeRegions;
+
 /// Replaces all free regions appearing in the MIR with fresh
 /// inference variables, returning the number of variables created.
-pub fn renumber_mir<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                    mir: &mut Mir<'tcx>)
-                                    -> usize
-{
-    let mut visitor = NLLVisitor::new(infcx);
+pub fn renumber_mir<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    free_regions: &FreeRegions<'tcx>,
+    mir: &mut Mir<'tcx>,
+) -> usize {
+    // Create inference variables for each of the free regions
+    // declared on the function signature.
+    let free_region_inference_vars = (0..free_regions.indices.len())
+        .map(|_| {
+            infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
+        })
+        .collect();
+
+    let mut visitor = NLLVisitor {
+        infcx,
+        lookup_map: HashMap::new(),
+        num_region_variables: free_regions.indices.len(),
+        free_regions,
+        free_region_inference_vars,
+        arg_count: mir.arg_count,
+    };
     visitor.visit_mir(mir);
     visitor.num_region_variables
 }
 
 struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
-    lookup_map: HashMap<RegionVid, Lookup>,
+    lookup_map: HashMap<RegionVid, TyContext>,
     num_region_variables: usize,
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    free_regions: &'a FreeRegions<'tcx>,
+    free_region_inference_vars: Vec<ty::Region<'tcx>>,
+    arg_count: usize,
 }
 
 impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
-        NLLVisitor {
-            infcx,
-            lookup_map: HashMap::new(),
-            num_region_variables: 0
-        }
+    /// Replaces all regions appearing in `value` with fresh inference
+    /// variables. This is what we do for almost the entire MIR, with
+    /// the exception of the declared types of our arguments.
+    fn renumber_regions<T>(&mut self, value: &T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.infcx
+            .tcx
+            .fold_regions(value, &mut false, |_region, _depth| {
+                self.num_region_variables += 1;
+                self.infcx
+                    .next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
+            })
     }
 
-    fn renumber_regions<T>(&mut self, value: &T) -> T where T: TypeFoldable<'tcx> {
-        self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
-            self.num_region_variables += 1;
-            self.infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
-        })
+    /// Renumbers the regions appearing in `value`, but those regions
+    /// are expected to be free regions from the function signature.
+    fn renumber_free_regions<T>(&mut self, value: &T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.infcx
+            .tcx
+            .fold_regions(value, &mut false, |region, _depth| {
+                let index = self.free_regions.indices[&region];
+                self.free_region_inference_vars[index]
+            })
     }
 
-    fn store_region(&mut self, region: &RegionKind, lookup: Lookup) {
+    fn store_region(&mut self, region: &RegionKind, lookup: TyContext) {
         if let RegionKind::ReVar(rid) = *region {
             self.lookup_map.entry(rid).or_insert(lookup);
         }
     }
 
-    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) {
+    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, ty_context: TyContext) {
         for region in ty.regions() {
-            self.store_region(region, lookup);
+            self.store_region(region, ty_context);
         }
     }
 
-    fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) {
+    fn store_kind_regions(&mut self, kind: &'tcx Kind, ty_context: TyContext) {
         if let Some(ty) = kind.as_type() {
-            self.store_ty_regions(&ty, lookup);
+            self.store_ty_regions(&ty, ty_context);
         } else if let Some(region) = kind.as_region() {
-            self.store_region(region, lookup);
+            self.store_region(region, ty_context);
         }
     }
+
+    fn is_argument_or_return_slot(&self, local: Local) -> bool {
+        // The first argument is return slot, next N are arguments.
+        local.index() <= self.arg_count
+    }
 }
 
 impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
+        let is_arg = match ty_context {
+            TyContext::LocalDecl { local, .. } => self.is_argument_or_return_slot(local),
+            _ => false,
+        };
+
         let old_ty = *ty;
-        *ty = self.renumber_regions(&old_ty);
-        self.store_ty_regions(ty, lookup);
+        *ty = if is_arg {
+            self.renumber_free_regions(&old_ty)
+        } else {
+            self.renumber_regions(&old_ty)
+        };
+        self.store_ty_regions(ty, ty_context);
     }
 
     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
-        *substs = self.renumber_regions(&{*substs});
-        let lookup = Lookup::Loc(location);
+        *substs = self.renumber_regions(&{ *substs });
+        let ty_context = TyContext::Location(location);
         for kind in *substs {
-            self.store_kind_regions(kind, lookup);
+            self.store_kind_regions(kind, ty_context);
         }
     }
 
@@ -91,8 +141,8 @@ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
             Rvalue::Ref(ref mut r, _, _) => {
                 let old_r = *r;
                 *r = self.renumber_regions(&old_r);
-                let lookup = Lookup::Loc(location);
-                self.store_region(r, lookup);
+                let ty_context = TyContext::Location(location);
+                self.store_region(r, ty_context);
             }
             Rvalue::Use(..) |
             Rvalue::Repeat(..) |
@@ -110,20 +160,20 @@ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_closure_substs(&mut self,
-                            substs: &mut ClosureSubsts<'tcx>,
-                            location: Location) {
+    fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
         *substs = self.renumber_regions(substs);
-        let lookup = Lookup::Loc(location);
+        let ty_context = TyContext::Location(location);
         for kind in substs.substs {
-            self.store_kind_regions(kind, lookup);
+            self.store_kind_regions(kind, ty_context);
         }
     }
 
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &mut Statement<'tcx>,
-                       location: Location) {
+    fn visit_statement(
+        &mut self,
+        block: BasicBlock,
+        statement: &mut Statement<'tcx>,
+        location: Location,
+    ) {
         if let StatementKind::EndRegion(_) = statement.kind {
             statement.kind = StatementKind::Nop;
         }
index d8dc7a8d5cc7d3e57f377828295f4bfd900a61a7..b07e818ee87525045e6d237d575d74cb66117cef 100644 (file)
@@ -92,8 +92,8 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.sanitize_type(rvalue, rval_ty);
     }
 
-    fn visit_local_decl(&mut self, local_decl: &LocalDecl<'tcx>) {
-        self.super_local_decl(local_decl);
+    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
+        self.super_local_decl(local, local_decl);
         self.sanitize_type(local_decl, local_decl.ty);
     }
 
index bd9fb4bc3cc5f6fd203c4372b3b5a31d1f170803..9ada8f2bebf706c1c56a65ff0b6e020a0eb178cc 100644 (file)
@@ -15,6 +15,8 @@
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::marker::PhantomData;
 use std::mem;
+use std::slice;
+use std::iter;
 
 pub struct DefUseAnalysis<'tcx> {
     info: IndexVec<Local, Info<'tcx>>,
@@ -39,6 +41,8 @@ pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
     }
 
     pub fn analyze(&mut self, mir: &Mir<'tcx>) {
+        self.clear();
+
         let mut finder = DefUseFinder {
             info: mem::replace(&mut self.info, IndexVec::new()),
         };
@@ -46,6 +50,12 @@ pub fn analyze(&mut self, mir: &Mir<'tcx>) {
         self.info = finder.info
     }
 
+    fn clear(&mut self) {
+        for info in &mut self.info {
+            info.clear();
+        }
+    }
+
     pub fn local_info(&self, local: Local) -> &Info<'tcx> {
         &self.info[local]
     }
@@ -93,14 +103,24 @@ fn new() -> Info<'tcx> {
         }
     }
 
+    fn clear(&mut self) {
+        self.defs_and_uses.clear();
+    }
+
     pub fn def_count(&self) -> usize {
         self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
     }
 
     pub fn def_count_not_including_drop(&self) -> usize {
+        self.defs_not_including_drop().count()
+    }
+
+    pub fn defs_not_including_drop(
+        &self,
+    ) -> iter::Filter<slice::Iter<Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
         self.defs_and_uses.iter().filter(|lvalue_use| {
             lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
-        }).count()
+        })
     }
 
     pub fn use_count(&self) -> usize {
index 1d924175b2167dca4fd27ca849a2322b00f42059..0f07f1fe550cca769f204a6ade8c289870bfbe8a 100644 (file)
@@ -132,9 +132,13 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         let p = Path::new(file_dir);
         file_path.push(p);
     };
+
     let _ = fs::create_dir_all(&file_path);
-    let file_name = format!("rustc.node{}{}{}.{}.{}.mir",
-                            source.item_id(), promotion_id, pass_num, pass_name, disambiguator);
+    let function_name  = tcx.hir.def_path_from_id(source.item_id())
+        .map(|d| d.to_filename_friendly_no_crate())
+        .unwrap_or(format!("node{}", source.item_id()));
+    let file_name = format!("rustc.{}{}{}.{}.{}.mir",
+                            function_name, promotion_id, pass_num, pass_name, disambiguator);
     file_path.push(&file_name);
     let _ = fs::File::create(&file_path).and_then(|mut file| {
         writeln!(file, "// MIR for `{}`", node_path)?;
index 6d9c294884128688364485bd5e63d7908e7ffe51..40adc6bcb122fb727542c02d9504f246d7593502 100644 (file)
@@ -72,7 +72,8 @@ fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err:
             match arg.pat.node {
                 PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
                 PatKind::Wild => {}
-                PatKind::Ident(..) => report_err(arg.pat.span, true),
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
+                    report_err(arg.pat.span, true),
                 _ => report_err(arg.pat.span, false),
             }
         }
@@ -151,14 +152,8 @@ fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.node {
             TyKind::BareFn(ref bfty) => {
                 self.check_decl_no_pat(&bfty.decl, |span, _| {
-                    let mut err = struct_span_err!(self.session,
-                                                   span,
-                                                   E0561,
-                                                   "patterns aren't allowed in function pointer \
-                                                    types");
-                    err.span_note(span,
-                                  "this is a recent error, see issue #35203 for more details");
-                    err.emit();
+                    struct_span_err!(self.session, span, E0561,
+                                     "patterns aren't allowed in function pointer types").emit();
                 });
             }
             TyKind::TraitObject(ref bounds, ..) => {
@@ -260,12 +255,16 @@ fn visit_item(&mut self, item: &'a Item) {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
                         self.check_trait_fn_not_const(sig.constness);
                         if block.is_none() {
-                            self.check_decl_no_pat(&sig.decl, |span, _| {
-                                self.session.buffer_lint(
-                                    lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
-                                    trait_item.id, span,
-                                    "patterns aren't allowed in methods \
-                                     without bodies");
+                            self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
+                                if mut_ident {
+                                    self.session.buffer_lint(
+                                        lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                                        trait_item.id, span,
+                                        "patterns aren't allowed in methods without bodies");
+                                } else {
+                                    struct_span_err!(self.session, span, E0642,
+                                        "patterns aren't allowed in methods without bodies").emit();
+                                }
                             });
                         }
                     }
@@ -299,18 +298,10 @@ fn visit_item(&mut self, item: &'a Item) {
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match fi.node {
             ForeignItemKind::Fn(ref decl, _) => {
-                self.check_decl_no_pat(decl, |span, is_recent| {
-                    let mut err = struct_span_err!(self.session,
-                                                   span,
-                                                   E0130,
-                                                   "patterns aren't allowed in foreign function \
-                                                    declarations");
-                    err.span_label(span, "pattern not allowed in foreign function");
-                    if is_recent {
-                        err.span_note(span,
-                                      "this is a recent error, see issue #35203 for more details");
-                    }
-                    err.emit();
+                self.check_decl_no_pat(decl, |span, _| {
+                    struct_span_err!(self.session, span, E0130,
+                                     "patterns aren't allowed in foreign function declarations")
+                        .span_label(span, "pattern not allowed in foreign function").emit();
                 });
             }
             ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
index a6eaff4481c769b8a599a34049f9cc9287532552..4515d9c7837c8ed40a0a0df8d34e5bf1d17976e1 100644 (file)
@@ -43,7 +43,7 @@
 use rustc::ty::subst::Substs;
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
-use rustc::util::nodemap::{ItemLocalMap, NodeSet};
+use rustc::util::nodemap::{ItemLocalSet, NodeSet};
 use rustc::lint::builtin::CONST_ERR;
 use rustc::hir::{self, PatKind, RangeEnd};
 use std::rc::Rc;
@@ -79,12 +79,12 @@ fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      .expect("rvalue_promotable_map invoked with non-local def-id");
     let body_id = tcx.hir.body_owned_by(node_id);
     let body_hir_id = tcx.hir.node_to_hir_id(body_id.node_id);
-    tcx.rvalue_promotable_map(def_id).contains_key(&body_hir_id.local_id)
+    tcx.rvalue_promotable_map(def_id).contains(&body_hir_id.local_id)
 }
 
 fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    def_id: DefId)
-                                   -> Rc<ItemLocalMap<bool>>
+                                   -> Rc<ItemLocalSet>
 {
     let outer_def_id = tcx.closure_base_def_id(def_id);
     if outer_def_id != def_id {
@@ -100,7 +100,7 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         mut_rvalue_borrows: NodeSet(),
         param_env: ty::ParamEnv::empty(Reveal::UserFacing),
         identity_substs: Substs::empty(),
-        result_map: ItemLocalMap(),
+        result: ItemLocalSet(),
     };
 
     // `def_id` should be a `Body` owner
@@ -109,7 +109,7 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let body_id = tcx.hir.body_owned_by(node_id);
     visitor.visit_nested_body(body_id);
 
-    Rc::new(visitor.result_map)
+    Rc::new(visitor.result)
 }
 
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
@@ -121,7 +121,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     identity_substs: &'tcx Substs<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
-    result_map: ItemLocalMap<bool>,
+    result: ItemLocalSet,
 }
 
 impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
@@ -322,7 +322,9 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
             }
         }
 
-        self.result_map.insert(ex.hir_id.local_id, self.promotable);
+        if self.promotable {
+            self.result.insert(ex.hir_id.local_id);
+        }
         self.promotable &= outer;
     }
 }
index 1bfa5943ee90a1849851be8459648cfa34b6018e..3597a6f18287e62e2e9d41640e2b918f8587b84e 100644 (file)
@@ -264,4 +264,5 @@ fn foo() {}
     E0226, // only a single explicit lifetime bound is permitted
     E0472, // asm! is unsupported on this target
     E0561, // patterns aren't allowed in function pointer types
+    E0642, // patterns aren't allowed in methods without bodies
 }
index 30e2ba61dbda7ef90b50b4c6fd5605562f517a78..ab41ad1e0995056c46635618869377fffad65af6 100644 (file)
@@ -14,7 +14,7 @@
 
 use rustc_const_math::{ConstUsize};
 use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
-use rustc::mir::{Constant, Literal, Location, LocalDecl};
+use rustc::mir::{Constant, Literal, Location, Local, LocalDecl};
 use rustc::mir::{Lvalue, LvalueElem, LvalueProjection};
 use rustc::mir::{Mir, Operand, ProjectionElem};
 use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
@@ -270,9 +270,10 @@ fn visit_const_usize(&mut self,
     }
 
     fn visit_local_decl(&mut self,
+                        local: Local,
                         local_decl: &LocalDecl<'tcx>) {
         self.record("LocalDecl", local_decl);
-        self.super_local_decl(local_decl);
+        self.super_local_decl(local, local_decl);
     }
 
     fn visit_visibility_scope(&mut self,
index a10bce293422645ea01729844bb0c4e9edb3f1bf..b30fc38fcbcdf617a92fda12cac1550c57b18ffa 100644 (file)
@@ -250,7 +250,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 }
             }
 
-            ItemKind::ExternCrate(_) => {
+            ItemKind::ExternCrate(as_name) => {
                 self.crate_loader.process_item(item, &self.definitions);
 
                 // n.b. we don't need to look at the path option here, because cstore already did
@@ -265,7 +265,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     id: item.id,
                     parent,
                     imported_module: Cell::new(Some(module)),
-                    subclass: ImportDirectiveSubclass::ExternCrate,
+                    subclass: ImportDirectiveSubclass::ExternCrate(as_name),
                     span: item.span,
                     module_path: Vec::new(),
                     vis: Cell::new(vis),
index a66d1ce0859b7efe179eda60087d3c5c7ddf4a7e..5820acf1b9006132aefa9479ceccdf750c6cfca5 100644 (file)
@@ -120,7 +120,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
             _ if directive.used.get() ||
                  directive.vis.get() == ty::Visibility::Public ||
                  directive.span.source_equal(&DUMMY_SP) => {}
-            ImportDirectiveSubclass::ExternCrate => {
+            ImportDirectiveSubclass::ExternCrate(_) => {
                 resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
             }
             ImportDirectiveSubclass::MacroUse => {
index bed9f37c5157fab483b947fbf3b70a54e706f490..8207057fd0aae2825c4dd979af5e36fec7aa6481 100644 (file)
@@ -377,12 +377,6 @@ enum PatternSource {
 }
 
 impl PatternSource {
-    fn is_refutable(self) -> bool {
-        match self {
-            PatternSource::Match | PatternSource::IfLet | PatternSource::WhileLet => true,
-            PatternSource::Let | PatternSource::For | PatternSource::FnParam  => false,
-        }
-    }
     fn descr(self) -> &'static str {
         match self {
             PatternSource::Match => "match binding",
@@ -1118,7 +1112,7 @@ fn is_extern_crate(&self) -> bool {
         match self.kind {
             NameBindingKind::Import {
                 directive: &ImportDirective {
-                    subclass: ImportDirectiveSubclass::ExternCrate, ..
+                    subclass: ImportDirectiveSubclass::ExternCrate(_), ..
                 }, ..
             } => true,
             _ => false,
@@ -1132,6 +1126,15 @@ fn is_import(&self) -> bool {
         }
     }
 
+    fn is_renamed_extern_crate(&self) -> bool {
+        if let NameBindingKind::Import { directive, ..} = self.kind {
+            if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass {
+                return true;
+            }
+        }
+        false
+    }
+
     fn is_glob_import(&self) -> bool {
         match self.kind {
             NameBindingKind::Import { directive, .. } => directive.is_glob(),
@@ -2379,20 +2382,24 @@ fn resolve_pattern(&mut self,
                                                                       false, pat.span)
                                       .and_then(LexicalScopeBinding::item);
                     let resolution = binding.map(NameBinding::def).and_then(|def| {
-                        let ivmode = BindingMode::ByValue(Mutability::Immutable);
-                        let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
-                                             bmode != ivmode;
+                        let is_syntactic_ambiguity = opt_pat.is_none() &&
+                            bmode == BindingMode::ByValue(Mutability::Immutable);
                         match def {
                             Def::StructCtor(_, CtorKind::Const) |
                             Def::VariantCtor(_, CtorKind::Const) |
-                            Def::Const(..) if !always_binding => {
-                                // A unit struct/variant or constant pattern.
+                            Def::Const(..) if is_syntactic_ambiguity => {
+                                // Disambiguate in favor of a unit struct/variant
+                                // or constant pattern.
                                 self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
                                 Some(PathResolution::new(def))
                             }
                             Def::StructCtor(..) | Def::VariantCtor(..) |
                             Def::Const(..) | Def::Static(..) => {
-                                // A fresh binding that shadows something unacceptable.
+                                // This is unambiguously a fresh binding, either syntactically
+                                // (e.g. `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
+                                // to something unusable as a pattern (e.g. constructor function),
+                                // but we still conservatively report an error, see
+                                // issues/33118#issuecomment-233962221 for one reason why.
                                 resolve_error(
                                     self,
                                     ident.span,
@@ -2401,7 +2408,7 @@ fn resolve_pattern(&mut self,
                                 );
                                 None
                             }
-                            Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
+                            Def::Fn(..) | Def::Err => {
                                 // These entities are explicitly allowed
                                 // to be shadowed by fresh bindings.
                                 None
@@ -2603,7 +2610,7 @@ fn smart_resolve_path_fragment(&mut self,
                             }
                         }
                         err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
-                                                       path_str));
+                                                     path_str));
                         return (err, candidates);
                     }
                     _ => {}
@@ -3700,7 +3707,8 @@ fn report_conflict<'b>(&mut self,
             let cm = self.session.codemap();
             let rename_msg = "You can use `as` to change the binding name of the import";
 
-            if let Ok(snippet) = cm.span_to_snippet(binding.span) {
+            if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
+                                           binding.is_renamed_extern_crate()) {
                 err.span_suggestion(binding.span,
                                     rename_msg,
                                     format!("{} as Other{}", snippet, name));
index b85bf18ea800c4fec42d0a7947aa566c4d49d3e6..bcbabd700946ad904b2ffaba39e05dd6adc17734 100644 (file)
@@ -23,7 +23,7 @@
 use rustc::hir::def::*;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
-use syntax::ast::{Ident, SpannedIdent, NodeId};
+use syntax::ast::{Ident, Name, SpannedIdent, NodeId};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
 use syntax::parse::token;
@@ -48,7 +48,7 @@ pub enum ImportDirectiveSubclass<'a> {
         max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
         // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
     },
-    ExternCrate,
+    ExternCrate(Option<Name>),
     MacroUse,
 }
 
@@ -923,7 +923,7 @@ fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> St
     match *subclass {
         SingleImport { source, .. } => source.to_string(),
         GlobImport { .. } => "*".to_string(),
-        ExternCrate => "<extern crate>".to_string(),
+        ExternCrate(_) => "<extern crate>".to_string(),
         MacroUse => "#[macro_use]".to_string(),
     }
 }
index d190ae1431fd80db73e78f9d15c27645a924f7d2..272b1cb8d35160e45038d7d63f8df2240f6adfbb 100644 (file)
 
 use std::path::Path;
 
-use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
+use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID};
 use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
-use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string};
+use syntax::print::pprust::{bounds_to_string, generics_to_string, path_to_string, ty_to_string};
 use syntax::ptr::P;
 use syntax::codemap::Spanned;
 use syntax_pos::*;
 
-use {escape, generated_code, SaveContext, PathCollector, lower_attributes};
-use json_dumper::{JsonDumper, DumpOutput};
+use {escape, generated_code, lower_attributes, PathCollector, SaveContext};
+use json_dumper::{DumpOutput, JsonDumper};
 use span_utils::SpanUtils;
 use sig;
 
-use rls_data::{CratePreludeData, GlobalCrateId, Import, ImportKind, SpanData,
-               Ref, RefKind, Def, DefKind, Relation, RelationKind};
+use rls_data::{CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref, RefKind,
+               Relation, RelationKind, SpanData};
 
 macro_rules! down_cast_data {
     ($id:ident, $kind:ident, $sp:expr) => {
@@ -77,9 +77,10 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> {
 }
 
 impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
-    pub fn new(save_ctxt: SaveContext<'l, 'tcx>,
-               dumper: &'ll mut JsonDumper<O>)
-               -> DumpVisitor<'l, 'tcx, 'll, O> {
+    pub fn new(
+        save_ctxt: SaveContext<'l, 'tcx>,
+        dumper: &'ll mut JsonDumper<O>,
+    ) -> DumpVisitor<'l, 'tcx, 'll, O> {
         let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
         DumpVisitor {
             tcx: save_ctxt.tcx,
@@ -93,7 +94,8 @@ pub fn new(save_ctxt: SaveContext<'l, 'tcx>,
     }
 
     fn nest_scope<F>(&mut self, scope_id: NodeId, f: F)
-        where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>)
+    where
+        F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
     {
         let parent_scope = self.cur_scope;
         self.cur_scope = scope_id;
@@ -102,7 +104,8 @@ fn nest_scope<F>(&mut self, scope_id: NodeId, f: F)
     }
 
     fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
-        where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>)
+    where
+        F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
     {
         let item_def_id = self.tcx.hir.local_def_id(item_id);
         if self.tcx.has_typeck_tables(item_def_id) {
@@ -133,8 +136,11 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
                 name: name.into(),
-                disambiguator: self.tcx.sess.local_crate_disambiguator()
-                                   .to_fingerprint().as_value(),
+                disambiguator: self.tcx
+                    .sess
+                    .local_crate_disambiguator()
+                    .to_fingerprint()
+                    .as_value(),
             },
             crate_root: crate_root.unwrap_or("<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
@@ -210,10 +216,10 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
         if len <= 1 {
             return;
         }
-        let sub_paths = &sub_paths[.. (len-1)];
+        let sub_paths = &sub_paths[..(len - 1)];
 
         // write the trait part of the sub-path
-        let (ref span, _) = sub_paths[len-2];
+        let (ref span, _) = sub_paths[len - 2];
         let span = self.span_from_span(*span);
         self.dumper.dump_ref(Ref {
             kind: RefKind::Type,
@@ -225,7 +231,7 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
         if len <= 2 {
             return;
         }
-        let sub_paths = &sub_paths[..len-2];
+        let sub_paths = &sub_paths[..len - 2];
         for &(ref span, _) in sub_paths {
             let span = self.span_from_span(*span);
             self.dumper.dump_ref(Ref {
@@ -243,11 +249,13 @@ fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
         }
     }
 
-    fn process_def_kind(&mut self,
-                        ref_id: NodeId,
-                        span: Span,
-                        sub_span: Option<Span>,
-                        def_id: DefId) {
+    fn process_def_kind(
+        &mut self,
+        ref_id: NodeId,
+        span: Span,
+        sub_span: Option<Span>,
+        def_id: DefId,
+    ) {
         if self.span.filter_generated(sub_span, span) {
             return;
         }
@@ -309,9 +317,7 @@ fn process_def_kind(&mut self,
             HirDef::PrimTy(_) |
             HirDef::GlobalAsm(_) |
             HirDef::Err => {
-               span_bug!(span,
-                         "process_def_kind for unexpected item: {:?}",
-                         def);
+                span_bug!(span, "process_def_kind for unexpected item: {:?}", def);
             }
         }
     }
@@ -334,49 +340,55 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                     let id = ::id_from_node_id(id, &self.save_ctxt);
                     let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
-                    self.dumper.dump_def(false, Def {
-                        kind: DefKind::Local,
-                        id,
-                        span,
-                        name: i.to_string(),
-                        qualname: format!("{}::{}", qualname, i.to_string()),
-                        value: typ,
-                        parent: None,
-                        children: vec![],
-                        decl_id: None,
-                        docs: String::new(),
-                        sig: None,
-                        attributes:vec![],
-                    });
+                    self.dumper.dump_def(
+                        false,
+                        Def {
+                            kind: DefKind::Local,
+                            id,
+                            span,
+                            name: i.to_string(),
+                            qualname: format!("{}::{}", qualname, i.to_string()),
+                            value: typ,
+                            parent: None,
+                            children: vec![],
+                            decl_id: None,
+                            docs: String::new(),
+                            sig: None,
+                            attributes: vec![],
+                        },
+                    );
                 }
             }
         }
     }
 
-    fn process_method(&mut self,
-                      sig: &'l ast::MethodSig,
-                      body: Option<&'l ast::Block>,
-                      id: ast::NodeId,
-                      name: ast::Ident,
-                      generics: &'l ast::Generics,
-                      vis: ast::Visibility,
-                      span: Span) {
+    fn process_method(
+        &mut self,
+        sig: &'l ast::MethodSig,
+        body: Option<&'l ast::Block>,
+        id: ast::NodeId,
+        name: ast::Ident,
+        generics: &'l ast::Generics,
+        vis: ast::Visibility,
+        span: Span,
+    ) {
         debug!("process_method: {}:{}", id, name);
 
         if let Some(mut method_data) = self.save_ctxt.get_method_data(id, name.name, span) {
-
             let sig_str = ::make_signature(&sig.decl, &generics);
             if body.is_some() {
-                self.nest_tables(id, |v| {
-                    v.process_formals(&sig.decl.inputs, &method_data.qualname)
-                });
+                self.nest_tables(
+                    id,
+                    |v| v.process_formals(&sig.decl.inputs, &method_data.qualname),
+                );
             }
 
             self.process_generic_params(&generics, span, &method_data.qualname, id);
 
             method_data.value = sig_str;
             method_data.sig = sig::method_signature(id, name, generics, sig, &self.save_ctxt);
-            self.dumper.dump_def(vis == ast::Visibility::Public, method_data);
+            self.dumper
+                .dump_def(vis == ast::Visibility::Public, method_data);
         }
 
         // walk arg and return types
@@ -397,57 +409,66 @@ fn process_method(&mut self,
     fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
         let field_data = self.save_ctxt.get_field_data(field, parent_id);
         if let Some(field_data) = field_data {
-            self.dumper.dump_def(field.vis == ast::Visibility::Public, field_data);
+            self.dumper
+                .dump_def(field.vis == ast::Visibility::Public, field_data);
         }
     }
 
     // Dump generic params bindings, then visit_generics
-    fn process_generic_params(&mut self,
-                              generics: &'l ast::Generics,
-                              full_span: Span,
-                              prefix: &str,
-                              id: NodeId) {
+    fn process_generic_params(
+        &mut self,
+        generics: &'l ast::Generics,
+        full_span: Span,
+        prefix: &str,
+        id: NodeId,
+    ) {
         for param in &generics.ty_params {
             let param_ss = param.span;
             let name = escape(self.span.snippet(param_ss));
             // Append $id to name to make sure each one is unique
-            let qualname = format!("{}::{}${}",
-                                   prefix,
-                                   name,
-                                   id);
+            let qualname = format!("{}::{}${}", prefix, name, id);
             if !self.span.filter_generated(Some(param_ss), full_span) {
                 let id = ::id_from_node_id(param.id, &self.save_ctxt);
                 let span = self.span_from_span(param_ss);
 
-                self.dumper.dump_def(false, Def {
-                    kind: DefKind::Type,
-                    id,
-                    span,
-                    name,
-                    qualname,
-                    value: String::new(),
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: String::new(),
-                    sig: None,
-                    attributes: vec![],
-                });
+                self.dumper.dump_def(
+                    false,
+                    Def {
+                        kind: DefKind::Type,
+                        id,
+                        span,
+                        name,
+                        qualname,
+                        value: String::new(),
+                        parent: None,
+                        children: vec![],
+                        decl_id: None,
+                        docs: String::new(),
+                        sig: None,
+                        attributes: vec![],
+                    },
+                );
             }
         }
         self.visit_generics(generics);
     }
 
-    fn process_fn(&mut self,
-                  item: &'l ast::Item,
-                  decl: &'l ast::FnDecl,
-                  ty_params: &'l ast::Generics,
-                  body: &'l ast::Block) {
+    fn process_fn(
+        &mut self,
+        item: &'l ast::Item,
+        decl: &'l ast::FnDecl,
+        ty_params: &'l ast::Generics,
+        body: &'l ast::Block,
+    ) {
         if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
             down_cast_data!(fn_data, DefData, item.span);
-            self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname));
+            self.nest_tables(
+                item.id,
+                |v| v.process_formals(&decl.inputs, &fn_data.qualname),
+            );
             self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
-            self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data);
+            self.dumper
+                .dump_def(item.vis == ast::Visibility::Public, fn_data);
         }
 
         for arg in &decl.inputs {
@@ -461,29 +482,34 @@ fn process_fn(&mut self,
         self.nest_tables(item.id, |v| v.nest_scope(item.id, |v| v.visit_block(&body)));
     }
 
-    fn process_static_or_const_item(&mut self,
-                                    item: &'l ast::Item,
-                                    typ: &'l ast::Ty,
-                                    expr: &'l ast::Expr) {
+    fn process_static_or_const_item(
+        &mut self,
+        item: &'l ast::Item,
+        typ: &'l ast::Ty,
+        expr: &'l ast::Expr,
+    ) {
         self.nest_tables(item.id, |v| {
             if let Some(var_data) = v.save_ctxt.get_item_data(item) {
                 down_cast_data!(var_data, DefData, item.span);
-                v.dumper.dump_def(item.vis == ast::Visibility::Public, var_data);
+                v.dumper
+                    .dump_def(item.vis == ast::Visibility::Public, var_data);
             }
             v.visit_ty(&typ);
             v.visit_expr(expr);
         });
     }
 
-    fn process_assoc_const(&mut self,
-                           id: ast::NodeId,
-                           name: ast::Name,
-                           span: Span,
-                           typ: &'l ast::Ty,
-                           expr: Option<&'l ast::Expr>,
-                           parent_id: DefId,
-                           vis: ast::Visibility,
-                           attrs: &'l [Attribute]) {
+    fn process_assoc_const(
+        &mut self,
+        id: ast::NodeId,
+        name: ast::Name,
+        span: Span,
+        typ: &'l ast::Ty,
+        expr: Option<&'l ast::Expr>,
+        parent_id: DefId,
+        vis: ast::Visibility,
+        attrs: &'l [Attribute],
+    ) {
         let qualname = format!("::{}", self.tcx.node_path_str(id));
 
         let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
@@ -493,20 +519,23 @@ fn process_assoc_const(&mut self,
             let id = ::id_from_node_id(id, &self.save_ctxt);
             let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
-            self.dumper.dump_def(vis == ast::Visibility::Public, Def {
-                kind: DefKind::Const,
-                id,
-                span,
-                name: name.to_string(),
-                qualname,
-                value: ty_to_string(&typ),
-                parent: Some(::id_from_def_id(parent_id)),
-                children: vec![],
-                decl_id: None,
-                docs: self.save_ctxt.docs_for_attrs(attrs),
-                sig,
-                attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
-            });
+            self.dumper.dump_def(
+                vis == ast::Visibility::Public,
+                Def {
+                    kind: DefKind::Const,
+                    id,
+                    span,
+                    name: name.to_string(),
+                    qualname,
+                    value: ty_to_string(&typ),
+                    parent: Some(::id_from_def_id(parent_id)),
+                    children: vec![],
+                    decl_id: None,
+                    docs: self.save_ctxt.docs_for_attrs(attrs),
+                    sig,
+                    attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
+                },
+            );
         }
 
         // walk type and init value
@@ -517,10 +546,12 @@ fn process_assoc_const(&mut self,
     }
 
     // FIXME tuple structs should generate tuple-specific data.
-    fn process_struct(&mut self,
-                      item: &'l ast::Item,
-                      def: &'l ast::VariantData,
-                      ty_params: &'l ast::Generics) {
+    fn process_struct(
+        &mut self,
+        item: &'l ast::Item,
+        def: &'l ast::VariantData,
+        ty_params: &'l ast::Generics,
+    ) {
         debug!("process_struct {:?} {:?}", item, item.span);
         let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
@@ -540,36 +571,47 @@ fn process_struct(&mut self,
                     .iter()
                     .enumerate()
                     .filter_map(|(i, f)| {
-                         if include_priv_fields || f.vis == ast::Visibility::Public {
-                             f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
-                         } else {
-                             None
-                         }
+                        if include_priv_fields || f.vis == ast::Visibility::Public {
+                            f.ident
+                                .map(|i| i.to_string())
+                                .or_else(|| Some(i.to_string()))
+                        } else {
+                            None
+                        }
                     })
                     .collect::<Vec<_>>()
                     .join(", ");
                 let value = format!("{} {{ {} }}", name, fields_str);
-                (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
+                (
+                    value,
+                    fields
+                        .iter()
+                        .map(|f| ::id_from_node_id(f.id, &self.save_ctxt))
+                        .collect(),
+                )
             }
-            _ => (String::new(), vec![])
+            _ => (String::new(), vec![]),
         };
 
         if !self.span.filter_generated(sub_span, item.span) {
             let span = self.span_from_span(sub_span.expect("No span found for struct"));
-            self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                kind,
-                id: ::id_from_node_id(item.id, &self.save_ctxt),
-                span,
-                name,
-                qualname: qualname.clone(),
-                value,
-                parent: None,
-                children: fields,
-                decl_id: None,
-                docs: self.save_ctxt.docs_for_attrs(&item.attrs),
-                sig: sig::item_signature(item, &self.save_ctxt),
-                attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
-            });
+            self.dumper.dump_def(
+                item.vis == ast::Visibility::Public,
+                Def {
+                    kind,
+                    id: ::id_from_node_id(item.id, &self.save_ctxt),
+                    span,
+                    name,
+                    qualname: qualname.clone(),
+                    value,
+                    parent: None,
+                    children: fields,
+                    decl_id: None,
+                    docs: self.save_ctxt.docs_for_attrs(&item.attrs),
+                    sig: sig::item_signature(item, &self.save_ctxt),
+                    attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                },
+            );
         }
 
         for field in def.fields() {
@@ -580,10 +622,12 @@ fn process_struct(&mut self,
         self.process_generic_params(ty_params, item.span, &qualname, item.id);
     }
 
-    fn process_enum(&mut self,
-                    item: &'l ast::Item,
-                    enum_definition: &'l ast::EnumDef,
-                    ty_params: &'l ast::Generics) {
+    fn process_enum(
+        &mut self,
+        item: &'l ast::Item,
+        enum_definition: &'l ast::EnumDef,
+        ty_params: &'l ast::Generics,
+    ) {
         let enum_data = self.save_ctxt.get_item_data(item);
         let enum_data = match enum_data {
             None => return,
@@ -600,34 +644,41 @@ fn process_enum(&mut self,
             match variant.node.data {
                 ast::VariantData::Struct(ref fields, _) => {
                     let sub_span = self.span.span_for_first_ident(variant.span);
-                    let fields_str = fields.iter()
-                                           .enumerate()
-                                           .map(|(i, f)| f.ident.map(|i| i.to_string())
-                                                          .unwrap_or(i.to_string()))
-                                           .collect::<Vec<_>>()
-                                           .join(", ");
+                    let fields_str = fields
+                        .iter()
+                        .enumerate()
+                        .map(|(i, f)| {
+                            f.ident.map(|i| i.to_string()).unwrap_or(i.to_string())
+                        })
+                        .collect::<Vec<_>>()
+                        .join(", ");
                     let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                     if !self.span.filter_generated(sub_span, variant.span) {
-                        let span = self.span_from_span(
-                            sub_span.expect("No span found for struct variant"));
+                        let span = self
+                            .span_from_span(sub_span.expect("No span found for struct variant"));
                         let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
                         let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
 
-                        self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                            kind: DefKind::StructVariant,
-                            id,
-                            span,
-                            name,
-                            qualname,
-                            value,
-                            parent,
-                            children: vec![],
-                            decl_id: None,
-                            docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
-                            sig: sig::variant_signature(variant, &self.save_ctxt),
-                            attributes: lower_attributes(variant.node.attrs.clone(),
-                                                         &self.save_ctxt),
-                        });
+                        self.dumper.dump_def(
+                            item.vis == ast::Visibility::Public,
+                            Def {
+                                kind: DefKind::StructVariant,
+                                id,
+                                span,
+                                name,
+                                qualname,
+                                value,
+                                parent,
+                                children: vec![],
+                                decl_id: None,
+                                docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
+                                sig: sig::variant_signature(variant, &self.save_ctxt),
+                                attributes: lower_attributes(
+                                    variant.node.attrs.clone(),
+                                    &self.save_ctxt,
+                                ),
+                            },
+                        );
                     }
                 }
                 ref v => {
@@ -635,10 +686,11 @@ fn process_enum(&mut self,
                     let mut value = format!("{}::{}", enum_data.name, name);
                     if let &ast::VariantData::Tuple(ref fields, _) = v {
                         value.push('(');
-                        value.push_str(&fields.iter()
-                                              .map(|f| ty_to_string(&f.ty))
-                                              .collect::<Vec<_>>()
-                                              .join(", "));
+                        value.push_str(&fields
+                            .iter()
+                            .map(|f| ty_to_string(&f.ty))
+                            .collect::<Vec<_>>()
+                            .join(", "));
                         value.push(')');
                     }
                     if !self.span.filter_generated(sub_span, variant.span) {
@@ -647,21 +699,26 @@ fn process_enum(&mut self,
                         let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
                         let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
 
-                        self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                            kind: DefKind::TupleVariant,
-                            id,
-                            span,
-                            name,
-                            qualname,
-                            value,
-                            parent,
-                            children: vec![],
-                            decl_id: None,
-                            docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
-                            sig: sig::variant_signature(variant, &self.save_ctxt),
-                            attributes: lower_attributes(variant.node.attrs.clone(),
-                                                         &self.save_ctxt),
-                        });
+                        self.dumper.dump_def(
+                            item.vis == ast::Visibility::Public,
+                            Def {
+                                kind: DefKind::TupleVariant,
+                                id,
+                                span,
+                                name,
+                                qualname,
+                                value,
+                                parent,
+                                children: vec![],
+                                decl_id: None,
+                                docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
+                                sig: sig::variant_signature(variant, &self.save_ctxt),
+                                attributes: lower_attributes(
+                                    variant.node.attrs.clone(),
+                                    &self.save_ctxt,
+                                ),
+                            },
+                        );
                     }
                 }
             }
@@ -673,15 +730,18 @@ fn process_enum(&mut self,
             }
         }
         self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
-        self.dumper.dump_def(item.vis == ast::Visibility::Public, enum_data);
+        self.dumper
+            .dump_def(item.vis == ast::Visibility::Public, enum_data);
     }
 
-    fn process_impl(&mut self,
-                    item: &'l ast::Item,
-                    type_parameters: &'l ast::Generics,
-                    trait_ref: &'l Option<ast::TraitRef>,
-                    typ: &'l ast::Ty,
-                    impl_items: &'l [ast::ImplItem]) {
+    fn process_impl(
+        &mut self,
+        item: &'l ast::Item,
+        type_parameters: &'l ast::Generics,
+        trait_ref: &'l Option<ast::TraitRef>,
+        typ: &'l ast::Ty,
+        impl_items: &'l [ast::ImplItem],
+    ) {
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
             down_cast_data!(impl_data, RelationData, item.span);
             self.dumper.dump_relation(impl_data);
@@ -697,11 +757,13 @@ fn process_impl(&mut self,
         }
     }
 
-    fn process_trait(&mut self,
-                     item: &'l ast::Item,
-                     generics: &'l ast::Generics,
-                     trait_refs: &'l ast::TyParamBounds,
-                     methods: &'l [ast::TraitItem]) {
+    fn process_trait(
+        &mut self,
+        item: &'l ast::Item,
+        generics: &'l ast::Generics,
+        trait_refs: &'l ast::TyParamBounds,
+        methods: &'l [ast::TraitItem],
+    ) {
         let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
         let mut val = name.clone();
@@ -716,30 +778,33 @@ fn process_trait(&mut self,
         if !self.span.filter_generated(sub_span, item.span) {
             let id = ::id_from_node_id(item.id, &self.save_ctxt);
             let span = self.span_from_span(sub_span.expect("No span found for trait"));
-            let children =
-                methods.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect();
-            self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                kind: DefKind::Trait,
-                id,
-                span,
-                name,
-                qualname: qualname.clone(),
-                value: val,
-                parent: None,
-                children,
-                decl_id: None,
-                docs: self.save_ctxt.docs_for_attrs(&item.attrs),
-                sig: sig::item_signature(item, &self.save_ctxt),
-                attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
-            });
+            let children = methods
+                .iter()
+                .map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
+                .collect();
+            self.dumper.dump_def(
+                item.vis == ast::Visibility::Public,
+                Def {
+                    kind: DefKind::Trait,
+                    id,
+                    span,
+                    name,
+                    qualname: qualname.clone(),
+                    value: val,
+                    parent: None,
+                    children,
+                    decl_id: None,
+                    docs: self.save_ctxt.docs_for_attrs(&item.attrs),
+                    sig: sig::item_signature(item, &self.save_ctxt),
+                    attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                },
+            );
         }
 
         // super-traits
         for super_bound in trait_refs.iter() {
             let trait_ref = match *super_bound {
-                ast::TraitTyParamBound(ref trait_ref, _) => {
-                    trait_ref
-                }
+                ast::TraitTyParamBound(ref trait_ref, _) => trait_ref,
                 ast::RegionTyParamBound(..) => {
                     continue;
                 }
@@ -781,35 +846,32 @@ fn process_trait(&mut self,
     fn process_mod(&mut self, item: &ast::Item) {
         if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
             down_cast_data!(mod_data, DefData, item.span);
-            self.dumper.dump_def(item.vis == ast::Visibility::Public, mod_data);
+            self.dumper
+                .dump_def(item.vis == ast::Visibility::Public, mod_data);
+        }
+    }
+
+    fn dump_path_ref(&mut self, id: NodeId, path: &ast::Path) {
+        let path_data = self.save_ctxt.get_path_data(id, path);
+        if let Some(path_data) = path_data {
+            self.dumper.dump_ref(path_data);
         }
     }
 
     fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
         debug!("process_path {:?}", path);
-        let path_data = self.save_ctxt.get_path_data(id, path);
-        if generated_code(path.span) && path_data.is_none() {
+        if generated_code(path.span) {
             return;
         }
-
-        let path_data = match path_data {
-            Some(pd) => pd,
-            None => {
-                return;
-            }
-        };
-
-        self.dumper.dump_ref(path_data);
+        self.dump_path_ref(id, path);
 
         // Type parameters
         for seg in &path.segments {
             if let Some(ref params) = seg.parameters {
                 match **params {
-                    ast::PathParameters::AngleBracketed(ref data) => {
-                        for t in &data.types {
-                            self.visit_ty(t);
-                        }
-                    }
+                    ast::PathParameters::AngleBracketed(ref data) => for t in &data.types {
+                        self.visit_ty(t);
+                    },
                     ast::PathParameters::Parenthesized(ref data) => {
                         for t in &data.inputs {
                             self.visit_ty(t);
@@ -847,12 +909,14 @@ fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
         }
     }
 
-    fn process_struct_lit(&mut self,
-                          ex: &'l ast::Expr,
-                          path: &'l ast::Path,
-                          fields: &'l [ast::Field],
-                          variant: &'l ty::VariantDef,
-                          base: &'l Option<P<ast::Expr>>) {
+    fn process_struct_lit(
+        &mut self,
+        ex: &'l ast::Expr,
+        path: &'l ast::Path,
+        fields: &'l [ast::Field],
+        variant: &'l ty::VariantDef,
+        base: &'l Option<P<ast::Expr>>,
+    ) {
         self.write_sub_paths_truncated(path);
 
         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
@@ -862,8 +926,7 @@ fn process_struct_lit(&mut self,
             }
 
             for field in fields {
-                if let Some(field_data) = self.save_ctxt
-                                              .get_field_ref_data(field, variant) {
+                if let Some(field_data) = self.save_ctxt.get_field_ref_data(field, variant) {
                     self.dumper.dump_ref(field_data);
                 }
 
@@ -874,10 +937,12 @@ fn process_struct_lit(&mut self,
         walk_list!(self, visit_expr, base);
     }
 
-    fn process_method_call(&mut self,
-                           ex: &'l ast::Expr,
-                           seg: &'l ast::PathSegment,
-                           args: &'l [P<ast::Expr>]) {
+    fn process_method_call(
+        &mut self,
+        ex: &'l ast::Expr,
+        seg: &'l ast::PathSegment,
+        args: &'l [P<ast::Expr>],
+    ) {
         debug!("process_method_call {:?} {:?}", ex, ex.span);
         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
             down_cast_data!(mcd, RefData, ex.span);
@@ -913,7 +978,11 @@ fn process_pat(&mut self, p: &'l ast::Pat) {
                 };
                 let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id));
 
-                for &Spanned { node: ref field, span } in fields {
+                for &Spanned {
+                    node: ref field,
+                    span,
+                } in fields
+                {
                     let sub_span = self.span.span_for_first_ident(span);
                     if let Some(f) = variant.find_field_named(field.ident.name) {
                         if !self.span.filter_generated(sub_span, span) {
@@ -968,20 +1037,23 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
                 let id = ::id_from_node_id(id, &self.save_ctxt);
                 let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
-                self.dumper.dump_def(false, Def {
-                    kind: DefKind::Local,
-                    id,
-                    span,
-                    name: i.to_string(),
-                    qualname,
-                    value: typ,
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: String::new(),
-                    sig: None,
-                    attributes:vec![],
-                });
+                self.dumper.dump_def(
+                    false,
+                    Def {
+                        kind: DefKind::Local,
+                        id,
+                        span,
+                        name: i.to_string(),
+                        qualname,
+                        value: typ,
+                        parent: None,
+                        children: vec![],
+                        decl_id: None,
+                        docs: String::new(),
+                        sig: None,
+                        attributes: vec![],
+                    },
+                );
             }
         }
     }
@@ -1032,52 +1104,62 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
         self.process_macro_use(trait_item.span);
         match trait_item.node {
             ast::TraitItemKind::Const(ref ty, ref expr) => {
-                self.process_assoc_const(trait_item.id,
-                                         trait_item.ident.name,
-                                         trait_item.span,
-                                         &ty,
-                                         expr.as_ref().map(|e| &**e),
-                                         trait_id,
-                                         ast::Visibility::Public,
-                                         &trait_item.attrs);
+                self.process_assoc_const(
+                    trait_item.id,
+                    trait_item.ident.name,
+                    trait_item.span,
+                    &ty,
+                    expr.as_ref().map(|e| &**e),
+                    trait_id,
+                    ast::Visibility::Public,
+                    &trait_item.attrs,
+                );
             }
             ast::TraitItemKind::Method(ref sig, ref body) => {
-                self.process_method(sig,
-                                    body.as_ref().map(|x| &**x),
-                                    trait_item.id,
-                                    trait_item.ident,
-                                    &trait_item.generics,
-                                    ast::Visibility::Public,
-                                    trait_item.span);
+                self.process_method(
+                    sig,
+                    body.as_ref().map(|x| &**x),
+                    trait_item.id,
+                    trait_item.ident,
+                    &trait_item.generics,
+                    ast::Visibility::Public,
+                    trait_item.span,
+                );
             }
             ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
                 let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id));
-                let sub_span = self.span.sub_span_after_keyword(trait_item.span, keywords::Type);
+                let sub_span = self.span
+                    .sub_span_after_keyword(trait_item.span, keywords::Type);
 
                 if !self.span.filter_generated(sub_span, trait_item.span) {
                     let span = self.span_from_span(sub_span.expect("No span found for assoc type"));
                     let id = ::id_from_node_id(trait_item.id, &self.save_ctxt);
 
-                    self.dumper.dump_def(true, Def {
-                        kind: DefKind::Type,
-                        id,
-                        span,
-                        name,
-                        qualname,
-                        value: self.span.snippet(trait_item.span),
-                        parent: Some(::id_from_def_id(trait_id)),
-                        children: vec![],
-                        decl_id: None,
-                        docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
-                        sig: sig::assoc_type_signature(trait_item.id,
-                                                       trait_item.ident,
-                                                       Some(bounds),
-                                                       default_ty.as_ref().map(|ty| &**ty),
-                                                       &self.save_ctxt),
-                        attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt),
-                    });
+                    self.dumper.dump_def(
+                        true,
+                        Def {
+                            kind: DefKind::Type,
+                            id,
+                            span,
+                            name,
+                            qualname,
+                            value: self.span.snippet(trait_item.span),
+                            parent: Some(::id_from_def_id(trait_id)),
+                            children: vec![],
+                            decl_id: None,
+                            docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
+                            sig: sig::assoc_type_signature(
+                                trait_item.id,
+                                trait_item.ident,
+                                Some(bounds),
+                                default_ty.as_ref().map(|ty| &**ty),
+                                &self.save_ctxt,
+                            ),
+                            attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt),
+                        },
+                    );
                 }
 
                 if let &Some(ref default_ty) = default_ty {
@@ -1092,23 +1174,27 @@ fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
         self.process_macro_use(impl_item.span);
         match impl_item.node {
             ast::ImplItemKind::Const(ref ty, ref expr) => {
-                self.process_assoc_const(impl_item.id,
-                                         impl_item.ident.name,
-                                         impl_item.span,
-                                         &ty,
-                                         Some(expr),
-                                         impl_id,
-                                         impl_item.vis.clone(),
-                                         &impl_item.attrs);
+                self.process_assoc_const(
+                    impl_item.id,
+                    impl_item.ident.name,
+                    impl_item.span,
+                    &ty,
+                    Some(expr),
+                    impl_id,
+                    impl_item.vis.clone(),
+                    &impl_item.attrs,
+                );
             }
             ast::ImplItemKind::Method(ref sig, ref body) => {
-                self.process_method(sig,
-                                    Some(body),
-                                    impl_item.id,
-                                    impl_item.ident,
-                                    &impl_item.generics,
-                                    impl_item.vis.clone(),
-                                    impl_item.span);
+                self.process_method(
+                    sig,
+                    Some(body),
+                    impl_item.id,
+                    impl_item.ident,
+                    &impl_item.generics,
+                    impl_item.vis.clone(),
+                    impl_item.span,
+                );
             }
             ast::ImplItemKind::Type(ref ty) => {
                 // FIXME uses of the assoc type should ideally point to this
@@ -1132,23 +1218,29 @@ fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], i
         let cm = self.tcx.sess.codemap();
         let filename = cm.span_to_filename(span);
         let data_id = ::id_from_node_id(id, &self.save_ctxt);
-        let children = m.items.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect();
+        let children = m.items
+            .iter()
+            .map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
+            .collect();
         let span = self.span_from_span(span);
 
-        self.dumper.dump_def(true, Def {
-            kind: DefKind::Mod,
-            id: data_id,
-            name: String::new(),
-            qualname,
-            span,
-            value: filename,
-            children,
-            parent: None,
-            decl_id: None,
-            docs: self.save_ctxt.docs_for_attrs(attrs),
-            sig: None,
-            attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
-        });
+        self.dumper.dump_def(
+            true,
+            Def {
+                kind: DefKind::Mod,
+                id: data_id,
+                name: String::new(),
+                qualname,
+                span,
+                value: filename,
+                children,
+                parent: None,
+                decl_id: None,
+                docs: self.save_ctxt.docs_for_attrs(attrs),
+                sig: None,
+                attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
+            },
+        );
         self.nest_scope(id, |v| visit::walk_mod(v, m));
     }
 
@@ -1170,8 +1262,9 @@ fn visit_item(&mut self, item: &'l ast::Item) {
 
                         // 'use' always introduces an alias, if there is not an explicit
                         // one, there is an implicit one.
-                        let sub_span = match self.span.sub_span_after_keyword(use_item.span,
-                                                                              keywords::As) {
+                        let sub_span = match self.span
+                            .sub_span_after_keyword(use_item.span, keywords::As)
+                        {
                             Some(sub_span) => Some(sub_span),
                             None => sub_span,
                         };
@@ -1179,13 +1272,16 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         if !self.span.filter_generated(sub_span, path.span) {
                             let span =
                                 self.span_from_span(sub_span.expect("No span found for use"));
-                            self.dumper.import(item.vis == ast::Visibility::Public, Import {
-                                kind: ImportKind::Use,
-                                ref_id: mod_id.map(|id| ::id_from_def_id(id)),
-                                span,
-                                name: ident.to_string(),
-                                value: String::new(),
-                            });
+                            self.dumper.import(
+                                item.vis == ast::Visibility::Public,
+                                Import {
+                                    kind: ImportKind::Use,
+                                    ref_id: mod_id.map(|id| ::id_from_def_id(id)),
+                                    span,
+                                    name: ident.to_string(),
+                                    value: String::new(),
+                                },
+                            );
                         }
                         self.write_sub_paths_truncated(path);
                     }
@@ -1201,17 +1297,20 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         }
 
                         let sub_span = self.span
-                                           .sub_span_of_token(item.span, token::BinOp(token::Star));
+                            .sub_span_of_token(item.span, token::BinOp(token::Star));
                         if !self.span.filter_generated(sub_span, item.span) {
                             let span =
                                 self.span_from_span(sub_span.expect("No span found for use glob"));
-                            self.dumper.import(item.vis == ast::Visibility::Public, Import {
-                                kind: ImportKind::GlobUse,
-                                ref_id: None,
-                                span,
-                                name: "*".to_owned(),
-                                value: names.join(", "),
-                            });
+                            self.dumper.import(
+                                item.vis == ast::Visibility::Public,
+                                Import {
+                                    kind: ImportKind::GlobUse,
+                                    ref_id: None,
+                                    span,
+                                    name: "*".to_owned(),
+                                    value: names.join(", "),
+                                },
+                            );
                         }
                         self.write_sub_paths(path);
                     }
@@ -1234,34 +1333,33 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                 if !self.span.filter_generated(alias_span, item.span) {
                     let span =
                         self.span_from_span(alias_span.expect("No span found for extern crate"));
-                    self.dumper.import(false, Import {
-                        kind: ImportKind::ExternCrate,
-                        ref_id: None,
-                        span,
-                        name: item.ident.to_string(),
-                        value: String::new(),
-                    });
+                    self.dumper.import(
+                        false,
+                        Import {
+                            kind: ImportKind::ExternCrate,
+                            ref_id: None,
+                            span,
+                            name: item.ident.to_string(),
+                            value: String::new(),
+                        },
+                    );
                 }
             }
-            Fn(ref decl, .., ref ty_params, ref body) =>
-                self.process_fn(item, &decl, ty_params, &body),
-            Static(ref typ, _, ref expr) =>
-                self.process_static_or_const_item(item, typ, expr),
-            Const(ref typ, ref expr) =>
-                self.process_static_or_const_item(item, &typ, &expr),
+            Fn(ref decl, .., ref ty_params, ref body) => {
+                self.process_fn(item, &decl, ty_params, &body)
+            }
+            Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
+            Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
             Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
                 self.process_struct(item, def, ty_params)
             }
             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            Impl(..,
-                 ref ty_params,
-                 ref trait_ref,
-                 ref typ,
-                 ref impl_items) => {
+            Impl(.., ref ty_params, ref trait_ref, ref typ, ref impl_items) => {
                 self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
             }
-            Trait(_, _, ref generics, ref trait_refs, ref methods) =>
-                self.process_trait(item, generics, trait_refs, methods),
+            Trait(_, _, ref generics, ref trait_refs, ref methods) => {
+                self.process_trait(item, generics, trait_refs, methods)
+            }
             Mod(ref m) => {
                 self.process_mod(item);
                 self.nest_scope(item.id, |v| visit::walk_mod(v, m));
@@ -1274,20 +1372,23 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                     let span = self.span_from_span(sub_span.expect("No span found for typedef"));
                     let id = ::id_from_node_id(item.id, &self.save_ctxt);
 
-                    self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                        kind: DefKind::Type,
-                        id,
-                        span,
-                        name: item.ident.to_string(),
-                        qualname: qualname.clone(),
-                        value,
-                        parent: None,
-                        children: vec![],
-                        decl_id: None,
-                        docs: self.save_ctxt.docs_for_attrs(&item.attrs),
-                        sig: sig::item_signature(item, &self.save_ctxt),
-                        attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
-                    });
+                    self.dumper.dump_def(
+                        item.vis == ast::Visibility::Public,
+                        Def {
+                            kind: DefKind::Type,
+                            id,
+                            span,
+                            name: item.ident.to_string(),
+                            qualname: qualname.clone(),
+                            value,
+                            parent: None,
+                            children: vec![],
+                            decl_id: None,
+                            docs: self.save_ctxt.docs_for_attrs(&item.attrs),
+                            sig: sig::item_signature(item, &self.save_ctxt),
+                            attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                        },
+                    );
                 }
 
                 self.visit_ty(&ty);
@@ -1374,8 +1475,11 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                 let hir_node = match self.save_ctxt.tcx.hir.find(sub_ex.id) {
                     Some(Node::NodeExpr(expr)) => expr,
                     _ => {
-                        debug!("Missing or weird node for sub-expression {} in {:?}",
-                               sub_ex.id, ex);
+                        debug!(
+                            "Missing or weird node for sub-expression {} in {:?}",
+                            sub_ex.id,
+                            ex
+                        );
                         return;
                     }
                 };
@@ -1400,9 +1504,7 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                         }
                     }
                     ty::TyTuple(..) => {}
-                    _ => span_bug!(ex.span,
-                                   "Expected struct or tuple type, found {:?}",
-                                   ty),
+                    _ => span_bug!(ex.span, "Expected struct or tuple type, found {:?}", ty),
                 }
             }
             ast::ExprKind::Closure(_, ref decl, ref body, _fn_decl_span) => {
@@ -1445,15 +1547,16 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
             }
             // In particular, we take this branch for call and path expressions,
             // where we'll index the idents involved just by continuing to walk.
-            _ => {
-                visit::walk_expr(self, ex)
-            }
+            _ => visit::walk_expr(self, ex),
         }
     }
 
     fn visit_mac(&mut self, mac: &'l ast::Mac) {
         // These shouldn't exist in the AST at this point, log a span bug.
-        span_bug!(mac.span, "macro invocation should have been expanded out of AST");
+        span_bug!(
+            mac.span,
+            "macro invocation should have been expanded out of AST"
+        );
     }
 
     fn visit_pat(&mut self, p: &'l ast::Pat) {
@@ -1480,10 +1583,10 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                     };
                     let hir_id = self.tcx.hir.node_to_hir_id(id);
                     let typ = self.save_ctxt
-                                  .tables
-                                  .node_id_to_type_opt(hir_id)
-                                  .map(|t| t.to_string())
-                                  .unwrap_or(String::new());
+                        .tables
+                        .node_id_to_type_opt(hir_id)
+                        .map(|t| t.to_string())
+                        .unwrap_or(String::new());
                     value.push_str(": ");
                     value.push_str(&typ);
 
@@ -1492,24 +1595,40 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                         let id = ::id_from_node_id(id, &self.save_ctxt);
                         let span = self.span_from_span(sp);
 
-                        self.dumper.dump_def(false, Def {
-                            kind: DefKind::Local,
-                            id,
-                            span,
-                            name: i.to_string(),
-                            qualname,
-                            value: typ,
-                            parent: None,
-                            children: vec![],
-                            decl_id: None,
-                            docs: String::new(),
-                            sig: None,
-                            attributes:vec![],
-                        });
+                        self.dumper.dump_def(
+                            false,
+                            Def {
+                                kind: DefKind::Local,
+                                id,
+                                span,
+                                name: i.to_string(),
+                                qualname,
+                                value: typ,
+                                parent: None,
+                                children: vec![],
+                                decl_id: None,
+                                docs: String::new(),
+                                sig: None,
+                                attributes: vec![],
+                            },
+                        );
                     }
                 }
-                def => error!("unexpected definition kind when processing collected idents: {:?}",
-                              def),
+                HirDef::StructCtor(..) |
+                HirDef::VariantCtor(..) |
+                HirDef::Const(..) |
+                HirDef::AssociatedConst(..) |
+                HirDef::Struct(..) |
+                HirDef::Variant(..) |
+                HirDef::TyAlias(..) |
+                HirDef::AssociatedTy(..) |
+                HirDef::SelfTy(..) => {
+                    self.dump_path_ref(id, &ast::Path::from_ident(sp, i));
+                }
+                def => error!(
+                    "unexpected definition kind when processing collected idents: {:?}",
+                    def
+                ),
             }
         }
 
@@ -1531,7 +1650,10 @@ fn visit_stmt(&mut self, s: &'l ast::Stmt) {
 
     fn visit_local(&mut self, l: &'l ast::Local) {
         self.process_macro_use(l.span);
-        let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new());
+        let value = l.init
+            .as_ref()
+            .map(|i| self.span.snippet(i.span))
+            .unwrap_or(String::new());
         self.process_var_decl(&l.pat, value);
 
         // Just walk the initialiser and type (don't want to walk the pattern again).
@@ -1545,10 +1667,13 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
                 if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(fn_data, DefData, item.span);
 
-                    self.nest_tables(item.id, |v| v.process_formals(&decl.inputs,
-                                                                    &fn_data.qualname));
+                    self.nest_tables(
+                        item.id,
+                        |v| v.process_formals(&decl.inputs, &fn_data.qualname),
+                    );
                     self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
-                    self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data);
+                    self.dumper
+                        .dump_def(item.vis == ast::Visibility::Public, fn_data);
                 }
 
                 for arg in &decl.inputs {
@@ -1562,7 +1687,8 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
             ast::ForeignItemKind::Static(ref ty, _) => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
-                    self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data);
+                    self.dumper
+                        .dump_def(item.vis == ast::Visibility::Public, var_data);
                 }
 
                 self.visit_ty(ty);
@@ -1570,7 +1696,8 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
             ast::ForeignItemKind::Ty => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
-                    self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data);
+                    self.dumper
+                        .dump_def(item.vis == ast::Visibility::Public, var_data);
                 }
             }
         }
index 8dd191f4375ed1b81c0ac4883c5c6562dd044cee..14b624b9338f6937775bad07dd425e11a4021bcc 100644 (file)
@@ -12,8 +12,8 @@
 
 use rustc_serialize::json::as_json;
 
-use rls_data::{self, Analysis, Import, Def, DefKind, Ref, RefKind, MacroRef,
-               Relation, CratePreludeData};
+use rls_data::{self, Analysis, CratePreludeData, Def, DefKind, Import, MacroRef, Ref, RefKind,
+               Relation};
 use rls_data::config::Config;
 use rls_span::{Column, Row};
 
@@ -54,15 +54,16 @@ pub fn new(writer: &'b mut W, config: Config) -> JsonDumper<WriteOutput<'b, W>>
         JsonDumper {
             output: WriteOutput { output: writer },
             config: config.clone(),
-            result: Analysis::new(config)
+            result: Analysis::new(config),
         }
     }
 }
 
 impl<'b> JsonDumper<CallbackOutput<'b>> {
-    pub fn with_callback(callback: &'b mut FnMut(&Analysis),
-                         config: Config)
-                         -> JsonDumper<CallbackOutput<'b>> {
+    pub fn with_callback(
+        callback: &'b mut FnMut(&Analysis),
+        config: Config,
+    ) -> JsonDumper<CallbackOutput<'b>> {
         JsonDumper {
             output: CallbackOutput { callback: callback },
             config: config.clone(),
index edb51ae59e1b56c8b431893212f0e0fd87aa9693..fddafed11f3146f8ef40b4d429c1fe227baf0a99 100644 (file)
@@ -9,20 +9,22 @@
 // except according to those terms.
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
-
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 
-#[macro_use] extern crate rustc;
+#[macro_use]
+extern crate rustc;
 
-#[macro_use] extern crate log;
-#[macro_use] extern crate syntax;
+#[macro_use]
+extern crate log;
 extern crate rustc_data_structures;
 extern crate rustc_serialize;
 extern crate rustc_typeck;
+#[macro_use]
+extern crate syntax;
 extern crate syntax_pos;
 
 extern crate rls_data;
@@ -38,7 +40,7 @@
 use rustc::hir;
 use rustc::hir::def::Def as HirDef;
 use rustc::hir::map::{Node, NodeItem};
-use rustc::hir::def_id::{LOCAL_CRATE, DefId};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::session::config::CrateType::CrateTypeExecutable;
 use rustc::ty::{self, TyCtxt};
 use rustc_typeck::hir_ty_to_ty;
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
-use syntax::ast::{self, NodeId, PatKind, Attribute};
+use syntax::ast::{self, Attribute, NodeId, PatKind};
 use syntax::parse::lexer::comments::strip_doc_comment_decoration;
 use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
-use syntax::print::pprust::{ty_to_string, arg_to_string};
+use syntax::print::pprust::{arg_to_string, ty_to_string};
 use syntax::codemap::MacroAttribute;
 use syntax_pos::*;
 
@@ -62,8 +64,8 @@
 use dump_visitor::DumpVisitor;
 use span_utils::SpanUtils;
 
-use rls_data::{Ref, RefKind, SpanData, MacroRef, Def, DefKind, Relation, RelationKind,
-               ExternalCrateData, GlobalCrateId};
+use rls_data::{Def, DefKind, ExternalCrateData, GlobalCrateId, MacroRef, Ref, RefKind, Relation,
+               RelationKind, SpanData};
 use rls_data::config::Config;
 
 
@@ -84,7 +86,7 @@ pub enum Data {
 
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     fn span_from_span(&self, span: Span) -> SpanData {
-        use rls_span::{Row, Column};
+        use rls_span::{Column, Row};
 
         let cm = self.tcx.sess.codemap();
         let start = cm.lookup_char_pos(span.lo());
@@ -119,8 +121,7 @@ pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
                 num: n.as_u32(),
                 id: GlobalCrateId {
                     name: self.tcx.crate_name(n).to_string(),
-                    disambiguator: self.tcx.crate_disambiguator(n)
-                                       .to_fingerprint().as_value(),
+                    disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(),
                 },
             });
         }
@@ -132,7 +133,8 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
         match item.node {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
+                let sub_span = self.span_utils
+                    .sub_span_after_keyword(item.span, keywords::Fn);
                 filter!(self.span_utils, sub_span, item.span, None);
 
                 Some(Data::DefData(Def {
@@ -182,7 +184,8 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         match item.node {
             ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
+                let sub_span = self.span_utils
+                    .sub_span_after_keyword(item.span, keywords::Fn);
                 filter!(self.span_utils, sub_span, item.span, None);
                 Some(Data::DefData(Def {
                     kind: DefKind::Function,
@@ -230,7 +233,8 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
             }
             ast::ItemKind::Const(ref typ, _) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const);
+                let sub_span = self.span_utils
+                    .sub_span_after_keyword(item.span, keywords::Const);
                 filter!(self.span_utils, sub_span, item.span, None);
 
                 let id = id_from_node_id(item.id, self);
@@ -257,7 +261,8 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                 let cm = self.tcx.sess.codemap();
                 let filename = cm.span_to_filename(m.inner);
 
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod);
+                let sub_span = self.span_utils
+                    .sub_span_after_keyword(item.span, keywords::Mod);
                 filter!(self.span_utils, sub_span, item.span, None);
 
                 Some(Data::DefData(Def {
@@ -268,7 +273,10 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     span: self.span_from_span(sub_span.unwrap()),
                     value: filename,
                     parent: None,
-                    children: m.items.iter().map(|i| id_from_node_id(i.id, self)).collect(),
+                    children: m.items
+                        .iter()
+                        .map(|i| id_from_node_id(i.id, self))
+                        .collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
@@ -278,12 +286,14 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
             ast::ItemKind::Enum(ref def, _) => {
                 let name = item.ident.to_string();
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Enum);
+                let sub_span = self.span_utils
+                    .sub_span_after_keyword(item.span, keywords::Enum);
                 filter!(self.span_utils, sub_span, item.span, None);
-                let variants_str = def.variants.iter()
-                                      .map(|v| v.node.name.to_string())
-                                      .collect::<Vec<_>>()
-                                      .join(", ");
+                let variants_str = def.variants
+                    .iter()
+                    .map(|v| v.node.name.to_string())
+                    .collect::<Vec<_>>()
+                    .join(", ");
                 let value = format!("{}::{{{}}}", name, variants_str);
                 Some(Data::DefData(Def {
                     kind: DefKind::Enum,
@@ -294,9 +304,9 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     value,
                     parent: None,
                     children: def.variants
-                                 .iter()
-                                 .map(|v| id_from_node_id(v.node.data.id(), self))
-                                 .collect(),
+                        .iter()
+                        .map(|v| id_from_node_id(v.node.data.id(), self))
+                        .collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
@@ -313,15 +323,18 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     filter!(self.span_utils, sub_span, typ.span, None);
 
                     let type_data = self.lookup_ref_id(typ.id);
-                    type_data.map(|type_data| Data::RelationData(Relation {
-                        kind: RelationKind::Impl,
-                        span: self.span_from_span(sub_span.unwrap()),
-                        from: id_from_def_id(type_data),
-                        to: trait_ref.as_ref()
-                                     .and_then(|t| self.lookup_ref_id(t.ref_id))
-                                     .map(id_from_def_id)
-                                     .unwrap_or(null_id()),
-                    }))
+                    type_data.map(|type_data| {
+                        Data::RelationData(Relation {
+                            kind: RelationKind::Impl,
+                            span: self.span_from_span(sub_span.unwrap()),
+                            from: id_from_def_id(type_data),
+                            to: trait_ref
+                                .as_ref()
+                                .and_then(|t| self.lookup_ref_id(t.ref_id))
+                                .map(id_from_def_id)
+                                .unwrap_or(null_id()),
+                        })
+                    })
                 } else {
                     None
                 }
@@ -333,14 +346,12 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         }
     }
 
-    pub fn get_field_data(&self,
-                          field: &ast::StructField,
-                          scope: NodeId)
-                          -> Option<Def> {
+    pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<Def> {
         if let Some(ident) = field.ident {
             let name = ident.to_string();
             let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
-            let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
+            let sub_span = self.span_utils
+                .sub_span_before_token(field.span, token::Colon);
             filter!(self.span_utils, sub_span, field.span, None);
             let def_id = self.tcx.hir.local_def_id(field.id);
             let typ = self.tcx.type_of(def_id).to_string();
@@ -370,18 +381,13 @@ pub fn get_field_data(&self,
 
     // FIXME would be nice to take a MethodItem here, but the ast provides both
     // trait and impl flavours, so the caller must do the disassembly.
-    pub fn get_method_data(&self,
-                           id: ast::NodeId,
-                           name: ast::Name,
-                           span: Span)
-                           -> Option<Def> {
+    pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> Option<Def> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
         let (qualname, parent_scope, decl_id, docs, attributes) =
-          match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) {
-            Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
-                Some(Node::NodeItem(item)) => {
-                    match item.node {
+            match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) {
+                Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
+                    Some(Node::NodeItem(item)) => match item.node {
                         hir::ItemImpl(.., ref ty, _) => {
                             let mut result = String::from("<");
                             result.push_str(&self.tcx.hir.node_to_pretty_string(ty.id));
@@ -391,7 +397,8 @@ pub fn get_method_data(&self,
                             if let Some(def_id) = trait_id {
                                 result.push_str(" as ");
                                 result.push_str(&self.tcx.item_path_str(def_id));
-                                self.tcx.associated_items(def_id)
+                                self.tcx
+                                    .associated_items(def_id)
                                     .find(|item| item.name == name)
                                     .map(|item| decl_id = Some(item.def_id));
                             } else {
@@ -403,53 +410,61 @@ pub fn get_method_data(&self,
                             }
                             result.push_str(">");
 
-                            (result, trait_id, decl_id,
-                             self.docs_for_attrs(&item.attrs),
-                             item.attrs.to_vec())
+                            (
+                                result,
+                                trait_id,
+                                decl_id,
+                                self.docs_for_attrs(&item.attrs),
+                                item.attrs.to_vec(),
+                            )
                         }
                         _ => {
-                            span_bug!(span,
-                                      "Container {:?} for method {} not an impl?",
-                                      impl_id,
-                                      id);
+                            span_bug!(
+                                span,
+                                "Container {:?} for method {} not an impl?",
+                                impl_id,
+                                id
+                            );
                         }
+                    },
+                    r => {
+                        span_bug!(
+                            span,
+                            "Container {:?} for method {} is not a node item {:?}",
+                            impl_id,
+                            id,
+                            r
+                        );
                     }
-                }
-                r => {
-                    span_bug!(span,
-                              "Container {:?} for method {} is not a node item {:?}",
-                              impl_id,
-                              id,
-                              r);
-                }
-            },
-            None => match self.tcx.trait_of_item(self.tcx.hir.local_def_id(id)) {
-                Some(def_id) => {
-                    match self.tcx.hir.get_if_local(def_id) {
-                        Some(Node::NodeItem(item)) => {
-                            (format!("::{}", self.tcx.item_path_str(def_id)),
-                             Some(def_id), None,
-                             self.docs_for_attrs(&item.attrs),
-                             item.attrs.to_vec())
-                        }
+                },
+                None => match self.tcx.trait_of_item(self.tcx.hir.local_def_id(id)) {
+                    Some(def_id) => match self.tcx.hir.get_if_local(def_id) {
+                        Some(Node::NodeItem(item)) => (
+                            format!("::{}", self.tcx.item_path_str(def_id)),
+                            Some(def_id),
+                            None,
+                            self.docs_for_attrs(&item.attrs),
+                            item.attrs.to_vec(),
+                        ),
                         r => {
-                            span_bug!(span,
-                                      "Could not find container {:?} for \
-                                       method {}, got {:?}",
-                                      def_id,
-                                      id,
-                                      r);
+                            span_bug!(
+                                span,
+                                "Could not find container {:?} for \
+                                 method {}, got {:?}",
+                                def_id,
+                                id,
+                                r
+                            );
                         }
+                    },
+                    None => {
+                        debug!("Could not find container for method {} at {:?}", id, span);
+                        // This is not necessarily a bug, if there was a compilation error,
+                        // the tables we need might not exist.
+                        return None;
                     }
-                }
-                None => {
-                    debug!("Could not find container for method {} at {:?}", id, span);
-                    // This is not necessarily a bug, if there was a compilation error, the tables
-                    // we need might not exist.
-                    return None;
-                }
-            },
-        };
+                },
+            };
 
         let qualname = format!("{}::{}", qualname, name);
 
@@ -473,9 +488,7 @@ pub fn get_method_data(&self,
         })
     }
 
-    pub fn get_trait_ref_data(&self,
-                              trait_ref: &ast::TraitRef)
-                              -> Option<Ref> {
+    pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
         self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
             let span = trait_ref.path.span;
             if generated_code(span) {
@@ -503,8 +516,11 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                 let hir_node = match self.tcx.hir.find(sub_ex.id) {
                     Some(Node::NodeExpr(expr)) => expr,
                     _ => {
-                        debug!("Missing or weird node for sub-expression {} in {:?}",
-                               sub_ex.id, expr);
+                        debug!(
+                            "Missing or weird node for sub-expression {} in {:?}",
+                            sub_ex.id,
+                            expr
+                        );
                         return None;
                     }
                 };
@@ -548,7 +564,13 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
             }
             ast::ExprKind::MethodCall(ref seg, ..) => {
                 let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id);
-                let method_id = self.tables.type_dependent_defs()[expr_hir_id].def_id();
+                let method_id = match self.tables.type_dependent_defs().get(expr_hir_id) {
+                    Some(id) => id.def_id(),
+                    None => {
+                        debug!("Could not resolve method id for {:?}", expr);
+                        return None;
+                    }
+                };
                 let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
                     ty::ImplContainer(_) => (Some(method_id), None),
                     ty::TraitContainer(_) => (None, Some(method_id)),
@@ -559,7 +581,10 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                 Some(Data::RefData(Ref {
                     kind: RefKind::Function,
                     span,
-                    ref_id: def_id.or(decl_id).map(|id| id_from_def_id(id)).unwrap_or(null_id()),
+                    ref_id: def_id
+                        .or(decl_id)
+                        .map(|id| id_from_def_id(id))
+                        .unwrap_or(null_id()),
                 }))
             }
             ast::ExprKind::Path(_, ref path) => {
@@ -576,40 +601,61 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
         match self.tcx.hir.get(id) {
             Node::NodeTraitRef(tr) => tr.path.def,
 
-            Node::NodeItem(&hir::Item { node: hir::ItemUse(ref path, _), .. }) |
+            Node::NodeItem(&hir::Item {
+                node: hir::ItemUse(ref path, _),
+                ..
+            }) |
             Node::NodeVisibility(&hir::Visibility::Restricted { ref path, .. }) => path.def,
 
-            Node::NodeExpr(&hir::Expr { node: hir::ExprStruct(ref qpath, ..), .. }) |
-            Node::NodeExpr(&hir::Expr { node: hir::ExprPath(ref qpath), .. }) |
-            Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) |
-            Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) |
-            Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => {
+            Node::NodeExpr(&hir::Expr {
+                node: hir::ExprStruct(ref qpath, ..),
+                ..
+            }) |
+            Node::NodeExpr(&hir::Expr {
+                node: hir::ExprPath(ref qpath),
+                ..
+            }) |
+            Node::NodePat(&hir::Pat {
+                node: hir::PatKind::Path(ref qpath),
+                ..
+            }) |
+            Node::NodePat(&hir::Pat {
+                node: hir::PatKind::Struct(ref qpath, ..),
+                ..
+            }) |
+            Node::NodePat(&hir::Pat {
+                node: hir::PatKind::TupleStruct(ref qpath, ..),
+                ..
+            }) => {
                 let hir_id = self.tcx.hir.node_to_hir_id(id);
                 self.tables.qpath_def(qpath, hir_id)
             }
 
             Node::NodeBinding(&hir::Pat {
-                node: hir::PatKind::Binding(_, canonical_id, ..), ..
+                node: hir::PatKind::Binding(_, canonical_id, ..),
+                ..
             }) => HirDef::Local(canonical_id),
 
-            Node::NodeTy(ty) => {
-                if let hir::Ty { node: hir::TyPath(ref qpath), .. } = *ty {
-                    match *qpath {
-                        hir::QPath::Resolved(_, ref path) => path.def,
-                        hir::QPath::TypeRelative(..) => {
-                            let ty = hir_ty_to_ty(self.tcx, ty);
-                            if let ty::TyProjection(proj) = ty.sty {
-                                return HirDef::AssociatedTy(proj.item_def_id);
-                            }
-                            HirDef::Err
+            Node::NodeTy(ty) => if let hir::Ty {
+                node: hir::TyPath(ref qpath),
+                ..
+            } = *ty
+            {
+                match *qpath {
+                    hir::QPath::Resolved(_, ref path) => path.def,
+                    hir::QPath::TypeRelative(..) => {
+                        let ty = hir_ty_to_ty(self.tcx, ty);
+                        if let ty::TyProjection(proj) = ty.sty {
+                            return HirDef::AssociatedTy(proj.item_def_id);
                         }
+                        HirDef::Err
                     }
-                } else {
-                    HirDef::Err
                 }
-            }
+            } else {
+                HirDef::Err
+            },
 
-            _ => HirDef::Err
+            _ => HirDef::Err,
         }
     }
 
@@ -636,8 +682,7 @@ fn fn_type(path: &ast::Path) -> bool {
         let sub_span = last_seg.span;
         filter!(self.span_utils, Some(sub_span), path.span, None);
         match def {
-            HirDef::Upvar(id, ..) |
-            HirDef::Local(id) => {
+            HirDef::Upvar(id, ..) | HirDef::Local(id) => {
                 let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Variable,
@@ -660,10 +705,12 @@ fn fn_type(path: &ast::Path) -> bool {
                 // Function type bounds are desugared in the parser, so we have to
                 // special case them here.
                 let fn_span = self.span_utils.span_for_first_ident(path.span);
-                fn_span.map(|span| Ref {
-                    kind: RefKind::Type,
-                    span: self.span_from_span(span),
-                    ref_id: id_from_def_id(def_id),
+                fn_span.map(|span| {
+                    Ref {
+                        kind: RefKind::Type,
+                        span: self.span_from_span(span),
+                        ref_id: id_from_def_id(def_id),
+                    }
                 })
             }
             HirDef::Struct(def_id) |
@@ -697,7 +744,8 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::Method(decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
-                    self.tcx.associated_items(ti.container.id())
+                    self.tcx
+                        .associated_items(ti.container.id())
                         .find(|item| item.name == ti.name && item.defaultness.has_value())
                         .map(|item| item.def_id)
                 } else {
@@ -735,10 +783,11 @@ fn fn_type(path: &ast::Path) -> bool {
         }
     }
 
-    pub fn get_field_ref_data(&self,
-                              field_ref: &ast::Field,
-                              variant: &ty::VariantDef)
-                              -> Option<Ref> {
+    pub fn get_field_ref_data(
+        &self,
+        field_ref: &ast::Field,
+        variant: &ty::VariantDef,
+    ) -> Option<Ref> {
         let f = variant.field_named(field_ref.ident.node.name);
         // We don't really need a sub-span here, but no harm done
         let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
@@ -776,7 +825,12 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
         // If the callee is an imported macro from an external crate, need to get
         // the source span and name from the session, as their spans are localized
         // when read in, and no longer correspond to the source.
-        if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee_span) {
+        if let Some(mac) = self.tcx
+            .sess
+            .imported_macro_spans
+            .borrow()
+            .get(&callee_span)
+        {
             let &(ref mac_name, mac_span) = mac;
             let mac_span = self.span_from_span(mac_span);
             return Some(MacroRef {
@@ -831,21 +885,29 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
     let mut sig = "fn ".to_owned();
     if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
         sig.push('<');
-        sig.push_str(&generics.lifetimes.iter()
-                              .map(|l| l.lifetime.ident.name.to_string())
-                              .collect::<Vec<_>>()
-                              .join(", "));
+        sig.push_str(&generics
+            .lifetimes
+            .iter()
+            .map(|l| l.lifetime.ident.name.to_string())
+            .collect::<Vec<_>>()
+            .join(", "));
         if !generics.lifetimes.is_empty() {
             sig.push_str(", ");
         }
-        sig.push_str(&generics.ty_params.iter()
-                              .map(|l| l.ident.to_string())
-                              .collect::<Vec<_>>()
-                              .join(", "));
+        sig.push_str(&generics
+            .ty_params
+            .iter()
+            .map(|l| l.ident.to_string())
+            .collect::<Vec<_>>()
+            .join(", "));
         sig.push_str("> ");
     }
     sig.push('(');
-    sig.push_str(&decl.inputs.iter().map(arg_to_string).collect::<Vec<_>>().join(", "));
+    sig.push_str(&decl.inputs
+        .iter()
+        .map(arg_to_string)
+        .collect::<Vec<_>>()
+        .join(", "));
     sig.push(')');
     match decl.output {
         ast::FunctionRetTy::Default(_) => sig.push_str(" -> ()"),
@@ -877,15 +939,16 @@ fn visit_pat(&mut self, p: &'a ast::Pat) {
             PatKind::Struct(ref path, ..) => {
                 self.collected_paths.push((p.id, path));
             }
-            PatKind::TupleStruct(ref path, ..) |
-            PatKind::Path(_, ref path) => {
+            PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => {
                 self.collected_paths.push((p.id, path));
             }
             PatKind::Ident(bm, ref path1, _) => {
-                debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
-                       path1.node,
-                       p.span,
-                       path1.span);
+                debug!(
+                    "PathCollector, visit ident in pat {}: {:?} {:?}",
+                    path1.node,
+                    p.span,
+                    path1.span
+                );
                 let immut = match bm {
                     // Even if the ref is mut, you can't change the ref, only
                     // the data pointed at, so showing the initialising expression
@@ -893,7 +956,8 @@ fn visit_pat(&mut self, p: &'a ast::Pat) {
                     ast::BindingMode::ByRef(_) => ast::Mutability::Immutable,
                     ast::BindingMode::ByValue(mt) => mt,
                 };
-                self.collected_idents.push((p.id, path1.node, path1.span, immut));
+                self.collected_idents
+                    .push((p.id, path1.node, path1.span, immut));
             }
             _ => {}
         }
@@ -903,23 +967,25 @@ fn visit_pat(&mut self, p: &'a ast::Pat) {
 
 /// Defines what to do with the results of saving the analysis.
 pub trait SaveHandler {
-    fn save<'l, 'tcx>(&mut self,
-                      save_ctxt: SaveContext<'l, 'tcx>,
-                      krate: &ast::Crate,
-                      cratename: &str);
+    fn save<'l, 'tcx>(
+        &mut self,
+        save_ctxt: SaveContext<'l, 'tcx>,
+        krate: &ast::Crate,
+        cratename: &str,
+    );
 }
 
 /// Dump the save-analysis results to a file.
 pub struct DumpHandler<'a> {
     odir: Option<&'a Path>,
-    cratename: String
+    cratename: String,
 }
 
 impl<'a> DumpHandler<'a> {
     pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
         DumpHandler {
             odir,
-            cratename: cratename.to_owned()
+            cratename: cratename.to_owned(),
         }
     }
 
@@ -937,8 +1003,10 @@ fn output_file(&self, ctx: &SaveContext) -> File {
                     error!("Could not create directory {}: {}", root_path.display(), e);
                 }
 
-                let executable =
-                    sess.crate_types.borrow().iter().any(|ct| *ct == CrateTypeExecutable);
+                let executable = sess.crate_types
+                    .borrow()
+                    .iter()
+                    .any(|ct| *ct == CrateTypeExecutable);
                 let mut out_name = if executable {
                     "".to_owned()
                 } else {
@@ -955,19 +1023,21 @@ fn output_file(&self, ctx: &SaveContext) -> File {
 
         info!("Writing output to {}", file_name.display());
 
-        let output_file = File::create(&file_name).unwrap_or_else(|e| {
-            sess.fatal(&format!("Could not open {}: {}", file_name.display(), e))
-        });
+        let output_file = File::create(&file_name).unwrap_or_else(
+            |e| sess.fatal(&format!("Could not open {}: {}", file_name.display(), e)),
+        );
 
         output_file
     }
 }
 
 impl<'a> SaveHandler for DumpHandler<'a> {
-    fn save<'l, 'tcx>(&mut self,
-                      save_ctxt: SaveContext<'l, 'tcx>,
-                      krate: &ast::Crate,
-                      cratename: &str) {
+    fn save<'l, 'tcx>(
+        &mut self,
+        save_ctxt: SaveContext<'l, 'tcx>,
+        krate: &ast::Crate,
+        cratename: &str,
+    ) {
         let output = &mut self.output_file(&save_ctxt);
         let mut dumper = JsonDumper::new(output, save_ctxt.config.clone());
         let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
@@ -983,10 +1053,12 @@ pub struct CallbackHandler<'b> {
 }
 
 impl<'b> SaveHandler for CallbackHandler<'b> {
-    fn save<'l, 'tcx>(&mut self,
-                      save_ctxt: SaveContext<'l, 'tcx>,
-                      krate: &ast::Crate,
-                      cratename: &str) {
+    fn save<'l, 'tcx>(
+        &mut self,
+        save_ctxt: SaveContext<'l, 'tcx>,
+        krate: &ast::Crate,
+        cratename: &str,
+    ) {
         // We're using the JsonDumper here because it has the format of the
         // save-analysis results that we will pass to the callback. IOW, we are
         // using the JsonDumper to collect the save-analysis results, but not
@@ -1000,12 +1072,14 @@ fn save<'l, 'tcx>(&mut self,
     }
 }
 
-pub fn process_crate<'l, 'tcx, H: SaveHandler>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
-                                               krate: &ast::Crate,
-                                               analysis: &'l ty::CrateAnalysis,
-                                               cratename: &str,
-                                               config: Option<Config>,
-                                               mut handler: H) {
+pub fn process_crate<'l, 'tcx, H: SaveHandler>(
+    tcx: TyCtxt<'l, 'tcx, 'tcx>,
+    krate: &ast::Crate,
+    analysis: &'l ty::CrateAnalysis,
+    cratename: &str,
+    config: Option<Config>,
+    mut handler: H,
+) {
     let _ignore = tcx.dep_graph.in_ignore();
 
     assert!(analysis.glob_map.is_some());
@@ -1028,10 +1102,8 @@ fn find_config(supplied: Option<Config>) -> Config {
         return config;
     }
     match env::var_os("RUST_SAVE_ANALYSIS_CONFIG") {
-        Some(config_string) => {
-            rustc_serialize::json::decode(config_string.to_str().unwrap())
-                .expect("Could not deserialize save-analysis config")
-        },
+        Some(config_string) => rustc_serialize::json::decode(config_string.to_str().unwrap())
+            .expect("Could not deserialize save-analysis config"),
         None => Config::default(),
     }
 }
index 80c1b0ebeb0b2d307518dd11bd0f27fbebe5477b..b244876226c484a71ea789880070da50fdcf3ec9 100644 (file)
@@ -35,9 +35,9 @@
 //
 // FIXME where clauses need implementing, defs/refs in generics are mostly missing.
 
-use {SaveContext, id_from_def_id, id_from_node_id};
+use {id_from_def_id, id_from_node_id, SaveContext};
 
-use rls_data::{Signature, SigElement};
+use rls_data::{SigElement, Signature};
 
 use rustc::hir::def::Def;
 use syntax::ast::{self, NodeId};
@@ -75,36 +75,39 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option<Si
     variant.node.make(0, None, scx).ok()
 }
 
-pub fn method_signature(id: NodeId,
-                        ident: ast::Ident,
-                        generics: &ast::Generics,
-                        m: &ast::MethodSig,
-                        scx: &SaveContext)
-                        -> Option<Signature> {
+pub fn method_signature(
+    id: NodeId,
+    ident: ast::Ident,
+    generics: &ast::Generics,
+    m: &ast::MethodSig,
+    scx: &SaveContext,
+) -> Option<Signature> {
     if !scx.config.signatures {
         return None;
     }
     make_method_signature(id, ident, generics, m, scx).ok()
 }
 
-pub fn assoc_const_signature(id: NodeId,
-                             ident: ast::Name,
-                             ty: &ast::Ty,
-                             default: Option<&ast::Expr>,
-                             scx: &SaveContext)
-                             -> Option<Signature> {
+pub fn assoc_const_signature(
+    id: NodeId,
+    ident: ast::Name,
+    ty: &ast::Ty,
+    default: Option<&ast::Expr>,
+    scx: &SaveContext,
+) -> Option<Signature> {
     if !scx.config.signatures {
         return None;
     }
     make_assoc_const_signature(id, ident, ty, default, scx).ok()
 }
 
-pub fn assoc_type_signature(id: NodeId,
-                            ident: ast::Ident,
-                            bounds: Option<&ast::TyParamBounds>,
-                            default: Option<&ast::Ty>,
-                            scx: &SaveContext)
-                            -> Option<Signature> {
+pub fn assoc_type_signature(
+    id: NodeId,
+    ident: ast::Ident,
+    bounds: Option<&ast::TyParamBounds>,
+    default: Option<&ast::Ty>,
+    scx: &SaveContext,
+) -> Option<Signature> {
     if !scx.config.signatures {
         return None;
     }
@@ -117,11 +120,12 @@ trait Sig {
     fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext) -> Result;
 }
 
-fn extend_sig(mut sig: Signature,
-              text: String,
-              defs: Vec<SigElement>,
-              refs: Vec<SigElement>)
-              -> Signature {
+fn extend_sig(
+    mut sig: Signature,
+    text: String,
+    defs: Vec<SigElement>,
+    refs: Vec<SigElement>,
+) -> Signature {
     sig.text = text;
     sig.defs.extend(defs.into_iter());
     sig.refs.extend(refs.into_iter());
@@ -142,8 +146,12 @@ fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
 
     let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip();
 
-    result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
-    result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
+    result
+        .defs
+        .extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
+    result
+        .refs
+        .extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
 
     result
 }
@@ -188,9 +196,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                 let text = format!("{}{}", prefix, nested.text);
                 Ok(replace_text(nested, text))
             }
-            ast::TyKind::Never => {
-                Ok(text_sig("!".to_owned()))
-            },
+            ast::TyKind::Never => Ok(text_sig("!".to_owned())),
             ast::TyKind::Tup(ref ts) => {
                 let mut text = "(".to_owned();
                 let mut defs = vec![];
@@ -215,8 +221,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                 if !f.lifetimes.is_empty() {
                     // FIXME defs, bounds on lifetimes
                     text.push_str("for<");
-                    text.push_str(&f.lifetimes.iter().map(|l|
-                        l.lifetime.ident.to_string()).collect::<Vec<_>>().join(", "));
+                    text.push_str(&f.lifetimes
+                        .iter()
+                        .map(|l| l.lifetime.ident.to_string())
+                        .collect::<Vec<_>>()
+                        .join(", "));
                     text.push('>');
                 }
 
@@ -251,9 +260,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
 
                 Ok(Signature { text, defs, refs })
             }
-            ast::TyKind::Path(None, ref path) => {
-                path.make(offset, id, scx)
-            }
+            ast::TyKind::Path(None, ref path) => path.make(offset, id, scx),
             ast::TyKind::Path(Some(ref qself), ref path) => {
                 let nested_ty = qself.ty.make(offset + 1, id, scx)?;
                 let prefix = if qself.position == 0 {
@@ -325,11 +332,13 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     text.push_str("mut ");
                 }
                 let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
+                let defs = vec![
+                    SigElement {
+                        id: id_from_node_id(self.id, scx),
+                        start: offset + text.len(),
+                        end: offset + text.len() + name.len(),
+                    },
+                ];
                 text.push_str(&name);
                 text.push_str(": ");
 
@@ -346,11 +355,13 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
             ast::ItemKind::Const(ref ty, ref expr) => {
                 let mut text = "const ".to_owned();
                 let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
+                let defs = vec![
+                    SigElement {
+                        id: id_from_node_id(self.id, scx),
+                        start: offset + text.len(),
+                        end: offset + text.len() + name.len(),
+                    },
+                ];
                 text.push_str(&name);
                 text.push_str(": ");
 
@@ -379,12 +390,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                 }
                 text.push_str("fn ");
 
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
                 sig.text.push('(');
                 for i in &decl.inputs {
@@ -413,11 +419,13 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
             ast::ItemKind::Mod(ref _mod) => {
                 let mut text = "mod ".to_owned();
                 let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
+                let defs = vec![
+                    SigElement {
+                        id: id_from_node_id(self.id, scx),
+                        start: offset + text.len(),
+                        end: offset + text.len() + name.len(),
+                    },
+                ];
                 text.push_str(&name);
                 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just puck one.
                 text.push(';');
@@ -430,12 +438,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
             }
             ast::ItemKind::Ty(ref ty, ref generics) => {
                 let text = "type ".to_owned();
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
                 sig.text.push_str(" = ");
                 let ty = ty.make(offset + sig.text.len(), id, scx)?;
@@ -446,34 +449,19 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
             }
             ast::ItemKind::Enum(_, ref generics) => {
                 let text = "enum ".to_owned();
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
             ast::ItemKind::Struct(_, ref generics) => {
                 let text = "struct ".to_owned();
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
             ast::ItemKind::Union(_, ref generics) => {
                 let text = "union ".to_owned();
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
@@ -488,12 +476,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     text.push_str("unsafe ");
                 }
                 text.push_str("trait ");
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
                 if !bounds.is_empty() {
                     sig.text.push_str(": ");
@@ -515,13 +498,15 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                 text.push_str(" for .. {}");
                 Ok(replace_text(trait_sig, text))
             }
-            ast::ItemKind::Impl(unsafety,
-                                polarity,
-                                defaultness,
-                                ref generics,
-                                ref opt_trait,
-                                ref ty,
-                                _) => {
+            ast::ItemKind::Impl(
+                unsafety,
+                polarity,
+                defaultness,
+                ref generics,
+                ref opt_trait,
+                ref ty,
+                _,
+            ) => {
                 let mut text = String::new();
                 if let ast::Defaultness::Default = defaultness {
                     text.push_str("default ");
@@ -562,8 +547,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
             ast::ItemKind::ExternCrate(_) => Err("extern crate"),
             // FIXME should implement this (e.g., pub use).
             ast::ItemKind::Use(_) => Err("import"),
-            ast::ItemKind::Mac(..) |
-            ast::ItemKind::MacroDef(_) => Err("Macro"),
+            ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
         }
     }
 }
@@ -573,19 +557,14 @@ fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext) -> Result {
         let def = scx.get_path_def(id.ok_or("Missing id for Path")?);
 
         let (name, start, end) = match def {
-            Def::Label(..)  |
-            Def::PrimTy(..) |
-            Def::SelfTy(..) |
-            Def::Err => {
+            Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {
                 return Ok(Signature {
                     text: pprust::path_to_string(self),
                     defs: vec![],
                     refs: vec![],
                 })
             }
-            Def::AssociatedConst(..) |
-            Def::Variant(..) |
-            Def::VariantCtor(..) => {
+            Def::AssociatedConst(..) | Def::Variant(..) | Def::VariantCtor(..) => {
                 let len = self.segments.len();
                 if len < 2 {
                     return Err("Bad path");
@@ -635,9 +614,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
 
             if !l.bounds.is_empty() {
                 l_text.push_str(": ");
-                let bounds = l.bounds.iter().map(|l| {
-                    l.ident.to_string()
-                }).collect::<Vec<_>>().join(" + ");
+                let bounds = l.bounds
+                    .iter()
+                    .map(|l| l.ident.to_string())
+                    .collect::<Vec<_>>()
+                    .join(" + ");
                 l_text.push_str(&bounds);
                 // FIXME add lifetime bounds refs.
             }
@@ -662,7 +643,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
         }
 
         text.push('>');
-        Ok(Signature {text, defs, refs: vec![] })
+        Ok(Signature {
+            text,
+            defs,
+            refs: vec![],
+        })
     }
 }
 
@@ -710,11 +695,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     refs.extend(field_sig.refs.into_iter());
                 }
                 text.push('}');
-                Ok(Signature {
-                    text,
-                    defs,
-                    refs,
-                })
+                Ok(Signature { text, defs, refs })
             }
             ast::VariantData::Tuple(ref fields, id) => {
                 let name_def = SigElement {
@@ -733,11 +714,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     refs.extend(field_sig.refs.into_iter());
                 }
                 text.push(')');
-                Ok(Signature {
-                    text,
-                    defs,
-                    refs,
-                })
+                Ok(Signature { text, defs, refs })
             }
             ast::VariantData::Unit(id) => {
                 let name_def = SigElement {
@@ -763,12 +740,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                 let mut text = String::new();
                 text.push_str("fn ");
 
-                let mut sig = name_and_generics(text,
-                                                offset,
-                                                generics,
-                                                self.id,
-                                                self.ident,
-                                                scx)?;
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
                 sig.text.push('(');
                 for i in &decl.inputs {
@@ -800,11 +772,13 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     text.push_str("mut ");
                 }
                 let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
+                let defs = vec![
+                    SigElement {
+                        id: id_from_node_id(self.id, scx),
+                        start: offset + text.len(),
+                        end: offset + text.len() + name.len(),
+                    },
+                ];
                 text.push_str(&name);
                 text.push_str(": ");
 
@@ -816,11 +790,13 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
             ast::ForeignItemKind::Ty => {
                 let mut text = "type ".to_owned();
                 let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
+                let defs = vec![
+                    SigElement {
+                        id: id_from_node_id(self.id, scx),
+                        start: offset + text.len(),
+                        end: offset + text.len() + name.len(),
+                    },
+                ];
                 text.push_str(&name);
                 text.push(';');
 
@@ -834,13 +810,14 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
     }
 }
 
-fn name_and_generics(mut text: String,
-                     offset: usize,
-                     generics: &ast::Generics,
-                     id: NodeId,
-                     name: ast::Ident,
-                     scx: &SaveContext)
-                     -> Result {
+fn name_and_generics(
+    mut text: String,
+    offset: usize,
+    generics: &ast::Generics,
+    id: NodeId,
+    name: ast::Ident,
+    scx: &SaveContext,
+) -> Result {
     let name = name.to_string();
     let def = SigElement {
         id: id_from_node_id(id, scx),
@@ -855,19 +832,22 @@ fn name_and_generics(mut text: String,
 }
 
 
-fn make_assoc_type_signature(id: NodeId,
-                             ident: ast::Ident,
-                             bounds: Option<&ast::TyParamBounds>,
-                             default: Option<&ast::Ty>,
-                             scx: &SaveContext)
-                             -> Result {
+fn make_assoc_type_signature(
+    id: NodeId,
+    ident: ast::Ident,
+    bounds: Option<&ast::TyParamBounds>,
+    default: Option<&ast::Ty>,
+    scx: &SaveContext,
+) -> Result {
     let mut text = "type ".to_owned();
     let name = ident.to_string();
-    let mut defs = vec![SigElement {
-        id: id_from_node_id(id, scx),
-        start: text.len(),
-        end: text.len() + name.len(),
-    }];
+    let mut defs = vec![
+        SigElement {
+            id: id_from_node_id(id, scx),
+            start: text.len(),
+            end: text.len() + name.len(),
+        },
+    ];
     let mut refs = vec![];
     text.push_str(&name);
     if let Some(bounds) = bounds {
@@ -886,19 +866,22 @@ fn make_assoc_type_signature(id: NodeId,
     Ok(Signature { text, defs, refs })
 }
 
-fn make_assoc_const_signature(id: NodeId,
-                              ident: ast::Name,
-                              ty: &ast::Ty,
-                              default: Option<&ast::Expr>,
-                              scx: &SaveContext)
-                              -> Result {
+fn make_assoc_const_signature(
+    id: NodeId,
+    ident: ast::Name,
+    ty: &ast::Ty,
+    default: Option<&ast::Expr>,
+    scx: &SaveContext,
+) -> Result {
     let mut text = "const ".to_owned();
     let name = ident.to_string();
-    let mut defs = vec![SigElement {
-        id: id_from_node_id(id, scx),
-        start: text.len(),
-        end: text.len() + name.len(),
-    }];
+    let mut defs = vec![
+        SigElement {
+            id: id_from_node_id(id, scx),
+            start: text.len(),
+            end: text.len() + name.len(),
+        },
+    ];
     let mut refs = vec![];
     text.push_str(&name);
     text.push_str(": ");
@@ -916,12 +899,13 @@ fn make_assoc_const_signature(id: NodeId,
     Ok(Signature { text, defs, refs })
 }
 
-fn make_method_signature(id: NodeId,
-                         ident: ast::Ident,
-                         generics: &ast::Generics,
-                         m: &ast::MethodSig,
-                         scx: &SaveContext)
-                         -> Result {
+fn make_method_signature(
+    id: NodeId,
+    ident: ast::Ident,
+    generics: &ast::Generics,
+    m: &ast::MethodSig,
+    scx: &SaveContext,
+) -> Result {
     // FIXME code dup with function signature
     let mut text = String::new();
     if m.constness.node == ast::Constness::Const {
@@ -937,12 +921,7 @@ fn make_method_signature(id: NodeId,
     }
     text.push_str("fn ");
 
-    let mut sig = name_and_generics(text,
-                                    0,
-                                    generics,
-                                    id,
-                                    ident,
-                                    scx)?;
+    let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
 
     sig.text.push('(');
     for i in &m.decl.inputs {
index 5bfb4d1b3b20389546be7f1fba6538b64fe5165f..ff1a8541e06a6e3b057980649b52a7de106fe9a1 100644 (file)
@@ -42,7 +42,11 @@ pub fn make_path_string(file_name: &str) -> String {
         if path.is_absolute() {
             path.clone().display().to_string()
         } else {
-            env::current_dir().unwrap().join(&path).display().to_string()
+            env::current_dir()
+                .unwrap()
+                .join(&path)
+                .display()
+                .to_string()
         }
     }
 
@@ -66,7 +70,7 @@ pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
         loop {
             let ts = toks.real_token();
             if ts.tok == token::Eof {
-                return result
+                return result;
             }
             if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
                 result = Some(ts.sp);
@@ -122,10 +126,9 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
         loop {
             let next = toks.real_token();
 
-            if (next.tok == token::Lt || next.tok == token::Colon) &&
-               angle_count == 0 &&
-               bracket_count == 0 &&
-               prev.tok.is_ident() {
+            if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0
+                && bracket_count == 0 && prev.tok.is_ident()
+            {
                 result = Some(prev.sp);
             }
 
@@ -152,12 +155,14 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
         }
         if angle_count != 0 || bracket_count != 0 {
             let loc = self.sess.codemap().lookup_char_pos(span.lo());
-            span_bug!(span,
-                      "Mis-counted brackets when breaking path? Parsing '{}' \
-                       in {}, line {}",
-                      self.snippet(span),
-                      loc.file.name,
-                      loc.line);
+            span_bug!(
+                span,
+                "Mis-counted brackets when breaking path? Parsing '{}' \
+                 in {}, line {}",
+                self.snippet(span),
+                loc.file.name,
+                loc.line
+            );
         }
         if result.is_none() && prev.tok.is_ident() && angle_count == 0 {
             return Some(prev.sp);
@@ -211,7 +216,7 @@ fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span>
             if f(ts.tok) {
                 let ts = toks.real_token();
                 if ts.tok == token::Eof {
-                    return None
+                    return None;
                 } else {
                     return Some(ts.sp);
                 }
@@ -278,7 +283,12 @@ pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
         };
 
         //If the span comes from a fake filemap, filter it.
-        if !self.sess.codemap().lookup_char_pos(parent.lo()).file.is_real_file() {
+        if !self.sess
+            .codemap()
+            .lookup_char_pos(parent.lo())
+            .file
+            .is_real_file()
+        {
             return true;
         }
 
index 5b7879ea58ee7e88de2b444d2f112c8c34811f27..f797464c1f8f13f8ffd4d89397a6e5c55c27ed5b 100644 (file)
@@ -19,6 +19,7 @@ owning_ref = "0.3.3"
 rustc-demangle = "0.1.4"
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
+rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
index 907693ea8a379ee179908b9132eefaf70cc02dcf..1d2bfd001f1fe20da070edd0822685f912a8907a 100644 (file)
@@ -503,31 +503,10 @@ fn link_staticlib(sess: &Session,
     if !all_native_libs.is_empty() {
         if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
             print_native_static_libs(sess, &all_native_libs);
-        } else {
-            // Fallback for backwards compatibility only
-            print_native_static_libs_legacy(sess, &all_native_libs);
         }
     }
 }
 
-fn print_native_static_libs_legacy(sess: &Session, all_native_libs: &[NativeLibrary]) {
-    sess.note_without_error("link against the following native artifacts when linking against \
-                             this static library");
-    sess.note_without_error("This list will not be printed by default. \
-        Please add --print=native-static-libs if you need this information");
-
-    for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) {
-        let name = match lib.kind {
-            NativeLibraryKind::NativeStaticNobundle |
-            NativeLibraryKind::NativeUnknown => "library",
-            NativeLibraryKind::NativeFramework => "framework",
-            // These are included, no need to print them
-            NativeLibraryKind::NativeStatic => continue,
-        };
-        sess.note_without_error(&format!("{}: {}", name, lib.name));
-    }
-}
-
 fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
     let lib_args: Vec<_> = all_native_libs.iter()
         .filter(|l| relevant_lib(sess, l))
@@ -671,11 +650,12 @@ fn link_natively(sess: &Session,
             break
         }
 
-        sess.struct_warn("looks like the linker segfaulted when we tried to \
-                          call it, automatically retrying again")
-            .note(&format!("{:?}", cmd))
-            .note(&out)
-            .emit();
+        warn!(
+            "looks like the linker segfaulted when we tried to call it, \
+             automatically retrying again. cmd = {:?}, out = {}.",
+            cmd,
+            out,
+        );
     }
 
     match prog {
index b9519bba2dd89b1eb6ed337a3c5b071ef346076c..23890905718a85cb8d7cf42c1d1fef05bab182ce 100644 (file)
@@ -125,6 +125,12 @@ pub fn provide_local(providers: &mut Providers) {
                               None,
                               SymbolExportLevel::Rust));
         }
+
+        // Sort so we get a stable incr. comp. hash.
+        local_crate.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
+            name1.cmp(name2)
+        });
+
         Arc::new(local_crate)
     };
 }
@@ -148,7 +154,7 @@ pub fn provide_extern(providers: &mut Providers) {
         let special_runtime_crate =
             tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
 
-        let crate_exports = tcx
+        let mut crate_exports: Vec<_> = tcx
             .exported_symbol_ids(cnum)
             .iter()
             .map(|&def_id| {
@@ -176,6 +182,11 @@ pub fn provide_extern(providers: &mut Providers) {
             })
             .collect();
 
+        // Sort so we get a stable incr. comp. hash.
+        crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
+            name1.cmp(name2)
+        });
+
         Arc::new(crate_exports)
     };
 }
index 10475a2b1b1a06fa98ff3b2a99a73d84d969fdd3..d59d8ca1a7801363c2196f1761c83b4575f161ed 100644 (file)
     ("large", llvm::CodeModel::Large),
 ];
 
+pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
+    ("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic),
+    ("local-dynamic", llvm::ThreadLocalMode::LocalDynamic),
+    ("initial-exec", llvm::ThreadLocalMode::InitialExec),
+    ("local-exec", llvm::ThreadLocalMode::LocalExec),
+];
+
 pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
     match llvm::last_error() {
         Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
@@ -173,9 +180,7 @@ pub fn target_machine_factory(sess: &Session)
         Some(x) => x.1,
         _ => {
             sess.err(&format!("{:?} is not a valid code model",
-                             sess.opts
-                                 .cg
-                                 .code_model));
+                              code_model_arg));
             sess.abort_if_errors();
             bug!();
         }
index eaf7392aab5b4f6d95a2ca635c4fb0bd8db8b3e6..4ae289cfada00a4b6746c0edb07211d7c5c61b53 100644 (file)
@@ -196,7 +196,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
 
         for attr in attrs {
             if attr.check_name("thread_local") {
-                llvm::set_thread_local(g, true);
+                llvm::set_thread_local_mode(g, ccx.tls_model());
             }
         }
 
@@ -215,7 +215,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
         // symbol and another one doesn't.
         for attr in ccx.tcx().get_attrs(def_id).iter() {
             if attr.check_name("thread_local") {
-                llvm::set_thread_local(g, true);
+                llvm::set_thread_local_mode(g, ccx.tls_model());
             }
         }
         if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
@@ -305,9 +305,8 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         debuginfo::create_global_var_metadata(ccx, id, g);
 
-        if attr::contains_name(attrs,
-                               "thread_local") {
-            llvm::set_thread_local(g, true);
+        if attr::contains_name(attrs, "thread_local") {
+            llvm::set_thread_local_mode(g, ccx.tls_model());
         }
 
         base::set_link_section(ccx, g, attrs);
index 9df057c77a95d36c2909921fcfbbb237ecb2ce30..cb71ef104d3d9424fc0310c63c3da083f5636d1b 100644 (file)
@@ -52,6 +52,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     check_overflow: bool,
     use_dll_storage_attrs: bool,
+    tls_model: llvm::ThreadLocalMode,
 }
 
 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
@@ -159,9 +160,25 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
         Some(x) => x.1,
         _ => {
             sess.err(&format!("{:?} is not a valid relocation mode",
-                             sess.opts
-                                 .cg
-                                 .code_model));
+                              reloc_model_arg));
+            sess.abort_if_errors();
+            bug!();
+        }
+    }
+}
+
+fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
+    let tls_model_arg = match sess.opts.debugging_opts.tls_model {
+        Some(ref s) => &s[..],
+        None => &sess.target.target.options.tls_model[..],
+    };
+
+    match ::back::write::TLS_MODEL_ARGS.iter().find(
+        |&&arg| arg.0 == tls_model_arg) {
+        Some(x) => x.1,
+        _ => {
+            sess.err(&format!("{:?} is not a valid TLS model",
+                              tls_model_arg));
             sess.abort_if_errors();
             bug!();
         }
@@ -283,10 +300,13 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> SharedCrateContext<'b, 'tcx> {
 
         let check_overflow = tcx.sess.overflow_checks();
 
+        let tls_model = get_tls_model(&tcx.sess);
+
         SharedCrateContext {
             tcx,
             check_overflow,
             use_dll_storage_attrs,
+            tls_model,
         }
     }
 
@@ -528,6 +548,10 @@ pub fn use_dll_storage_attrs(&self) -> bool {
         self.shared.use_dll_storage_attrs()
     }
 
+    pub fn tls_model(&self) -> llvm::ThreadLocalMode {
+        self.shared.tls_model
+    }
+
     /// Generate a new symbol name with the given prefix. This symbol name must
     /// only be used for definitions with `internal` or `private` linkage.
     pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
index e80239175681e8bd80d3bbfbc0cc23768a77429b..2f1a95038eae59a543a580eb16198bc26f5e43d5 100644 (file)
@@ -1203,7 +1203,8 @@ macro_rules! arith {
         simd_add: TyUint, TyInt => add, TyFloat => fadd;
         simd_sub: TyUint, TyInt => sub, TyFloat => fsub;
         simd_mul: TyUint, TyInt => mul, TyFloat => fmul;
-        simd_div: TyFloat => fdiv;
+        simd_div: TyUint => udiv, TyInt => sdiv, TyFloat => fdiv;
+        simd_rem: TyUint => urem, TyInt => srem, TyFloat => frem;
         simd_shl: TyUint, TyInt => shl;
         simd_shr: TyUint => lshr, TyInt => ashr;
         simd_and: TyUint, TyInt => and;
index c0460fb4852e99df89ea6b8c4df1661914f8d8c5..29394af33969faf984129c62405220a621739088 100644 (file)
@@ -24,6 +24,7 @@
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
+#![feature(i128)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
@@ -43,6 +44,7 @@
 extern crate owning_ref;
 #[macro_use] extern crate rustc;
 extern crate rustc_allocator;
+extern crate rustc_apfloat;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate rustc_incremental;
index 4fe726364f227bc2e5d1e3ccd02b2c1142476b5e..b91638a8d14c9339242e7bc149a9e2a058383e40 100644 (file)
@@ -78,7 +78,9 @@ unsafe fn configure_llvm(sess: &Session) {
 const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                  "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                  "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
-                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
+                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
+                                                 "xsave\0", "xsaveopt\0", "xsavec\0",
+                                                 "xsaves\0"];
 
 const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
 
index cea7b9585d8e3081d91e2b88e674c47072ac988c..6573e507bd32554e26acd6398a9b7cde2d8c2a24 100644 (file)
@@ -11,7 +11,7 @@
 use llvm::{self, ValueRef};
 use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
 use rustc_const_math::ConstInt::*;
-use rustc_const_math::{ConstInt, ConstMathErr};
+use rustc_const_math::{ConstInt, ConstMathErr, MAX_F32_PLUS_HALF_ULP};
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
 use rustc::traits;
@@ -21,6 +21,7 @@
 use rustc::ty::layout::{self, LayoutTyper};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::subst::{Kind, Substs, Subst};
+use rustc_apfloat::{ieee, Float, Status};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use {adt, base, machine};
 use abi::{self, Abi};
@@ -689,20 +690,18 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                                     llvm::LLVMConstIntCast(llval, ll_t_out.to_ref(), s)
                                 }
                                 (CastTy::Int(_), CastTy::Float) => {
-                                    if signed {
-                                        llvm::LLVMConstSIToFP(llval, ll_t_out.to_ref())
-                                    } else {
-                                        llvm::LLVMConstUIToFP(llval, ll_t_out.to_ref())
-                                    }
+                                    cast_const_int_to_float(self.ccx, llval, signed, ll_t_out)
                                 }
                                 (CastTy::Float, CastTy::Float) => {
                                     llvm::LLVMConstFPCast(llval, ll_t_out.to_ref())
                                 }
                                 (CastTy::Float, CastTy::Int(IntTy::I)) => {
-                                    llvm::LLVMConstFPToSI(llval, ll_t_out.to_ref())
+                                    cast_const_float_to_int(self.ccx, &operand,
+                                                            true, ll_t_out, span)
                                 }
                                 (CastTy::Float, CastTy::Int(_)) => {
-                                    llvm::LLVMConstFPToUI(llval, ll_t_out.to_ref())
+                                    cast_const_float_to_int(self.ccx, &operand,
+                                                            false, ll_t_out, span)
                                 }
                                 (CastTy::Ptr(_), CastTy::Ptr(_)) |
                                 (CastTy::FnPtr, CastTy::Ptr(_)) |
@@ -955,6 +954,64 @@ pub fn const_scalar_checked_binop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+unsafe fn cast_const_float_to_int(ccx: &CrateContext,
+                                  operand: &Const,
+                                  signed: bool,
+                                  int_ty: Type,
+                                  span: Span) -> ValueRef {
+    let llval = operand.llval;
+    let float_bits = match operand.ty.sty {
+        ty::TyFloat(fty) => fty.bit_width(),
+        _ => bug!("cast_const_float_to_int: operand not a float"),
+    };
+    // Note: this breaks if llval is a complex constant expression rather than a simple constant.
+    // One way that might happen would be if addresses could be turned into integers in constant
+    // expressions, but that doesn't appear to be possible?
+    // In any case, an ICE is better than producing undef.
+    let llval_bits = consts::bitcast(llval, Type::ix(ccx, float_bits as u64));
+    let bits = const_to_opt_u128(llval_bits, false).unwrap_or_else(|| {
+        panic!("could not get bits of constant float {:?}",
+               Value(llval));
+    });
+    let int_width = int_ty.int_width() as usize;
+    // Try to convert, but report an error for overflow and NaN. This matches HIR const eval.
+    let cast_result = match float_bits {
+        32 if signed => ieee::Single::from_bits(bits).to_i128(int_width).map(|v| v as u128),
+        64 if signed => ieee::Double::from_bits(bits).to_i128(int_width).map(|v| v as u128),
+        32 => ieee::Single::from_bits(bits).to_u128(int_width),
+        64 => ieee::Double::from_bits(bits).to_u128(int_width),
+        n => bug!("unsupported float width {}", n),
+    };
+    if cast_result.status.contains(Status::INVALID_OP) {
+        let err = ConstEvalErr { span: span, kind: ErrKind::CannotCast };
+        err.report(ccx.tcx(), span, "expression");
+    }
+    C_big_integral(int_ty, cast_result.value)
+}
+
+unsafe fn cast_const_int_to_float(ccx: &CrateContext,
+                                  llval: ValueRef,
+                                  signed: bool,
+                                  float_ty: Type) -> ValueRef {
+    // Note: this breaks if llval is a complex constant expression rather than a simple constant.
+    // One way that might happen would be if addresses could be turned into integers in constant
+    // expressions, but that doesn't appear to be possible?
+    // In any case, an ICE is better than producing undef.
+    let value = const_to_opt_u128(llval, signed).unwrap_or_else(|| {
+        panic!("could not get z128 value of constant integer {:?}",
+               Value(llval));
+    });
+    if signed {
+        llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
+    } else if float_ty.float_width() == 32 && value >= MAX_F32_PLUS_HALF_ULP {
+        // We're casting to f32 and the value is > f32::MAX + 0.5 ULP -> round up to infinity.
+        let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
+        consts::bitcast(infinity_bits, float_ty)
+    } else {
+        llvm::LLVMConstUIToFP(llval, float_ty.to_ref())
+    }
+}
+
 impl<'a, 'tcx> MirContext<'a, 'tcx> {
     pub fn trans_constant(&mut self,
                           bcx: &Builder<'a, 'tcx>,
index 777b86387e8bfcd650a714efa11d9026466f2ee3..7e187a85867cbd870f9c1418fa2c6405127c3cd8 100644 (file)
 use rustc::mir::tcx::LvalueTy;
 use rustc::mir;
 use rustc::middle::lang_items::ExchangeMallocFnLangItem;
+use rustc_apfloat::{ieee, Float, Status, Round};
+use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
+use std::{u128, i128};
 
 use base;
 use builder::Builder;
 use callee;
-use common::{self, val_ty, C_bool, C_i32, C_null, C_usize, C_uint};
+use common::{self, val_ty, C_bool, C_i32, C_u32, C_u64, C_null, C_usize, C_uint, C_big_integral};
+use consts;
 use adt;
 use machine;
 use monomorphize;
@@ -333,14 +337,12 @@ pub fn trans_rvalue_operand(&mut self,
                                 bcx.ptrtoint(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Ptr(_)) =>
                                 bcx.inttoptr(llval, ll_t_out),
-                            (CastTy::Int(_), CastTy::Float) if signed =>
-                                bcx.sitofp(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Float) =>
-                                bcx.uitofp(llval, ll_t_out),
+                                cast_int_to_float(&bcx, signed, llval, ll_t_in, ll_t_out),
                             (CastTy::Float, CastTy::Int(IntTy::I)) =>
-                                bcx.fptosi(llval, ll_t_out),
+                                cast_float_to_int(&bcx, true, llval, ll_t_in, ll_t_out),
                             (CastTy::Float, CastTy::Int(_)) =>
-                                bcx.fptoui(llval, ll_t_out),
+                                cast_float_to_int(&bcx, false, llval, ll_t_in, ll_t_out),
                             _ => bug!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
                         };
                         OperandValue::Immediate(newval)
@@ -815,3 +817,158 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
 
     bcx.ccx.get_intrinsic(&name)
 }
+
+fn cast_int_to_float(bcx: &Builder,
+                     signed: bool,
+                     x: ValueRef,
+                     int_ty: Type,
+                     float_ty: Type) -> ValueRef {
+    // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
+    // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
+    // LLVM's uitofp produces undef in those cases, so we manually check for that case.
+    let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32;
+    if is_u128_to_f32 {
+        // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
+        // and for everything else LLVM's uitofp works just fine.
+        let max = C_big_integral(int_ty, MAX_F32_PLUS_HALF_ULP);
+        let overflow = bcx.icmp(llvm::IntUGE, x, max);
+        let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
+        let infinity = consts::bitcast(infinity_bits, float_ty);
+        bcx.select(overflow, infinity, bcx.uitofp(x, float_ty))
+    } else {
+        if signed {
+            bcx.sitofp(x, float_ty)
+        } else {
+            bcx.uitofp(x, float_ty)
+        }
+    }
+}
+
+fn cast_float_to_int(bcx: &Builder,
+                     signed: bool,
+                     x: ValueRef,
+                     float_ty: Type,
+                     int_ty: Type) -> ValueRef {
+    let fptosui_result = if signed {
+        bcx.fptosi(x, int_ty)
+    } else {
+        bcx.fptoui(x, int_ty)
+    };
+
+    if !bcx.sess().opts.debugging_opts.saturating_float_casts {
+        return fptosui_result;
+    }
+    // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
+    // destination integer type after rounding towards zero. This `undef` value can cause UB in
+    // safe code (see issue #10184), so we implement a saturating conversion on top of it:
+    // Semantically, the mathematical value of the input is rounded towards zero to the next
+    // mathematical integer, and then the result is clamped into the range of the destination
+    // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
+    // the destination integer type. NaN is mapped to 0.
+    //
+    // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
+    // a value representable in int_ty.
+    // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
+    // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
+    // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
+    // representable. Note that this only works if float_ty's exponent range is sufficently large.
+    // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
+    // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
+    // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
+    // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
+    // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
+    fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: Type) -> (u128, u128) {
+        let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
+        assert_eq!(rounded_min.status, Status::OK);
+        let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
+        assert!(rounded_max.value.is_finite());
+        (rounded_min.value.to_bits(), rounded_max.value.to_bits())
+    }
+    fn int_max(signed: bool, int_ty: Type) -> u128 {
+        let shift_amount = 128 - int_ty.int_width();
+        if signed {
+            i128::MAX as u128 >> shift_amount
+        } else {
+            u128::MAX >> shift_amount
+        }
+    }
+    fn int_min(signed: bool, int_ty: Type) -> i128 {
+        if signed {
+            i128::MIN >> (128 - int_ty.int_width())
+        } else {
+            0
+        }
+    }
+    let float_bits_to_llval = |bits| {
+        let bits_llval = match float_ty.float_width() {
+            32 => C_u32(bcx.ccx, bits as u32),
+            64 => C_u64(bcx.ccx, bits as u64),
+            n => bug!("unsupported float width {}", n),
+        };
+        consts::bitcast(bits_llval, float_ty)
+    };
+    let (f_min, f_max) = match float_ty.float_width() {
+        32 => compute_clamp_bounds::<ieee::Single>(signed, int_ty),
+        64 => compute_clamp_bounds::<ieee::Double>(signed, int_ty),
+        n => bug!("unsupported float width {}", n),
+    };
+    let f_min = float_bits_to_llval(f_min);
+    let f_max = float_bits_to_llval(f_max);
+    // To implement saturation, we perform the following steps:
+    //
+    // 1. Cast x to an integer with fpto[su]i. This may result in undef.
+    // 2. Compare x to f_min and f_max, and use the comparison results to select:
+    //  a) int_ty::MIN if x < f_min or x is NaN
+    //  b) int_ty::MAX if x > f_max
+    //  c) the result of fpto[su]i otherwise
+    // 3. If x is NaN, return 0.0, otherwise return the result of step 2.
+    //
+    // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
+    // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
+    // undef does not introduce any non-determinism either.
+    // More importantly, the above procedure correctly implements saturating conversion.
+    // Proof (sketch):
+    // If x is NaN, 0 is returned by definition.
+    // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
+    // This yields three cases to consider:
+    // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
+    //     saturating conversion for inputs in that range.
+    // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
+    //     (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
+    //     than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
+    //     is correct.
+    // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
+    //     int_ty::MIN and therefore the return value of int_ty::MIN is correct.
+    // QED.
+
+    // Step 1 was already performed above.
+
+    // Step 2: We use two comparisons and two selects, with %s1 being the result:
+    //     %less_or_nan = fcmp ult %x, %f_min
+    //     %greater = fcmp olt %x, %f_max
+    //     %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
+    //     %s1 = select %greater, int_ty::MAX, %s0
+    // Note that %less_or_nan uses an *unordered* comparison. This comparison is true if the
+    // operands are not comparable (i.e., if x is NaN). The unordered comparison ensures that s1
+    // becomes int_ty::MIN if x is NaN.
+    // Performance note: Unordered comparison can be lowered to a "flipped" comparison and a
+    // negation, and the negation can be merged into the select. Therefore, it not necessarily any
+    // more expensive than a ordered ("normal") comparison. Whether these optimizations will be
+    // performed is ultimately up to the backend, but at least x86 does perform them.
+    let less_or_nan = bcx.fcmp(llvm::RealULT, x, f_min);
+    let greater = bcx.fcmp(llvm::RealOGT, x, f_max);
+    let int_max = C_big_integral(int_ty, int_max(signed, int_ty));
+    let int_min = C_big_integral(int_ty, int_min(signed, int_ty) as u128);
+    let s0 = bcx.select(less_or_nan, int_min, fptosui_result);
+    let s1 = bcx.select(greater, int_max, s0);
+
+    // Step 3: NaN replacement.
+    // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
+    // Therefore we only need to execute this step for signed integer types.
+    if signed {
+        // LLVM has no isNaN predicate, so we use (x == x) instead
+        bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
+    } else {
+        s1
+    }
+}
index 6980ba8a52505f9ccfa0f3366095c5b4c1f0e2c8..03c0f13e2f5f7b7e1dbd2526ac66b94d9a6911b7 100644 (file)
 
 use collector::InliningMap;
 use common;
-use rustc::dep_graph::{DepNode, WorkProductId};
+use rustc::dep_graph::WorkProductId;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::middle::trans::{Linkage, Visibility};
@@ -147,10 +147,6 @@ fn work_product_id(&self) -> WorkProductId {
         WorkProductId::from_cgu_name(self.name())
     }
 
-    fn work_product_dep_node(&self) -> DepNode {
-        self.work_product_id().to_dep_node()
-    }
-
     fn items_in_deterministic_order<'a>(&self,
                                         tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                         -> Vec<(TransItem<'tcx>,
@@ -253,14 +249,6 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         cgu1.name().cmp(cgu2.name())
     });
 
-    if tcx.sess.opts.enable_dep_node_debug_strs() {
-        for cgu in &result {
-            let dep_node = cgu.work_product_dep_node();
-            tcx.dep_graph.register_dep_node_debug_str(dep_node,
-                                                            || cgu.name().to_string());
-        }
-    }
-
     result
 }
 
index fd003fc097933c1cfddd0274994d9a7efe3891a9..429471221c671041c012c72d648c0262a83120a2 100644 (file)
 
 use rustc_data_structures::bitvec::BitVector;
 
+use syntax::attr;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
     Eager,
@@ -324,9 +326,14 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut roots = Vec::new();
 
     {
+        let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _)| {
+            tcx.hir.local_def_id(node_id)
+        });
+
         let mut visitor = RootCollector {
             tcx,
             mode,
+            entry_fn,
             output: &mut roots,
         };
 
@@ -875,6 +882,7 @@ struct RootCollector<'b, 'a: 'b, 'tcx: 'a + 'b> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mode: TransItemCollectionMode,
     output: &'b mut Vec<TransItem<'tcx>>,
+    entry_fn: Option<DefId>,
 }
 
 impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
@@ -932,10 +940,7 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                 let tcx = self.tcx;
                 let def_id = tcx.hir.local_def_id(item.id);
 
-                if (self.mode == TransItemCollectionMode::Eager ||
-                    !tcx.is_const_fn(def_id) || tcx.is_exported_symbol(def_id)) &&
-                   !item_has_type_parameters(tcx, def_id) {
-
+                if self.is_root(def_id) {
                     debug!("RootCollector: ItemFn({})",
                            def_id_to_string(tcx, def_id));
 
@@ -957,10 +962,7 @@ fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
                 let tcx = self.tcx;
                 let def_id = tcx.hir.local_def_id(ii.id);
 
-                if (self.mode == TransItemCollectionMode::Eager ||
-                    !tcx.is_const_fn(def_id) ||
-                    tcx.is_exported_symbol(def_id)) &&
-                   !item_has_type_parameters(tcx, def_id) {
+                if self.is_root(def_id) {
                     debug!("RootCollector: MethodImplItem({})",
                            def_id_to_string(tcx, def_id));
 
@@ -973,6 +975,22 @@ fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
     }
 }
 
+impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
+    fn is_root(&self, def_id: DefId) -> bool {
+        !item_has_type_parameters(self.tcx, def_id) && match self.mode {
+            TransItemCollectionMode::Eager => {
+                true
+            }
+            TransItemCollectionMode::Lazy => {
+                self.entry_fn == Some(def_id) ||
+                self.tcx.is_exported_symbol(def_id) ||
+                attr::contains_name(&self.tcx.get_attrs(def_id),
+                                    "rustc_std_internal_symbol")
+            }
+        }
+    }
+}
+
 fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
     let generics = tcx.generics_of(def_id);
     generics.parent_types as usize + generics.types.len() > 0
index ec9c5b1119b74824748ab64efba8553a92e4877e..47968afd70d97112675ff0380155c434cef7e5e5 100644 (file)
@@ -51,7 +51,8 @@ pub fn requests_inline<'a, 'tcx>(
         // available to normal end-users.
         return true
     }
-    attr::requests_inline(&instance.def.attrs(tcx)[..])
+    attr::requests_inline(&instance.def.attrs(tcx)[..]) ||
+        tcx.is_const_fn(instance.def.def_id())
 }
 
 pub fn is_inline_instance<'a, 'tcx>(
index 6a341a1e7d378dd2ea81e963495d9942fa8e9d00..d6f8707b8747a834caf890745b038ae58f96dbba 100644 (file)
 extern crate syntax;
 extern crate syntax_pos;
 
-use rustc::ty::TyCtxt;
+use rustc::ty::{TyCtxt, Instance};
 use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::map as hir_map;
 use rustc::util::nodemap::NodeSet;
 
-use syntax::attr;
-
 pub mod common;
 pub mod link;
 pub mod collector;
@@ -77,7 +75,7 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
 ///
 /// This list is later used by linkers to determine the set of symbols needed to
 /// be exposed from a dynamic library and it's also encoded into the metadata.
-pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
+pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
     tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
         // Next, we want to ignore some FFI functions that are not exposed from
         // this crate. Reachable FFI functions can be lumped into two
@@ -107,11 +105,10 @@ pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
                 node: hir::ImplItemKind::Method(..), .. }) => {
                 let def_id = tcx.hir.local_def_id(id);
                 let generics = tcx.generics_of(def_id);
-                let attributes = tcx.get_attrs(def_id);
                 (generics.parent_types == 0 && generics.types.is_empty()) &&
                 // Functions marked with #[inline] are only ever translated
                 // with "internal" linkage and are never exported.
-                !attr::requests_inline(&attributes)
+                !common::requests_inline(tcx, &Instance::mono(tcx, def_id))
             }
 
             _ => false
index 1471e235156eb8ade6a050fe0668ceb92e75565a..95b19616e5e631e5d75b31ffde1b737cd114915d 100644 (file)
@@ -572,8 +572,8 @@ fn conv_object_ty_poly_trait_ref(&self,
             let b = &trait_bounds[0];
             let span = b.trait_ref.path.span;
             struct_span_err!(self.tcx().sess, span, E0225,
-                "only Send/Sync traits can be used as additional traits in a trait object")
-                .span_label(span, "non-Send/Sync additional trait")
+                "only auto traits can be used as additional traits in a trait object")
+                .span_label(span, "non-auto additional trait")
                 .emit();
         }
 
@@ -1257,27 +1257,10 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     -> (Vec<DefId>, Vec<&'b hir::PolyTraitRef>)
 {
     let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.iter().partition(|bound| {
+        // Checks whether `trait_did` is an auto trait and adds it to `auto_traits` if so.
         match bound.trait_ref.path.def {
-            Def::Trait(trait_did) => {
-                // Checks whether `trait_did` refers to one of the builtin
-                // traits, like `Send`, and adds it to `auto_traits` if so.
-                if Some(trait_did) == tcx.lang_items().send_trait() ||
-                    Some(trait_did) == tcx.lang_items().sync_trait() {
-                    let segments = &bound.trait_ref.path.segments;
-                    segments[segments.len() - 1].with_parameters(|parameters| {
-                        if !parameters.types.is_empty() {
-                            check_type_argument_count(tcx, bound.trait_ref.path.span,
-                                                      parameters.types.len(), &[]);
-                        }
-                        if !parameters.lifetimes.is_empty() {
-                            report_lifetime_number_error(tcx, bound.trait_ref.path.span,
-                                                         parameters.lifetimes.len(), 0);
-                        }
-                    });
-                    true
-                } else {
-                    false
-                }
+            Def::Trait(trait_did) if tcx.trait_is_auto(trait_did) => {
+                true
             }
             _ => false
         }
@@ -1403,64 +1386,3 @@ pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
         vec
     }
 }
-
-pub enum ExplicitSelf<'tcx> {
-    ByValue,
-    ByReference(ty::Region<'tcx>, hir::Mutability),
-    ByBox
-}
-
-impl<'tcx> ExplicitSelf<'tcx> {
-    /// We wish to (for now) categorize an explicit self
-    /// declaration like `self: SomeType` into either `self`,
-    /// `&self`, `&mut self`, or `Box<self>`. We do this here
-    /// by some simple pattern matching. A more precise check
-    /// is done later in `check_method_receiver()`.
-    ///
-    /// Examples:
-    ///
-    /// ```
-    /// impl Foo for &T {
-    ///     // Legal declarations:
-    ///     fn method1(self: &&T); // ExplicitSelf::ByReference
-    ///     fn method2(self: &T); // ExplicitSelf::ByValue
-    ///     fn method3(self: Box<&T>); // ExplicitSelf::ByBox
-    ///
-    ///     // Invalid cases will be caught later by `check_method_receiver`:
-    ///     fn method_err1(self: &mut T); // ExplicitSelf::ByReference
-    /// }
-    /// ```
-    ///
-    /// To do the check we just count the number of "modifiers"
-    /// on each type and compare them. If they are the same or
-    /// the impl has more, we call it "by value". Otherwise, we
-    /// look at the outermost modifier on the method decl and
-    /// call it by-ref, by-box as appropriate. For method1, for
-    /// example, the impl type has one modifier, but the method
-    /// type has two, so we end up with
-    /// ExplicitSelf::ByReference.
-    pub fn determine(untransformed_self_ty: Ty<'tcx>,
-                     self_arg_ty: Ty<'tcx>)
-                     -> ExplicitSelf<'tcx> {
-        fn count_modifiers(ty: Ty) -> usize {
-            match ty.sty {
-                ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
-                ty::TyAdt(def, _) if def.is_box() => count_modifiers(ty.boxed_ty()) + 1,
-                _ => 0,
-            }
-        }
-
-        let impl_modifiers = count_modifiers(untransformed_self_ty);
-        let method_modifiers = count_modifiers(self_arg_ty);
-
-        if impl_modifiers >= method_modifiers {
-            ExplicitSelf::ByValue
-        } else {
-            match self_arg_ty.sty {
-                ty::TyRef(r, mt) => ExplicitSelf::ByReference(r, mt.mutbl),
-                ty::TyAdt(def, _) if def.is_box() => ExplicitSelf::ByBox,
-                _ => ExplicitSelf::ByValue,
-            }
-        }
-    }
-}
index 7b35b466830999788218217c0a8b235609ecb9d8..d68c139894b92adba2c4be525de8fa442a240300 100644 (file)
@@ -83,28 +83,30 @@ enum PointerKind<'tcx> {
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     /// Returns the kind of unsize information of t, or None
-    /// if t is sized or it is unknown.
-    fn pointer_kind(&self, t: Ty<'tcx>, span: Span) -> PointerKind<'tcx> {
+    /// if t is unknown.
+    fn pointer_kind(&self, t: Ty<'tcx>, span: Span) -> Option<PointerKind<'tcx>> {
         if self.type_is_known_to_be_sized(t, span) {
-            return PointerKind::Thin;
+            return Some(PointerKind::Thin);
         }
 
         match t.sty {
-            ty::TySlice(_) | ty::TyStr => PointerKind::Length,
+            ty::TySlice(_) | ty::TyStr => Some(PointerKind::Length),
             ty::TyDynamic(ref tty, ..) =>
-                PointerKind::Vtable(tty.principal().map(|p| p.def_id())),
+                Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))),
             ty::TyAdt(def, substs) if def.is_struct() => {
                 // FIXME(arielb1): do some kind of normalization
                 match def.struct_variant().fields.last() {
-                    None => PointerKind::Thin,
+                    None => Some(PointerKind::Thin),
                     Some(f) => self.pointer_kind(f.ty(self.tcx, substs), span),
                 }
             }
             // Pointers to foreign types are thin, despite being unsized
-            ty::TyForeign(..) => PointerKind::Thin,
+            ty::TyForeign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
-            ty::TyProjection(ref pi) => PointerKind::OfProjection(pi),
-            ty::TyParam(ref p) => PointerKind::OfParam(p),
+            ty::TyProjection(ref pi) => Some(PointerKind::OfProjection(pi)),
+            ty::TyParam(ref p) => Some(PointerKind::OfParam(p)),
+            // Insufficient type information.
+            ty::TyInfer(_) => None,
             _ => panic!(),
         }
     }
@@ -123,6 +125,8 @@ enum CastError {
     NeedViaThinPtr,
     NeedViaInt,
     NonScalar,
+    UnknownExprPtrKind,
+    UnknownCastPtrKind,
 }
 
 fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
@@ -241,6 +245,25 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                                  self.expr_ty,
                                  fcx.ty_to_string(self.cast_ty)).emit();
             }
+            CastError::UnknownCastPtrKind |
+            CastError::UnknownExprPtrKind => {
+                let unknown_cast_to = match e {
+                    CastError::UnknownCastPtrKind => true,
+                    CastError::UnknownExprPtrKind => false,
+                    _ => bug!(),
+                };
+                let mut err = struct_span_err!(fcx.tcx.sess, self.span, E0641,
+                                               "cannot cast {} a pointer of an unknown kind",
+                                               if unknown_cast_to { "to" } else { "from" });
+                err.note("The type information given here is insufficient to check whether \
+                          the pointer cast is valid");
+                if unknown_cast_to {
+                    err.span_suggestion_short(self.cast_span,
+                                              "consider giving more type information",
+                                              String::new());
+                }
+                err.emit();
+            }
         }
     }
 
@@ -457,14 +480,27 @@ fn check_ptr_ptr_cast(&self,
         debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
         // ptr-ptr cast. vtables must match.
 
-        // Cast to thin pointer is OK
+        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span);
         let cast_kind = fcx.pointer_kind(m_cast.ty, self.span);
+
+        let cast_kind = match cast_kind {
+            // We can't cast if target pointer kind is unknown
+            None => return Err(CastError::UnknownCastPtrKind),
+            Some(cast_kind) => cast_kind,
+        };
+
+        // Cast to thin pointer is OK
         if cast_kind == PointerKind::Thin {
             return Ok(CastKind::PtrPtrCast);
         }
 
+        let expr_kind = match expr_kind {
+            // We can't cast to fat pointer if source pointer kind is unknown
+            None => return Err(CastError::UnknownExprPtrKind),
+            Some(expr_kind) => expr_kind,
+        };
+
         // thin -> fat? report invalid cast (don't complain about vtable kinds)
-        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span);
         if expr_kind == PointerKind::Thin {
             return Err(CastError::SizedUnsizedCast);
         }
@@ -483,10 +519,10 @@ fn check_fptr_ptr_cast(&self,
                            -> Result<CastKind, CastError> {
         // fptr-ptr cast. must be to thin ptr
 
-        if fcx.pointer_kind(m_cast.ty, self.span) == PointerKind::Thin {
-            Ok(CastKind::FnPtrPtrCast)
-        } else {
-            Err(CastError::IllegalCast)
+        match fcx.pointer_kind(m_cast.ty, self.span) {
+            None => Err(CastError::UnknownCastPtrKind),
+            Some(PointerKind::Thin) => Ok(CastKind::FnPtrPtrCast),
+            _ => Err(CastError::IllegalCast),
         }
     }
 
@@ -496,10 +532,10 @@ fn check_ptr_addr_cast(&self,
                            -> Result<CastKind, CastError> {
         // ptr-addr cast. must be from thin ptr
 
-        if fcx.pointer_kind(m_expr.ty, self.span) == PointerKind::Thin {
-            Ok(CastKind::PtrAddrCast)
-        } else {
-            Err(CastError::NeedViaThinPtr)
+        match fcx.pointer_kind(m_expr.ty, self.span) {
+            None => Err(CastError::UnknownExprPtrKind),
+            Some(PointerKind::Thin) => Ok(CastKind::PtrAddrCast),
+            _ => Err(CastError::NeedViaThinPtr),
         }
     }
 
@@ -533,10 +569,10 @@ fn check_addr_ptr_cast(&self,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError> {
         // ptr-addr cast. pointer must be thin.
-        if fcx.pointer_kind(m_cast.ty, self.span) == PointerKind::Thin {
-            Ok(CastKind::AddrPtrCast)
-        } else {
-            Err(CastError::IllegalCast)
+        match fcx.pointer_kind(m_cast.ty, self.span) {
+            None => Err(CastError::UnknownCastPtrKind),
+            Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
+            _ => Err(CastError::IllegalCast),
         }
     }
 
index 554a858bcc17342f4d67f63383e702cd1f0dc87d..2c44c40d83d49012d860fa4c9f719e4fd7c93354 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::region;
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::util::ExplicitSelf;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
 use rustc::ty::subst::{Subst, Substs};
@@ -21,7 +22,6 @@
 use syntax_pos::Span;
 
 use super::{Inherited, FnCtxt};
-use astconv::ExplicitSelf;
 
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
@@ -503,12 +503,17 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             ty::TraitContainer(_) => tcx.mk_self_type()
         };
         let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder();
-        match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) {
-            ExplicitSelf::ByValue => "self".to_string(),
-            ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
-            ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(),
-            _ => format!("self: {}", self_arg_ty)
-        }
+        let param_env = ty::ParamEnv::empty(Reveal::All);
+
+        tcx.infer_ctxt().enter(|infcx| {
+            let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
+            match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
+                ExplicitSelf::ByValue => "self".to_string(),
+                ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
+                ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(),
+                _ => format!("self: {}", self_arg_ty)
+            }
+        })
     };
 
     match (trait_m.method_has_self_argument, impl_m.method_has_self_argument) {
index 3861a358b23e0bace364eff331501ac590090dc7..6ef0c37a31583e4b96a8d05ac98e7bd50feec30f 100644 (file)
@@ -348,7 +348,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         "simd_eq" | "simd_ne" | "simd_lt" | "simd_le" | "simd_gt" | "simd_ge" => {
             (2, vec![param(0), param(0)], param(1))
         }
-        "simd_add" | "simd_sub" | "simd_mul" |
+        "simd_add" | "simd_sub" | "simd_mul" | "simd_rem" |
         "simd_div" | "simd_shl" | "simd_shr" |
         "simd_and" | "simd_or" | "simd_xor" => {
             (1, vec![param(0), param(0)], param(0))
index d179b390a291868130709077558d33211a1ce055..a6a81485b23df83c9a483507e3c36e6abec85639 100644 (file)
@@ -289,10 +289,14 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self,
         let guarantor = cmt.guarantor();
         debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
                guarantor);
+        debug!("adjust_upvar_borrow_kind_for_consume: guarantor.cat={:?}",
+               guarantor.cat);
         match guarantor.cat {
             Categorization::Deref(_, mc::BorrowedPtr(..)) |
             Categorization::Deref(_, mc::Implicit(..)) => {
-                match cmt.note {
+                debug!("adjust_upvar_borrow_kind_for_consume: found deref with note {:?}",
+                       cmt.note);
+                match guarantor.note {
                     mc::NoteUpvarRef(upvar_id) => {
                         debug!("adjust_upvar_borrow_kind_for_consume: \
                                 setting upvar_id={:?} to by value",
index 483af08cabfce624deec7e8da665377672928f17..37cf67fe53ef646de897fcab94d7e2fa6f4ef550 100644 (file)
@@ -8,19 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use astconv::ExplicitSelf;
 use check::{Inherited, FnCtxt};
 use constrained_type_params::{identify_constrained_type_params, Parameter};
 
 use hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::util::ExplicitSelf;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::middle::lang_items;
 
 use syntax::ast;
+use syntax::feature_gate::{self, GateIssue};
 use syntax_pos::Span;
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
@@ -451,8 +452,7 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
                                          method: &ty::AssociatedItem,
                                          self_ty: Ty<'tcx>)
     {
-        // check that the type of the method's receiver matches the
-        // method's first parameter.
+        // check that the method has a valid receiver type, given the type `Self`
         debug!("check_method_receiver({:?}, self_ty={:?})",
                method, self_ty);
 
@@ -468,26 +468,57 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
 
         debug!("check_method_receiver: sig={:?}", sig);
 
+        let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
+        let self_ty = fcx.liberate_late_bound_regions(
+            method.def_id,
+            &ty::Binder(self_ty)
+        );
+
         let self_arg_ty = sig.inputs()[0];
-        let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) {
-            ExplicitSelf::ByValue => self_ty,
-            ExplicitSelf::ByReference(region, mutbl) => {
-                fcx.tcx.mk_ref(region, ty::TypeAndMut {
-                    ty: self_ty,
-                    mutbl,
-                })
+
+        let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
+        let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
+        let self_arg_ty = fcx.liberate_late_bound_regions(
+            method.def_id,
+            &ty::Binder(self_arg_ty)
+        );
+
+        let mut autoderef = fcx.autoderef(span, self_arg_ty);
+
+        loop {
+            if let Some((potential_self_ty, _)) = autoderef.next() {
+                debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
+                    potential_self_ty, self_ty);
+
+                if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
+                    autoderef.finalize();
+                    if let Some(mut err) = fcx.demand_eqtype_with_origin(
+                        &cause, self_ty, potential_self_ty) {
+                        err.emit();
+                    }
+                    break
+                }
+            } else {
+                fcx.tcx.sess.diagnostic().mut_span_err(
+                    span, &format!("invalid `self` type: {:?}", self_arg_ty))
+                .note(&format!("type must be `{:?}` or a type that dereferences to it`", self_ty))
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .code(DiagnosticId::Error("E0307".into()))
+                .emit();
+                return
             }
-            ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
-        };
-        let rcvr_ty = fcx.normalize_associated_types_in(span, &rcvr_ty);
-        let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id,
-                                                      &ty::Binder(rcvr_ty));
+        }
 
-        debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
+        let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
+        let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
 
-        let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
-        if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) {
-            err.emit();
+        if let ExplicitSelf::Other = self_kind {
+            if !fcx.tcx.sess.features.borrow().arbitrary_self_types {
+                feature_gate::feature_err(&fcx.tcx.sess.parse_sess, "arbitrary_self_types", span,
+                    GateIssue::Language, "arbitrary `self` types are unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
+            }
         }
     }
 
index 075367cbbb7cdc2130a0eeec101516bb0484a2f6..73bec697d492e408c9bfe43c00efb137587f906e 100644 (file)
@@ -2455,9 +2455,9 @@ fn main() {
 }
 ```
 
-Send and Sync are an exception to this rule: it's possible to have bounds of
-one non-builtin trait, plus either or both of Send and Sync. For example, the
-following compiles correctly:
+Auto traits such as Send and Sync are an exception to this rule:
+It's possible to have bounds of one non-builtin trait, plus any number of
+auto traits. For example, the following compiles correctly:
 
 ```
 fn main() {
@@ -4724,6 +4724,7 @@ fn description(&self) -> &str {
 //  E0247,
 //  E0248, // value used as a type, now reported earlier during resolution as E0412
 //  E0249,
+    E0307, // invalid method `self` type
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
 //  E0372, // coherence not object safe
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
@@ -4743,4 +4744,5 @@ fn description(&self) -> &str {
     E0627, // yield statement outside of generator literal
     E0632, // cannot provide explicit type parameters when `impl Trait` is used in
            // argument position.
+    E0641, // cannot cast to/from a pointer with an unknown kind
 }
index 79eaabe31e86b4698a10da1ee0fa1ecdd91fed9a..8c14d1bbe8f8ac02ba9500335b758cbffe06dccf 100644 (file)
@@ -105,7 +105,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
                     <dd>Switch tab</dd>
                     <dt>&#9166;</dt>
                     <dd>Go to active search result</dd>
-                    <dt>+</dt>
+                    <dt style="width:31px;">+ / -</dt>
                     <dd>Collapse/expand all sections</dd>
                 </dl>
             </div>
index f3a897d2121cb4c2f3345341a2fed5536e6290ac..69eaf24289bfcd13bd5f52997b836aadb59d9732 100644 (file)
@@ -361,6 +361,7 @@ fn to_json(&self) -> Json {
 /// A type used for the search index.
 struct Type {
     name: Option<String>,
+    generics: Option<Vec<String>>,
 }
 
 impl ToJson for Type {
@@ -369,6 +370,9 @@ fn to_json(&self) -> Json {
             Some(ref name) => {
                 let mut data = BTreeMap::new();
                 data.insert("name".to_owned(), name.to_json());
+                if let Some(ref generics) = self.generics {
+                    data.insert("generics".to_owned(), generics.to_json());
+                }
                 Json::Object(data)
             },
             None => Json::Null
@@ -420,7 +424,7 @@ fn init_ids() -> FxHashMap<String, usize> {
      "methods",
      "deref-methods",
      "implementations",
-     ].into_iter().map(|id| (String::from(*id), 1)).collect()
+    ].into_iter().map(|id| (String::from(*id), 1)).collect()
 }
 
 /// This method resets the local table of used ID attributes. This is typically
@@ -667,7 +671,6 @@ fn concise_compared_strs(s1: &str, s2: &str) -> (String, String) {
     (format!("...{}", concise_str(s1)), format!("...{}", concise_str(s2)))
 }
 
-
 fn print_message(msg: &str, intro_msg: &mut bool, span: &Span, text: &str) {
     if !*intro_msg {
         println!("WARNING: documentation for this crate may be rendered \
@@ -1326,7 +1329,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 // Figure out the id of this impl. This may map to a
                 // primitive rather than always to a struct/enum.
                 // Note: matching twice to restrict the lifetime of the `i` borrow.
-                let mut dids = vec![];
+                let mut dids = FxHashSet();
                 if let clean::Item { inner: clean::ImplItem(ref i), .. } = item {
                     let masked_trait = i.trait_.def_id().map_or(false,
                         |d| self.masked_crates.contains(&d.krate));
@@ -1336,7 +1339,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                             clean::BorrowedRef {
                                 type_: box clean::ResolvedPath { did, .. }, ..
                             } => {
-                                dids.push(did);
+                                dids.insert(did);
                             }
                             ref t => {
                                 let did = t.primitive_type().and_then(|t| {
@@ -1344,7 +1347,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                                 });
 
                                 if let Some(did) = did {
-                                    dids.push(did);
+                                    dids.insert(did);
                                 }
                             }
                         }
@@ -1353,7 +1356,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
                         for bound in generics {
                             if let Some(did) = bound.def_id() {
-                                dids.push(did);
+                                dids.insert(did);
                             }
                         }
                     }
@@ -2498,7 +2501,7 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
 
         if !foreign.is_empty() {
             write!(w, "
-                <h2 id='foreign-impls' class='section-header'>
+                <h2 id='foreign-impls' class='small-section-header'>
                   Implementations on Foreign Types<a href='#foreign-impls' class='anchor'></a>
                 </h2>
             ")?;
@@ -3591,7 +3594,8 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
             let mut links = HashSet::new();
             let ret = v.iter()
                        .filter_map(|i| if let Some(ref i) = i.inner_impl().trait_ {
-                           let out = format!("{:#}", i).replace("<", "&lt;").replace(">", "&gt;");
+                           let i_display = format!("{:#}", i);
+                           let out = Escape(&i_display);
                            let encoded = small_url_encode(&format!("{:#}", i));
                            let generated = format!("<a href=\"#impl-{}\">{}</a>", encoded, out);
                            if !links.contains(&generated) && links.insert(generated.clone()) {
@@ -3617,11 +3621,12 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
 fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item,
                   s: &clean::Struct) -> fmt::Result {
     let mut sidebar = String::new();
+    let fields = get_struct_fields_name(&s.fields);
 
-    if s.fields.iter()
-               .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) {
+    if !fields.is_empty() {
         if let doctree::Plain = s.struct_type {
-            sidebar.push_str("<li><a href=\"#fields\">Fields</a></li>");
+            sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
+                                       <div class=\"sidebar-links\">{}</div>", fields));
         }
     }
 
@@ -3633,40 +3638,122 @@ fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
+fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> {
+    match item.inner {
+        clean::ItemEnum::ImplItem(ref i) => {
+            if let Some(ref trait_) = i.trait_ {
+                Some((format!("{:#}", i.for_), format!("{:#}", trait_)))
+            } else {
+                None
+            }
+        },
+        _ => None,
+    }
+}
+
 fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
                  t: &clean::Trait) -> fmt::Result {
     let mut sidebar = String::new();
 
-    let has_types = t.items.iter().any(|m| m.is_associated_type());
-    let has_consts = t.items.iter().any(|m| m.is_associated_const());
-    let has_required = t.items.iter().any(|m| m.is_ty_method());
-    let has_provided = t.items.iter().any(|m| m.is_method());
+    let types = t.items
+                 .iter()
+                 .filter_map(|m| {
+                     match m.name {
+                         Some(ref name) if m.is_associated_type() => {
+                             Some(format!("<a href=\"#associatedtype.{name}\">{name}</a>",
+                                          name=name))
+                         }
+                         _ => None,
+                     }
+                 })
+                 .collect::<String>();
+    let consts = t.items
+                  .iter()
+                  .filter_map(|m| {
+                      match m.name {
+                          Some(ref name) if m.is_associated_const() => {
+                              Some(format!("<a href=\"#associatedconstant.{name}\">{name}</a>",
+                                           name=name))
+                          }
+                          _ => None,
+                      }
+                  })
+                  .collect::<String>();
+    let required = t.items
+                    .iter()
+                    .filter_map(|m| {
+                        match m.name {
+                            Some(ref name) if m.is_ty_method() => {
+                                Some(format!("<a href=\"#tymethod.{name}\">{name}</a>",
+                                             name=name))
+                            }
+                            _ => None,
+                        }
+                    })
+                    .collect::<String>();
+    let provided = t.items
+                    .iter()
+                    .filter_map(|m| {
+                        match m.name {
+                            Some(ref name) if m.is_method() => {
+                                Some(format!("<a href=\"#method.{name}\">{name}</a>", name=name))
+                            }
+                            _ => None,
+                        }
+                    })
+                    .collect::<String>();
 
-    if has_types {
-        sidebar.push_str("<li><a href=\"#associated-types\">Associated Types</a></li>");
+    if !types.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#associated-types\">\
+                                   Associated Types</a><div class=\"sidebar-links\">{}</div>",
+                                  types));
     }
-    if has_consts {
-        sidebar.push_str("<li><a href=\"#associated-const\">Associated Constants</a></li>");
+    if !consts.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#associated-const\">\
+                                   Associated Constants</a><div class=\"sidebar-links\">{}</div>",
+                                  consts));
     }
-    if has_required {
-        sidebar.push_str("<li><a href=\"#required-methods\">Required Methods</a></li>");
+    if !required.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#required-methods\">\
+                                   Required Methods</a><div class=\"sidebar-links\">{}</div>",
+                                  required));
     }
-    if has_provided {
-        sidebar.push_str("<li><a href=\"#provided-methods\">Provided Methods</a></li>");
+    if !provided.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#provided-methods\">\
+                                   Provided Methods</a><div class=\"sidebar-links\">{}</div>",
+                                  provided));
     }
 
     let c = cache();
 
     if let Some(implementors) = c.implementors.get(&it.def_id) {
-        if implementors.iter().any(|i| i.impl_.for_.def_id()
-                                   .map_or(false, |d| !c.paths.contains_key(&d)))
-        {
-            sidebar.push_str("<li><a href=\"#foreign-impls\">\
-                             Implementations on Foreign Types</a></li>");
-        }
-    }
-
-    sidebar.push_str("<li><a href=\"#implementors\">Implementors</a></li>");
+        let res = implementors.iter()
+                              .filter(|i| i.impl_.for_.def_id()
+                                                      .map_or(false, |d| !c.paths.contains_key(&d)))
+                              .filter_map(|i| {
+                                  if let Some(item) = implementor2item(&c, i) {
+                                      match extract_for_impl_name(&item) {
+                                          Some((ref name, ref url)) => {
+                                              Some(format!("<a href=\"#impl-{}\">{}</a>",
+                                                           small_url_encode(url),
+                                                           Escape(name)))
+                                          }
+                                          _ => None,
+                                      }
+                                  } else {
+                                      None
+                                  }
+                              })
+                              .collect::<String>();
+        if !res.is_empty() {
+            sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#foreign-impls\">\
+                                       Implementations on Foreign Types</a><div \
+                                       class=\"sidebar-links\">{}</div>",
+                                      res));
+        }
+    }
+
+    sidebar.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
 
     sidebar.push_str(&sidebar_assoc_items(it));
 
@@ -3693,13 +3780,29 @@ fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
+fn get_struct_fields_name(fields: &[clean::Item]) -> String {
+    fields.iter()
+          .filter(|f| if let clean::StructFieldItem(..) = f.inner {
+              true
+          } else {
+              false
+          })
+          .filter_map(|f| match f.name {
+              Some(ref name) => Some(format!("<a href=\"#structfield.{name}\">\
+                                              {name}</a>", name=name)),
+              _ => None,
+          })
+          .collect()
+}
+
 fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item,
                  u: &clean::Union) -> fmt::Result {
     let mut sidebar = String::new();
+    let fields = get_struct_fields_name(&u.fields);
 
-    if u.fields.iter()
-               .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) {
-        sidebar.push_str("<li><a href=\"#fields\">Fields</a></li>");
+    if !fields.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
+                                   <div class=\"sidebar-links\">{}</div>", fields));
     }
 
     sidebar.push_str(&sidebar_assoc_items(it));
@@ -3714,8 +3817,16 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
                 e: &clean::Enum) -> fmt::Result {
     let mut sidebar = String::new();
 
-    if !e.variants.is_empty() {
-        sidebar.push_str("<li><a href=\"#variants\">Variants</a></li>");
+    let variants = e.variants.iter()
+                             .filter_map(|v| match v.name {
+                                 Some(ref name) => Some(format!("<a href=\"#variant.{name}\">{name}\
+                                                                 </a>", name = name)),
+                                 _ => None,
+                             })
+                             .collect::<String>();
+    if !variants.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#variants\">Variants</a>\
+                                   <div class=\"sidebar-links\">{}</div>", variants));
     }
 
     sidebar.push_str(&sidebar_assoc_items(it));
@@ -3848,23 +3959,42 @@ fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
 }
 
 fn get_index_type(clean_type: &clean::Type) -> Type {
-    Type { name: get_index_type_name(clean_type).map(|s| s.to_ascii_lowercase()) }
+    let t = Type {
+        name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()),
+        generics: get_generics(clean_type),
+    };
+    t
 }
 
-fn get_index_type_name(clean_type: &clean::Type) -> Option<String> {
+fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<String> {
     match *clean_type {
         clean::ResolvedPath { ref path, .. } => {
             let segments = &path.segments;
             Some(segments[segments.len() - 1].name.clone())
-        },
-        clean::Generic(ref s) => Some(s.clone()),
+        }
+        clean::Generic(ref s) if accept_generic => Some(s.clone()),
         clean::Primitive(ref p) => Some(format!("{:?}", p)),
-        clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_),
+        clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic),
         // FIXME: add all from clean::Type.
         _ => None
     }
 }
 
+fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
+    clean_type.generics()
+              .and_then(|types| {
+                  let r = types.iter()
+                               .filter_map(|t| get_index_type_name(t, false))
+                               .map(|s| s.to_ascii_lowercase())
+                               .collect::<Vec<_>>();
+                  if r.is_empty() {
+                      None
+                  } else {
+                      Some(r)
+                  }
+              })
+}
+
 pub fn cache() -> Arc<Cache> {
     CACHE_KEY.with(|c| c.borrow().clone())
 }
index b1120e0af38949e13daa2d1eb2125e2098291766..8d0faf261f6c934df9314726a828edd992f69a47 100644 (file)
         if (elem && className && elem.className) {
             var elemClass = elem.className;
             var start = elemClass.indexOf(className);
-            if (start == -1) {
+            if (start === -1) {
                 return false;
-            } else if (elemClass.length == className.length) {
+            } else if (elemClass.length === className.length) {
                 return true;
             } else {
-                if (start > 0 && elemClass[start - 1] != ' ') {
+                if (start > 0 && elemClass[start - 1] !== ' ') {
                     return false;
                 }
                 var end = start + className.length;
-                if (end < elemClass.length && elemClass[end] != ' ') {
+                if (end < elemClass.length && elemClass[end] !== ' ') {
                     return false;
                 }
                 return true;
             }
+            if (start > 0 && elemClass[start - 1] !== ' ') {
+                return false;
+            }
+            var end = start + className.length;
+            if (end < elemClass.length && elemClass[end] !== ' ') {
+                return false;
+            }
+            return true;
         }
         return false;
     }
     }
 
     function highlightSourceLines(ev) {
+        var search = document.getElementById("search");
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
             from = parseInt(match[1], 10);
                 if (x) {
                     x.scrollIntoView();
                 }
-            };
+            }
             onEach(document.getElementsByClassName('line-numbers'), function(e) {
                 onEach(e.getElementsByTagName('span'), function(i_e) {
                     removeClass(i_e, 'line-highlighted');
             for (i = from; i <= to; ++i) {
                 addClass(document.getElementById(i), 'line-highlighted');
             }
+        } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
+            addClass(search, "hidden");
+            removeClass(document.getElementById("main"), "hidden");
+            var hash = ev.newURL.slice(ev.newURL.indexOf('#') + 1);
+            if (browserSupportsHistoryApi()) {
+                history.replaceState(hash, "", "?search=#" + hash);
+            }
+            var elem = document.getElementById(hash);
+            if (elem) {
+                elem.scrollIntoView();
+            }
         }
     }
     highlightSourceLines(null);
             break;
 
         case "+":
+        case "-":
             ev.preventDefault();
             toggleAllDocs();
             break;
                 return b;
             }
 
-            function nbElements(obj) {
-                var size = 0, key;
-                for (key in obj) {
-                    if (obj.hasOwnProperty(key)) {
-                        size += 1;
+            function extractGenerics(val) {
+                val = val.toLowerCase();
+                if (val.indexOf('<') !== -1) {
+                    var values = val.substring(val.indexOf('<') + 1, val.lastIndexOf('>'));
+                    return {
+                        name: val.substring(0, val.indexOf('<')),
+                        generics: values.split(/\s*,\s*/),
+                    };
+                }
+                return {
+                    name: val,
+                    generics: [],
+                };
+            }
+
+            function checkGenerics(obj, val) {
+                // The names match, but we need to be sure that all generics kinda
+                // match as well.
+                var lev_distance = MAX_LEV_DISTANCE + 1;
+                if (val.generics.length > 0) {
+                    if (obj.generics &&
+                        obj.generics.length >= val.generics.length) {
+                        var elems = obj.generics.slice(0);
+                        for (var y = 0;
+                             y < val.generics.length;
+                             ++y) {
+                            // The point here is to find the type that matches the most.
+                            var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
+                            for (var x = 0; x < elems.length; ++x) {
+                                var tmp_lev = levenshtein(elems[x], val.generics[y]);
+                                if (tmp_lev < lev.lev) {
+                                    lev.lev = tmp_lev;
+                                    lev.pos = x;
+                                }
+                            }
+                            if (lev.pos !== -1) {
+                                elems.splice(lev.pos, 1);
+                                lev_distance = min(lev.lev, lev_distance);
+                            } else {
+                                return MAX_LEV_DISTANCE + 1;
+                            }
+                        }
+                        return lev_distance;
                     }
+                } else {
+                    return 0;
                 }
-                return size;
+                return MAX_LEV_DISTANCE + 1;
             }
 
-            function findArg(obj, val) {
+            // Check for type name and type generics (if any).
+            function checkType(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
+                if (obj.name === val.name) {
+                    if (literalSearch === true) {
+                        if (val.generics.length !== 0) {
+                            if (obj.generics && obj.length >= val.generics.length) {
+                                var elems = obj.generics.slice(0);
+                                var allFound = true;
+                                var x;
+
+                                for (var y = 0; allFound === true && y < val.generics.length; ++y) {
+                                    allFound = false;
+                                    for (x = 0; allFound === false && x < elems.length; ++x) {
+                                        allFound = elems[x] === val.generics[y];
+                                    }
+                                    if (allFound === true) {
+                                        elems.splice(x - 1, 1);
+                                    }
+                                }
+                                if (allFound === true) {
+                                    return true;
+                                }
+                            } else {
+                                return false;
+                            }
+                        }
+                        return true;
+                    }
+                    // If the type has generics but don't match, then it won't return at this point.
+                    // Otherwise, `checkGenerics` will return 0 and it'll return.
+                    var tmp_lev = checkGenerics(obj, val);
+                    if (tmp_lev <= MAX_LEV_DISTANCE) {
+                        return tmp_lev;
+                    }
+                }
+                // Names didn't match so let's check if one of the generic types could.
+                if (literalSearch === true) {
+                     if (obj.generics.length > 0) {
+                        for (var x = 0; x < obj.generics.length; ++x) {
+                            if (obj.generics[x] === val.name) {
+                                return true;
+                            }
+                        }
+                    }
+                    return false;
+                }
+                var new_lev = levenshtein(obj.name, val.name);
+                if (new_lev < lev_distance) {
+                    if ((lev = checkGenerics(obj, val)) <= MAX_LEV_DISTANCE) {
+                        lev_distance = min(min(new_lev, lev), lev_distance);
+                    }
+                } else if (obj.generics && obj.generics.length > 0) {
+                    for (var x = 0; x < obj.generics.length; ++x) {
+                        lev_distance = min(levenshtein(obj.generics[x], val.name), lev_distance);
+                    }
+                }
+                // Now whatever happens, the returned distance is "less good" so we should mark it
+                // as such, and so we add 1 to the distance to make it "less good".
+                return lev_distance + 1;
+            }
+
+            function findArg(obj, val, literalSearch) {
+                var lev_distance = MAX_LEV_DISTANCE + 1;
+
                 if (obj && obj.type && obj.type.inputs.length > 0) {
                     for (var i = 0; i < obj.type.inputs.length; i++) {
-                        if (obj.type.inputs[i].name === val) {
-                            // No need to check anything else: we found it. Let's just move on.
-                            return 0;
+                        var tmp = checkType(obj.type.inputs[i], val, literalSearch);
+                        if (literalSearch === true && tmp === true) {
+                            return true;
                         }
-                        lev_distance = min(levenshtein(obj.type.inputs[i].name, val), lev_distance);
+                        lev_distance = min(tmp, lev_distance);
                         if (lev_distance === 0) {
                             return 0;
                         }
                     }
                 }
-                return lev_distance;
+                return literalSearch === true ? false : lev_distance;
             }
 
-            function checkReturned(obj, val) {
+            function checkReturned(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
+
                 if (obj && obj.type && obj.type.output) {
-                    if (obj.type.output.name.toLowerCase() === val) {
-                        return 0;
+                    var tmp = checkType(obj.type.output, val, literalSearch);
+                    if (literalSearch === true && tmp === true) {
+                        return true;
                     }
-                    lev_distance = min(levenshtein(obj.type.output.name, val));
+                    lev_distance = min(tmp, lev_distance);
                     if (lev_distance === 0) {
                         return 0;
                     }
                 }
-                return lev_distance;
+                return literalSearch === true ? false : lev_distance;
             }
 
             function typePassesFilter(filter, type) {
             if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
                 val.charAt(val.length - 1) === val.charAt(0))
             {
-                val = val.substr(1, val.length - 2).toLowerCase();
+                var results_length = 0;
+                val = extractGenerics(val.substr(1, val.length - 2));
                 for (var i = 0; i < nSearchWords; ++i) {
+                    var in_args = findArg(searchIndex[i], val, true);
+                    var returned = checkReturned(searchIndex[i], val, true);
                     var ty = searchIndex[i];
-                    if (searchWords[i] === val) {
+                    if (searchWords[i] === val.name) {
                         // filter type: ... queries
-                        if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
+                        if (typePassesFilter(typeFilter, searchIndex[i].ty) &&
+                            results[ty.path + ty.name] === undefined)
+                        {
                             results[ty.path + ty.name] = {id: i, index: -1};
+                            results_length += 1;
                         }
-                    } else if (findArg(searchIndex[i], val) ||
-                               (ty.type &&
-                                ty.type.output &&
-                                ty.type.output.name === val)) {
-                        if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
+                    } else if ((in_args === true || returned === true) &&
+                               typePassesFilter(typeFilter, searchIndex[i].ty)) {
+                        if (results[ty.path + ty.name] === undefined) {
                             results[ty.path + ty.name] = {
                                 id: i,
                                 index: -1,
                                 dontValidate: true,
+                                in_args: in_args,
+                                returned: returned,
                             };
+                            results_length += 1;
+                        } else {
+                            if (in_args === true) {
+                                results[ty.path + ty.name].in_args = true;
+                            }
+                            if (returned === true) {
+                                results[ty.path + ty.name].returned = true;
+                            }
                         }
                     }
-                    if (nbElements(results) === max) {
+                    if (results_length === max) {
                         break;
                     }
                 }
                 var input = parts[0];
                 // sort inputs so that order does not matter
                 var inputs = input.split(",").map(trimmer).sort();
-                var output = parts[1];
+                for (var i = 0; i < inputs.length; ++i) {
+                    inputs[i] = extractGenerics(inputs[i]);
+                }
+                var output = extractGenerics(parts[1]);
 
                 for (var i = 0; i < nSearchWords; ++i) {
                     var type = searchIndex[i].type;
                         continue;
                     }
 
-                    // sort index inputs so that order does not matter
-                    var typeInputs = type.inputs.map(function (input) {
-                        return input.name;
-                    }).sort();
-
                     // allow searching for void (no output) functions as well
                     var typeOutput = type.output ? type.output.name : "";
-                    if (output === "*" || output == typeOutput) {
+                    var returned = checkReturned(ty, output, true);
+                    if (output.name === "*" || returned === true) {
+                        var in_args = false;
+                        var module = false;
+
                         if (input === "*") {
-                            results[ty.path + ty.name] = {id: i, index: -1, dontValidate: true};
+                            module = true;
                         } else {
                             var allFound = true;
                             for (var it = 0; allFound === true && it < inputs.length; it++) {
-                                var found = false;
-                                for (var y = 0; found === false && y < typeInputs.length; y++) {
-                                    found = typeInputs[y] === inputs[it];
-                                }
-                                allFound = found;
+                                allFound = checkType(type, inputs[it], true);
                             }
-                            if (allFound === true) {
+                            in_args = allFound;
+                        }
+                        if (in_args === true || returned === true || module === true) {
+                            if (results[ty.path + ty.name] !== undefined) {
+                                if (returned === true) {
+                                    results[ty.path + ty.name].returned = true;
+                                }
+                                if (in_args === true) {
+                                    results[ty.path + ty.name].in_args = true;
+                                }
+                            } else {
                                 results[ty.path + ty.name] = {
                                     id: i,
                                     index: -1,
                                     dontValidate: true,
+                                    returned: returned,
+                                    in_args: in_args,
                                 };
                             }
                         }
                     }
                 }
-                query.inputs = inputs;
-                query.output = output;
+                query.inputs = inputs.map(function(input) {
+                    return input.name;
+                });
+                query.output = output.name;
             } else {
                 query.inputs = [val];
                 query.output = val;
                 query.search = val;
                 // gather matching search results up to a certain maximum
                 val = val.replace(/\_/g, "");
+                var valGenerics = extractGenerics(val);
+                var results_length = 0;
                 for (var i = 0; i < split.length; ++i) {
                     for (var j = 0; j < nSearchWords; ++j) {
                         var lev_distance;
                         if (!ty) {
                             continue;
                         }
+                        var returned = false;
+                        var in_args = false;
+                        var index = -1;
+                        // we want lev results to go lower than others
+                        var lev = MAX_LEV_DISTANCE;
+
                         if (searchWords[j].indexOf(split[i]) > -1 ||
                             searchWords[j].indexOf(val) > -1 ||
                             searchWords[j].replace(/_/g, "").indexOf(val) > -1)
                         {
                             // filter type: ... queries
-                            if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
+                            if (typePassesFilter(typeFilter, searchIndex[j].ty) &&
+                                results[ty.path + ty.name] === undefined) {
+                                index = searchWords[j].replace(/_/g, "").indexOf(val);
+                            }
+                        }
+                        if ((lev_distance = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
+                            if (typePassesFilter(typeFilter, searchIndex[j].ty) &&
+                                (results[ty.path + ty.name] === undefined ||
+                                 results[ty.path + ty.name].lev > lev_distance)) {
+                                lev = min(lev, lev_distance);
+                                index = 0;
+                            }
+                        }
+                        if ((lev_distance = findArg(searchIndex[j], valGenerics))
+                            <= MAX_LEV_DISTANCE) {
+                            if (typePassesFilter(typeFilter, searchIndex[j].ty) &&
+                                (results[ty.path + ty.name] === undefined ||
+                                 results[ty.path + ty.name].lev > lev_distance)) {
+                                in_args = true;
+                                lev = min(lev_distance, lev);
+                                index = 0;
+                            }
+                        }
+                        if ((lev_distance = checkReturned(searchIndex[j], valGenerics)) <=
+                            MAX_LEV_DISTANCE) {
+                            if (typePassesFilter(typeFilter, searchIndex[j].ty) &&
+                                (results[ty.path + ty.name] === undefined ||
+                                 results[ty.path + ty.name].lev > lev_distance)) {
+                                returned = true;
+                                lev = min(lev_distance, lev);
+                                index = 0;
+                            }
+                        }
+                        if (index !== -1) {
+                            if (results[ty.path + ty.name] === undefined) {
                                 results[ty.path + ty.name] = {
                                     id: j,
-                                    index: searchWords[j].replace(/_/g, "").indexOf(val),
-                                    lev: 0,
+                                    index: index,
+                                    lev: lev,
+                                    in_args: in_args,
+                                    returned: returned,
                                 };
-                            }
-                        } else if (
-                            (lev_distance = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
-                            if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                if (results[ty.path + ty.name] === undefined ||
-                                    results[ty.path + ty.name].lev > lev_distance) {
-                                    results[ty.path + ty.name] = {
-                                        id: j,
-                                        index: 0,
-                                        // we want lev results to go lower than others
-                                        lev: lev_distance,
-                                    };
+                                results_length += 1;
+                            } else {
+                                if (results[ty.path + ty.name].lev > lev) {
+                                    results[ty.path + ty.name].lev = lev;
                                 }
-                            }
-                        } else if (
-                            (lev_distance = findArg(searchIndex[j], val)) <= MAX_LEV_DISTANCE) {
-                            if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                if (results[ty.path + ty.name] === undefined ||
-                                    results[ty.path + ty.name].lev > lev_distance) {
-                                    results[ty.path + ty.name] = {
-                                        id: j,
-                                        index: 0,
-                                        // we want lev results to go lower than others
-                                        lev: lev_distance,
-                                    };
+                                if (in_args === true) {
+                                    results[ty.path + ty.name].in_args = true;
                                 }
-                            }
-                        } else if (
-                            (lev_distance = checkReturned(searchIndex[j], val)) <=
-                            MAX_LEV_DISTANCE) {
-                            if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                if (results[ty.path + ty.name] === undefined ||
-                                    results[ty.path + ty.name].lev > lev_distance) {
-                                    results[ty.path + ty.name] = {
-                                        id: j,
-                                        index: 0,
-                                        // we want lev results to go lower than others
-                                        lev: lev_distance,
-                                    };
+                                if (returned === true) {
+                                    results[ty.path + ty.name].returned = true;
                                 }
                             }
                         }
-                        if (nbElements(results) === max) {
+                        if (results_length === max) {
                             break;
                         }
                     }
             });
 
             for (var i = 0; i < results.length; ++i) {
-                var result = results[i],
-                    name = result.item.name.toLowerCase(),
-                    path = result.item.path.toLowerCase(),
-                    parent = result.item.parent;
+                var result = results[i];
 
                 // this validation does not make sense when searching by types
                 if (result.dontValidate) {
                     continue;
                 }
+                var name = result.item.name.toLowerCase(),
+                    path = result.item.path.toLowerCase(),
+                    parent = result.item.parent;
 
-                var valid = validateResult(name, path, split, parent);
-                if (!valid) {
+                if (result.returned === false && result.param === false &&
+                    validateResult(name, path, split, parent) === false)
+                {
                     result.id = -1;
                 }
             }
                 // each check is for validation so we negate the conditions and invalidate
                 if (!(
                     // check for an exact name match
-                    name.toLowerCase().indexOf(keys[i]) > -1 ||
+                    name.indexOf(keys[i]) > -1 ||
                     // then an exact path match
-                    path.toLowerCase().indexOf(keys[i]) > -1 ||
+                    path.indexOf(keys[i]) > -1 ||
                     // next if there is a parent, check for exact parent match
                     (parent !== undefined &&
                         parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
                     // lastly check to see if the name was a levenshtein match
-                    levenshtein(name.toLowerCase(), keys[i]) <= MAX_LEV_DISTANCE)) {
+                    levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
                     return false;
                 }
             }
             return output;
         }
 
-        function makeTabHeader(tabNb, text) {
+        function makeTabHeader(tabNb, text, nbElems) {
             if (currentTab === tabNb) {
-                return '<div class="selected">' + text + '</div>';
+                return '<div class="selected">' + text +
+                       ' <div class="count">(' + nbElems + ')</div></div>';
             }
-            return '<div>' + text + '</div>';
+            return '<div>' + text + ' <div class="count">(' + nbElems + ')</div></div>';
         }
 
         function showResults(results) {
             output = '<h1>Results for ' + escape(query.query) +
                 (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
                 '<div id="titles">' +
-                makeTabHeader(0, "Types/modules") +
-                makeTabHeader(1, "As parameters") +
-                makeTabHeader(2, "As return value") +
+                makeTabHeader(0, "Types/modules", results['others'].length) +
+                makeTabHeader(1, "As parameters", results['in_args'].length) +
+                makeTabHeader(2, "As return value", results['returned'].length) +
                 '</div><div id="results">';
 
             output += addTab(results['others'], query);
                     filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
                     if (obj.type) {
                         if (results['returned'].length < maxResults &&
-                            obj.type.output &&
-                            obj.type.output.name.toLowerCase() === query.output) {
+                            resultIndex[i].returned === true)
+                        {
                             results['returned'].push(obj);
                             added = true;
                         }
-                        if (results['in_args'].length < maxResults && obj.type.inputs.length > 0) {
-                            var all_founds = true;
-                            for (var it = 0;
-                                 all_founds === true && it < query.inputs.length;
-                                 it++) {
-                                var found = false;
-                                for (var y = 0;
-                                     found === false && y < obj.type.inputs.length;
-                                     y++) {
-                                    found = query.inputs[it] === obj.type.inputs[y].name;
-                                }
-                                all_founds = found;
-                            }
-                            if (all_founds === true) {
-                                results['in_args'].push(obj);
-                                added = true;
-                            }
+                        if (results['in_args'].length < maxResults &&
+                            resultIndex[i].in_args === true)
+                        {
+                            results['in_args'].push(obj);
+                            added = true;
                         }
                     }
                     if (results['others'].length < maxResults &&
-                        ((query.search && obj.name.indexOf(query.search) !== -1) ||
-                          added === false)) {
+                        (added === false ||
+                         (query.search && obj.name.indexOf(query.search) !== -1))) {
                         results['others'].push(obj);
                     }
                 }
 
         function itemTypeFromName(typename) {
             for (var i = 0; i < itemTypes.length; ++i) {
-                if (itemTypes[i] === typename) { return i; }
+                if (itemTypes[i] === typename) {
+                    return i;
+                }
             }
             return -1;
         }
             var search_input = document.getElementsByClassName("search-input")[0];
             search_input.onkeyup = callback;
             search_input.oninput = callback;
-            document.getElementsByClassName("search-form")[0].onsubmit = function(e){
+            document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
                 e.preventDefault();
                 clearTimeout(searchTimeout);
                 search();
 
             var crates = [];
             for (var crate in rawSearchIndex) {
-                if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
+                if (!rawSearchIndex.hasOwnProperty(crate)) {
+                    continue;
+                }
                 crates.push(crate);
             }
             crates.sort();
             });
         }
     });
+
+    var search_input = document.getElementsByClassName("search-input")[0];
+
+    if (search_input) {
+        search_input.onfocus = function() {
+            if (search_input.value !== "") {
+                addClass(document.getElementById("main"), "hidden");
+                removeClass(document.getElementById("search"), "hidden");
+                if (browserSupportsHistoryApi()) {
+                    history.replaceState(search_input.value,
+                                         "",
+                                         "?search=" + encodeURIComponent(search_input.value));
+                }
+            }
+        };
+    }
 }());
 
 // Sets the focus on the search bar at the top of the page
index 398a692f8df5e1529218f508b1cf30f937da530a..55acc575152371a5ac05b11a30ad3f17aa5b91ab 100644 (file)
@@ -582,13 +582,14 @@ body.blur > :not(#help) {
        display: block;
        margin-top: -1px;
 }
-#help dd { margin: 5px 33px; }
+#help dd { margin: 5px 35px; }
 #help .infos { padding-left: 0; }
 #help h1, #help h2 { margin-top: 0; }
 #help > div div {
        width: 50%;
        float: left;
        padding: 20px;
+       padding-left: 17px;
 }
 
 .stab {
@@ -944,3 +945,9 @@ pre.rust {
 #titles > div:hover {
        border-bottom: 3px solid #0089ff;
 }
+
+#titles > div > div.count {
+       display: inline-block;
+       color: #888;
+       font-size: 16px;
+}
index 9316805b9322abf6ea84759058393cd7c25dbfc4..9bbd16355be387a6afa8b3db40ab4213861ef369 100644 (file)
@@ -337,15 +337,23 @@ pub fn make_test(s: &str,
 
     let mut prog = String::new();
 
-    // First push any outer attributes from the example, assuming they
-    // are intended to be crate attributes.
-    prog.push_str(&crate_attrs);
+    if opts.attrs.is_empty() {
+        // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
+        // lints that are commonly triggered in doctests. The crate-level test attributes are
+        // commonly used to make tests fail in case they trigger warnings, so having this there in
+        // that case may cause some tests to pass when they shouldn't have.
+        prog.push_str("#![allow(unused)]\n");
+    }
 
-    // Next, any attributes for other aspects such as lints.
+    // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
     for attr in &opts.attrs {
         prog.push_str(&format!("#![{}]\n", attr));
     }
 
+    // Now push any outer attributes from the example, assuming they
+    // are intended to be crate attributes.
+    prog.push_str(&crate_attrs);
+
     // Don't inject `extern crate std` because it's already injected by the
     // compiler.
     if !s.contains("extern crate") && !opts.no_crate_inject && cratename != Some("std") {
index d239b79d4ba7a2d13a8df296ea7936ee8a1c2427..3430ecabcbeaea079874ef3406e77c19491ac5aa 100644 (file)
@@ -20,12 +20,14 @@ panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
-rand = { path = "../librand" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 std_unicode = { path = "../libstd_unicode" }
 unwind = { path = "../libunwind" }
 
+[dev-dependencies]
+rand = "0.3"
+
 [target.x86_64-apple-darwin.dependencies]
 rustc_asan = { path = "../librustc_asan" }
 rustc_tsan = { path = "../librustc_tsan" }
index d96a4f40d3f8ea0475582b7b9a6cca19afbc1926..7a79a472d58d9b8701aa8546c075651cebec9896 100644 (file)
@@ -20,8 +20,8 @@
 use iter::{FromIterator, FusedIterator};
 use mem::{self, replace};
 use ops::{Deref, Index, InPlace, Place, Placer};
-use rand::{self, Rng};
 use ptr;
+use sys;
 
 use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
 use super::table::BucketState::{Empty, Full};
@@ -2239,28 +2239,29 @@ fn take_key(&mut self) -> Option<K> {
         self.key.take()
     }
 
-    /// Replaces the entry, returning the old key and value.
+    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
+    /// the key used to create this entry.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(map_entry_replace)]
-    /// use std::collections::HashMap;
-    /// use std::collections::hash_map::Entry;
+    /// use std::collections::hash_map::{Entry, HashMap};
+    /// use std::rc::Rc;
+    ///
+    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
+    /// map.insert(Rc::new("Stringthing".to_string()), 15);
     ///
-    /// let mut map: HashMap<String, u32> = HashMap::new();
-    /// map.insert("poneyland".to_string(), 15);
+    /// let my_key = Rc::new("Stringthing".to_string());
     ///
-    /// if let Entry::Occupied(entry) = map.entry("poneyland".to_string()) {
-    ///     let (old_key, old_value): (String, u32) = entry.replace(16);
-    ///     assert_eq!(old_key, "poneyland");
-    ///     assert_eq!(old_value, 15);
+    /// if let Entry::Occupied(entry) = map.entry(my_key) {
+    ///     // Also replace the key with a handle to our other key.
+    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
     /// }
     ///
-    /// assert_eq!(map.get("poneyland"), Some(&16));
     /// ```
     #[unstable(feature = "map_entry_replace", issue = "44286")]
-    pub fn replace(mut self, value: V) -> (K, V) {
+    pub fn replace_entry(mut self, value: V) -> (K, V) {
         let (old_key, old_value) = self.elem.read_mut();
 
         let old_key = mem::replace(old_key, self.key.unwrap());
@@ -2268,6 +2269,37 @@ pub fn replace(mut self, value: V) -> (K, V) {
 
         (old_key, old_value)
     }
+
+    /// Replaces the key in the hash map with the key used to create this entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_replace)]
+    /// use std::collections::hash_map::{Entry, HashMap};
+    /// use std::rc::Rc;
+    ///
+    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
+    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
+    ///
+    /// // Initialise known strings, run program, etc.
+    ///
+    /// reclaim_memory(&mut map, &known_strings);
+    ///
+    /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
+    ///     for s in known_strings {
+    ///         if let Entry::Occupied(entry) = map.entry(s.clone()) {
+    ///             // Replaces the entry's key with our version of it in `known_strings`.
+    ///             entry.replace_key();
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "map_entry_replace", issue = "44286")]
+    pub fn replace_key(mut self) -> K {
+        let (old_key, _) = self.elem.read_mut();
+        mem::replace(old_key, self.key.unwrap())
+    }
 }
 
 impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
@@ -2461,9 +2493,7 @@ pub fn new() -> RandomState {
         // increment one of the seeds on every RandomState creation, giving
         // every corresponding HashMap a different iteration order.
         thread_local!(static KEYS: Cell<(u64, u64)> = {
-            let r = rand::OsRng::new();
-            let mut r = r.expect("failed to create an OS RNG");
-            Cell::new((r.gen(), r.gen()))
+            Cell::new(sys::hashmap_random_keys())
         });
 
         KEYS.with(|keys| {
index f81adad3ebebf1747578e982ab3fedb8bc021429..457c6e1409d3cf60628a18268c4558f548ee3274 100644 (file)
@@ -671,6 +671,10 @@ pub struct ArgsOs { inner: sys::args::Args }
 /// set to arbitrary text, and may not even exist. This means this property should
 /// not be relied upon for security purposes.
 ///
+/// On Unix systems shell usually expands unquoted arguments with glob patterns
+/// (such as `*` and `?`). On Windows this is not done, and such arguments are
+/// passed as-is.
+///
 /// # Panics
 ///
 /// The returned iterator will panic during iteration if any argument to the
index 0135cd0a588cf09e530499f3e4c60b571cbf62b2..7ec6124dfa4623548f43791f0e88304ad38b1de0 100644 (file)
@@ -23,6 +23,8 @@
 use intrinsics;
 #[cfg(not(test))]
 use num::FpCategory;
+#[cfg(not(test))]
+use sys::cmath;
 
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f32::consts;
 
-#[allow(dead_code)]
-mod cmath {
-    use libc::{c_float, c_int};
-
-    extern {
-        pub fn cbrtf(n: c_float) -> c_float;
-        pub fn erff(n: c_float) -> c_float;
-        pub fn erfcf(n: c_float) -> c_float;
-        pub fn expm1f(n: c_float) -> c_float;
-        pub fn fdimf(a: c_float, b: c_float) -> c_float;
-        pub fn fmodf(a: c_float, b: c_float) -> c_float;
-        pub fn ilogbf(n: c_float) -> c_int;
-        pub fn logbf(n: c_float) -> c_float;
-        pub fn log1pf(n: c_float) -> c_float;
-        pub fn modff(n: c_float, iptr: &mut c_float) -> c_float;
-        pub fn nextafterf(x: c_float, y: c_float) -> c_float;
-        pub fn tgammaf(n: c_float) -> c_float;
-
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgammaf_r")]
-        pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float;
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypotf")]
-        pub fn hypotf(x: c_float, y: c_float) -> c_float;
-    }
-
-    // See the comments in the `floor` function for why MSVC is special
-    // here.
-    #[cfg(not(target_env = "msvc"))]
-    extern {
-        pub fn acosf(n: c_float) -> c_float;
-        pub fn asinf(n: c_float) -> c_float;
-        pub fn atan2f(a: c_float, b: c_float) -> c_float;
-        pub fn atanf(n: c_float) -> c_float;
-        pub fn coshf(n: c_float) -> c_float;
-        pub fn sinhf(n: c_float) -> c_float;
-        pub fn tanf(n: c_float) -> c_float;
-        pub fn tanhf(n: c_float) -> c_float;
-    }
-
-    #[cfg(target_env = "msvc")]
-    pub use self::shims::*;
-    #[cfg(target_env = "msvc")]
-    mod shims {
-        use libc::c_float;
-
-        #[inline]
-        pub unsafe fn acosf(n: c_float) -> c_float {
-            f64::acos(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn asinf(n: c_float) -> c_float {
-            f64::asin(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float {
-            f64::atan2(n as f64, b as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn atanf(n: c_float) -> c_float {
-            f64::atan(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn coshf(n: c_float) -> c_float {
-            f64::cosh(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn sinhf(n: c_float) -> c_float {
-            f64::sinh(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn tanf(n: c_float) -> c_float {
-            f64::tan(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn tanhf(n: c_float) -> c_float {
-            f64::tanh(n as f64) as c_float
-        }
-    }
-}
-
 #[cfg(not(test))]
 #[lang = "f32"]
 impl f32 {
index d73d7cd2c7bd1cf52c088a0e45d45c4e5e688d84..e0f0acc6ac44136b808810900e13c9c749351974 100644 (file)
@@ -23,6 +23,8 @@
 use intrinsics;
 #[cfg(not(test))]
 use num::FpCategory;
+#[cfg(not(test))]
+use sys::cmath;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f64::consts;
 
-#[allow(dead_code)]
-mod cmath {
-    use libc::{c_double, c_int};
-
-    #[link_name = "m"]
-    extern {
-        pub fn acos(n: c_double) -> c_double;
-        pub fn asin(n: c_double) -> c_double;
-        pub fn atan(n: c_double) -> c_double;
-        pub fn atan2(a: c_double, b: c_double) -> c_double;
-        pub fn cbrt(n: c_double) -> c_double;
-        pub fn cosh(n: c_double) -> c_double;
-        pub fn erf(n: c_double) -> c_double;
-        pub fn erfc(n: c_double) -> c_double;
-        pub fn expm1(n: c_double) -> c_double;
-        pub fn fdim(a: c_double, b: c_double) -> c_double;
-        pub fn fmod(a: c_double, b: c_double) -> c_double;
-        pub fn frexp(n: c_double, value: &mut c_int) -> c_double;
-        pub fn ilogb(n: c_double) -> c_int;
-        pub fn ldexp(x: c_double, n: c_int) -> c_double;
-        pub fn logb(n: c_double) -> c_double;
-        pub fn log1p(n: c_double) -> c_double;
-        pub fn nextafter(x: c_double, y: c_double) -> c_double;
-        pub fn modf(n: c_double, iptr: &mut c_double) -> c_double;
-        pub fn sinh(n: c_double) -> c_double;
-        pub fn tan(n: c_double) -> c_double;
-        pub fn tanh(n: c_double) -> c_double;
-        pub fn tgamma(n: c_double) -> c_double;
-
-        // These are commonly only available for doubles
-
-        pub fn j0(n: c_double) -> c_double;
-        pub fn j1(n: c_double) -> c_double;
-        pub fn jn(i: c_int, n: c_double) -> c_double;
-
-        pub fn y0(n: c_double) -> c_double;
-        pub fn y1(n: c_double) -> c_double;
-        pub fn yn(i: c_int, n: c_double) -> c_double;
-
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgamma_r")]
-        pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double;
-
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypot")]
-        pub fn hypot(x: c_double, y: c_double) -> c_double;
-    }
-}
-
 #[cfg(not(test))]
 #[lang = "f64"]
 impl f64 {
index b54603919427c33bb812fa4f56e55061cf05a001..1aa47f066b69fc7f7177f929eaee2dc93933b3c5 100644 (file)
@@ -14,7 +14,6 @@
 use error::Error;
 use fmt::{self, Write};
 use io;
-use libc;
 use mem;
 use memchr;
 use ops;
@@ -22,6 +21,7 @@
 use ptr;
 use slice;
 use str::{self, Utf8Error};
+use sys;
 
 /// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
 /// middle.
@@ -404,7 +404,7 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
     /// ```
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
-        let len = libc::strlen(ptr) + 1; // Including the NUL byte
+        let len = sys::strlen(ptr) + 1; // Including the NUL byte
         let slice = slice::from_raw_parts_mut(ptr, len as usize);
         CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
     }
@@ -861,7 +861,7 @@ impl CStr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
-        let len = libc::strlen(ptr);
+        let len = sys::strlen(ptr);
         let ptr = ptr as *const u8;
         CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
     }
index 4ebd3554fd1428fc60f2854d7e1bc709fac70382..6d3fbc9d268222d3407b3e4cc8c3bbf43478da01 100644 (file)
@@ -147,6 +147,31 @@ pub fn get_ref(&self) -> &R { &self.inner }
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
+    /// Returns `true` if there are no bytes in the internal buffer.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(bufreader_is_empty)]
+    /// use std::io::BufReader;
+    /// use std::io::BufRead;
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let f1 = File::open("log.txt")?;
+    /// let mut reader = BufReader::new(f1);
+    /// assert!(reader.is_empty());
+    ///
+    /// if reader.fill_buf()?.len() > 0 {
+    ///     assert!(!reader.is_empty());
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+    pub fn is_empty(&self) -> bool {
+        self.pos == self.cap
+    }
+
     /// Unwraps this `BufReader`, returning the underlying reader.
     ///
     /// Note that any leftover data in the internal buffer is lost.
index fb489bf487b8bd66db3823874e67166c31f91d52..831688bb73d1cd49bb0528e3599101ddddf42bf6 100644 (file)
@@ -121,10 +121,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
-    use sys::stdio::EBADF_ERR;
-
     match r {
-        Err(ref e) if e.raw_os_error() == Some(EBADF_ERR) => Ok(default),
+        Err(ref e) if stdio::is_ebadf(e) => Ok(default),
         r => r
     }
 }
index 429153dc58b4cb8e5bdd53f038375e07204f3b8e..37cc7a49b527116f8aa807d6ec85a6fb93ab4b0a 100644 (file)
 
 // Access to Bencher, etc.
 #[cfg(test)] extern crate test;
+#[cfg(test)] extern crate rand;
 
 // We want to reexport a few macros from core but libcore has already been
 // imported by the compiler (via our #[no_std] attribute) In this case we just
                  debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
 extern crate core as __core;
 
-#[doc(masked)]
-#[allow(deprecated)]
-extern crate rand as core_rand;
 #[macro_use]
 #[macro_reexport(vec, format)]
 extern crate alloc;
 
 // Private support modules
 mod panicking;
-mod rand;
 mod memchr;
 
 // The runtime entry point and a few unstable public functions used by the
 // compiler
 pub mod rt;
 
-// Some external utilities of the standard library rely on randomness (aka
-// rustc_back::TempDir and tests) and need a way to get at the OS rng we've got
-// here. This module is not at all intended for stabilization as-is, however,
-// but it may be stabilized long-term. As a result we're exposing a hidden,
-// unstable module so we can get our build working.
-#[doc(hidden)]
-#[unstable(feature = "rand", issue = "27703")]
-pub mod __rand {
-    pub use rand::{thread_rng, ThreadRng, Rng};
-}
-
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
index 270878dc029c3d52fec5fb70a17b5e1e43fc4a15..69922470cff4a7072a69d8b5a3cf8bcf04fa9d01 100644 (file)
@@ -1690,11 +1690,11 @@ pub fn to_path_buf(&self) -> PathBuf {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     pub fn is_absolute(&self) -> bool {
-        if !cfg!(target_os = "redox") {
-            self.has_root() && (cfg!(unix) || self.prefix().is_some())
-        } else {
+        if cfg!(target_os = "redox") {
             // FIXME: Allow Redox prefixes
-            has_redox_scheme(self.as_u8_slice())
+            self.has_root() || has_redox_scheme(self.as_u8_slice())
+        } else {
+            self.has_root() && (cfg!(unix) || self.prefix().is_some())
         }
     }
 
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
deleted file mode 100644 (file)
index 8da070e..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Utilities for random number generation
-//!
-//! The key functions are `random()` and `Rng::gen()`. These are polymorphic
-//! and so can be used to generate any type that implements `Rand`. Type inference
-//! means that often a simple call to `rand::random()` or `rng.gen()` will
-//! suffice, but sometimes an annotation is required, e.g. `rand::random::<f64>()`.
-//!
-//! See the `distributions` submodule for sampling random numbers from
-//! distributions like normal and exponential.
-//!
-//! # Thread-local RNG
-//!
-//! There is built-in support for a RNG associated with each thread stored
-//! in thread-local storage. This RNG can be accessed via `thread_rng`, or
-//! used implicitly via `random`. This RNG is normally randomly seeded
-//! from an operating-system source of randomness, e.g. `/dev/urandom` on
-//! Unix systems, and will automatically reseed itself from this source
-//! after generating 32 KiB of random data.
-//!
-//! # Cryptographic security
-//!
-//! An application that requires an entropy source for cryptographic purposes
-//! must use `OsRng`, which reads randomness from the source that the operating
-//! system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
-//! The other random number generators provided by this module are not suitable
-//! for such purposes.
-//!
-//! *Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
-//! This module uses `/dev/urandom` for the following reasons:
-//!
-//! -   On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
-//!     This does not mean that `/dev/random` provides better output than
-//!     `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
-//!     number generator (CSPRNG) based on entropy pool for random number generation,
-//!     so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
-//!     However, this means that `/dev/urandom` can yield somewhat predictable randomness
-//!     if the entropy pool is very small, such as immediately after first booting.
-//!     Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
-//!     pool is not initialized yet, but it does not block once initialized.
-//!     `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD.
-//!     `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
-//!     If an application does not have `getrandom` and likely to be run soon after first booting,
-//!     or on a system with very few entropy sources, one should consider using `/dev/random` via
-//!     `ReaderRng`.
-//! -   On some systems (e.g. FreeBSD, OpenBSD and macOS) there is no difference
-//!     between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
-//!     and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
-
-#![unstable(feature = "rand", issue = "27703")]
-
-use cell::RefCell;
-use fmt;
-use io;
-use mem;
-use rc::Rc;
-use sys;
-
-#[cfg(target_pointer_width = "32")]
-use core_rand::IsaacRng as IsaacWordRng;
-#[cfg(target_pointer_width = "64")]
-use core_rand::Isaac64Rng as IsaacWordRng;
-
-pub use core_rand::{Rand, Rng, SeedableRng};
-pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
-pub use core_rand::reseeding;
-
-pub mod reader;
-
-/// The standard RNG. This is designed to be efficient on the current
-/// platform.
-#[derive(Copy, Clone)]
-pub struct StdRng {
-    rng: IsaacWordRng,
-}
-
-impl StdRng {
-    /// Create a randomly seeded instance of `StdRng`.
-    ///
-    /// This is a very expensive operation as it has to read
-    /// randomness from the operating system and use this in an
-    /// expensive seeding operation. If one is only generating a small
-    /// number of random numbers, or doesn't need the utmost speed for
-    /// generating each number, `thread_rng` and/or `random` may be more
-    /// appropriate.
-    ///
-    /// Reading the randomness from the OS may fail, and any error is
-    /// propagated via the `io::Result` return value.
-    pub fn new() -> io::Result<StdRng> {
-        OsRng::new().map(|mut r| StdRng { rng: r.gen() })
-    }
-}
-
-impl Rng for StdRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        self.rng.next_u32()
-    }
-
-    #[inline]
-    fn next_u64(&mut self) -> u64 {
-        self.rng.next_u64()
-    }
-}
-
-impl<'a> SeedableRng<&'a [usize]> for StdRng {
-    fn reseed(&mut self, seed: &'a [usize]) {
-        // the internal RNG can just be seeded from the above
-        // randomness.
-        self.rng.reseed(unsafe {mem::transmute(seed)})
-    }
-
-    fn from_seed(seed: &'a [usize]) -> StdRng {
-        StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
-    }
-}
-
-/// Controls how the thread-local RNG is reseeded.
-struct ThreadRngReseeder;
-
-impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
-    fn reseed(&mut self, rng: &mut StdRng) {
-        *rng = match StdRng::new() {
-            Ok(r) => r,
-            Err(e) => panic!("could not reseed thread_rng: {}", e)
-        }
-    }
-}
-const THREAD_RNG_RESEED_THRESHOLD: usize = 32_768;
-type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
-
-/// The thread-local RNG.
-#[derive(Clone)]
-pub struct ThreadRng {
-    rng: Rc<RefCell<ThreadRngInner>>,
-}
-
-impl fmt::Debug for ThreadRng {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("ThreadRng { .. }")
-    }
-}
-
-/// Retrieve the lazily-initialized thread-local random number
-/// generator, seeded by the system. Intended to be used in method
-/// chaining style, e.g. `thread_rng().gen::<isize>()`.
-///
-/// The RNG provided will reseed itself from the operating system
-/// after generating a certain amount of randomness.
-///
-/// The internal RNG used is platform and architecture dependent, even
-/// if the operating system random number generator is rigged to give
-/// the same sequence always. If absolute consistency is required,
-/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
-pub fn thread_rng() -> ThreadRng {
-    // used to make space in TLS for a random number generator
-    thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
-        let r = match StdRng::new() {
-            Ok(r) => r,
-            Err(e) => panic!("could not initialize thread_rng: {}", e)
-        };
-        let rng = reseeding::ReseedingRng::new(r,
-                                               THREAD_RNG_RESEED_THRESHOLD,
-                                               ThreadRngReseeder);
-        Rc::new(RefCell::new(rng))
-    });
-
-    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
-}
-
-impl Rng for ThreadRng {
-    fn next_u32(&mut self) -> u32 {
-        self.rng.borrow_mut().next_u32()
-    }
-
-    fn next_u64(&mut self) -> u64 {
-        self.rng.borrow_mut().next_u64()
-    }
-
-    #[inline]
-    fn fill_bytes(&mut self, bytes: &mut [u8]) {
-        self.rng.borrow_mut().fill_bytes(bytes)
-    }
-}
-
-/// A random number generator that retrieves randomness straight from
-/// the operating system. Platform sources:
-///
-/// - Unix-like systems (Linux, Android, macOS): read directly from
-///   `/dev/urandom`, or from `getrandom(2)` system call if available.
-/// - Windows: calls `CryptGenRandom`, using the default cryptographic
-///   service provider with the `PROV_RSA_FULL` type.
-/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
-/// - OpenBSD: uses the `getentropy(2)` system call.
-///
-/// This does not block.
-pub struct OsRng(sys::rand::OsRng);
-
-impl OsRng {
-    /// Create a new `OsRng`.
-    pub fn new() -> io::Result<OsRng> {
-        sys::rand::OsRng::new().map(OsRng)
-    }
-}
-
-impl Rng for OsRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        self.0.next_u32()
-    }
-
-    #[inline]
-    fn next_u64(&mut self) -> u64 {
-        self.0.next_u64()
-    }
-
-    #[inline]
-    fn fill_bytes(&mut self, bytes: &mut [u8]) {
-        self.0.fill_bytes(bytes)
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    use sync::mpsc::channel;
-    use rand::Rng;
-    use super::OsRng;
-    use thread;
-
-    #[test]
-    fn test_os_rng() {
-        let mut r = OsRng::new().unwrap();
-
-        r.next_u32();
-        r.next_u64();
-
-        let mut v = [0; 1000];
-        r.fill_bytes(&mut v);
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn test_os_rng_tasks() {
-
-        let mut txs = vec![];
-        for _ in 0..20 {
-            let (tx, rx) = channel();
-            txs.push(tx);
-
-            thread::spawn(move|| {
-                // wait until all the threads are ready to go.
-                rx.recv().unwrap();
-
-                // deschedule to attempt to interleave things as much
-                // as possible (XXX: is this a good test?)
-                let mut r = OsRng::new().unwrap();
-                thread::yield_now();
-                let mut v = [0; 1000];
-
-                for _ in 0..100 {
-                    r.next_u32();
-                    thread::yield_now();
-                    r.next_u64();
-                    thread::yield_now();
-                    r.fill_bytes(&mut v);
-                    thread::yield_now();
-                }
-            });
-        }
-
-        // start all the threads
-        for tx in &txs {
-            tx.send(()).unwrap();
-        }
-    }
-}
index 06fd838ea06d966b047f8e1a257d1acd253433cd..40b24cedcdcf587cca804b81fb41c9971ea859c7 100644 (file)
@@ -23,7 +23,6 @@
 #![doc(hidden)]
 
 
-
 // Reexport some of our utilities which are expected by other crates.
 pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 
index 5555f364e6e8d7fd74a88b7cb2f667cefb0f3bbd..6216d78528dbb779bbfc9ad2841e978456fb3502 100644 (file)
@@ -10,7 +10,6 @@
 
 use cell::UnsafeCell;
 use fmt;
-use marker;
 use mem;
 use ops::{Deref, DerefMut};
 use ptr;
@@ -102,7 +101,10 @@ pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
+impl<'a, T: ?Sized> !Send for RwLockReadGuard<'a, T> {}
+
+#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
+unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockReadGuard<'a, T> {}
 
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
@@ -121,7 +123,10 @@ pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {}
+impl<'a, T: ?Sized> !Send for RwLockWriteGuard<'a, T> {}
+
+#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
+unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockWriteGuard<'a, T> {}
 
 impl<T> RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
@@ -549,8 +554,6 @@ fn drop(&mut self) {
 
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
-    #![allow(deprecated)] // rand
-
     use rand::{self, Rng};
     use sync::mpsc::channel;
     use thread;
@@ -571,7 +574,7 @@ fn smoke() {
 
     #[test]
     fn frob() {
-        const N: usize = 10;
+        const N: u32 = 10;
         const M: usize = 1000;
 
         let r = Arc::new(RwLock::new(()));
index cfeabaddda9859fea27aa88a3da3da5d40d7d50d..0a174b3c3f58687b33d55a5769962d8f0491d823 100644 (file)
@@ -96,8 +96,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 
     if cx.idx < cx.frames.len() {
         cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr,
-            exact_position: ip,
+            symbol_addr: symaddr as *mut u8,
+            exact_position: ip as *mut u8,
         };
         cx.idx += 1;
     }
diff --git a/src/libstd/sys/redox/cmath.rs b/src/libstd/sys/redox/cmath.rs
new file mode 100644 (file)
index 0000000..2bc9665
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+#![cfg(not(test))]
+
+use libc::{c_float, c_double};
+
+#[link_name = "m"]
+extern {
+    pub fn acos(n: c_double) -> c_double;
+    pub fn acosf(n: c_float) -> c_float;
+    pub fn asin(n: c_double) -> c_double;
+    pub fn asinf(n: c_float) -> c_float;
+    pub fn atan(n: c_double) -> c_double;
+    pub fn atan2(a: c_double, b: c_double) -> c_double;
+    pub fn atan2f(a: c_float, b: c_float) -> c_float;
+    pub fn atanf(n: c_float) -> c_float;
+    pub fn cbrt(n: c_double) -> c_double;
+    pub fn cbrtf(n: c_float) -> c_float;
+    pub fn cosh(n: c_double) -> c_double;
+    pub fn coshf(n: c_float) -> c_float;
+    pub fn expm1(n: c_double) -> c_double;
+    pub fn expm1f(n: c_float) -> c_float;
+    pub fn fdim(a: c_double, b: c_double) -> c_double;
+    pub fn fdimf(a: c_float, b: c_float) -> c_float;
+    pub fn hypot(x: c_double, y: c_double) -> c_double;
+    pub fn hypotf(x: c_float, y: c_float) -> c_float;
+    pub fn log1p(n: c_double) -> c_double;
+    pub fn log1pf(n: c_float) -> c_float;
+    pub fn sinh(n: c_double) -> c_double;
+    pub fn sinhf(n: c_float) -> c_float;
+    pub fn tan(n: c_double) -> c_double;
+    pub fn tanf(n: c_float) -> c_float;
+    pub fn tanh(n: c_double) -> c_double;
+    pub fn tanhf(n: c_float) -> c_float;
+}
index fe4a89c6f3ebb5dc8aaf069a9ad221c5d94c22bb..2a611ed7dabbef50953c2a36975caf1a61410e81 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 use cell::UnsafeCell;
-use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg};
+use intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg};
 use ptr;
 use time::Duration;
 
 use sys::mutex::{mutex_unlock, Mutex};
-use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
+use sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
 
 pub struct Condvar {
     lock: UnsafeCell<*mut i32>,
@@ -63,33 +63,50 @@ pub fn notify_all(&self) {
     }
 
     #[inline]
-    pub fn wait(&self, mutex: &Mutex) {
-        unsafe {
-            let lock = self.lock.get();
-            let seq = self.seq.get();
-
-            if *lock != mutex.lock.get() {
-                if *lock != ptr::null_mut() {
-                    panic!("Condvar used with more than one Mutex");
-                }
+    unsafe fn wait_inner(&self, mutex: &Mutex, timeout_ptr: *const TimeSpec) -> bool {
+        let lock = self.lock.get();
+        let seq = self.seq.get();
 
-                atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize);
+        if *lock != mutex.lock.get() {
+            if *lock != ptr::null_mut() {
+                panic!("Condvar used with more than one Mutex");
             }
 
-            mutex_unlock(*lock);
+            atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize);
+        }
 
-            let _ = futex(seq, FUTEX_WAIT, *seq, 0, ptr::null_mut());
+        mutex_unlock(*lock);
 
-            while atomic_xchg(*lock, 2) != 0 {
-                let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
-            }
+        let seq_before = atomic_load(seq);
+
+        let _ = futex(seq, FUTEX_WAIT, seq_before, timeout_ptr as usize, ptr::null_mut());
+
+        let seq_after = atomic_load(seq);
+
+        while atomic_xchg(*lock, 2) != 0 {
+            let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
+        }
+
+        seq_before != seq_after
+    }
+
+    #[inline]
+    pub fn wait(&self, mutex: &Mutex) {
+        unsafe {
+            assert!(self.wait_inner(mutex, ptr::null()));
         }
     }
 
     #[inline]
-    pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
-        ::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n"));
-        unimplemented!();
+    pub fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        unsafe {
+            let timeout = TimeSpec {
+                tv_sec: dur.as_secs() as i64,
+                tv_nsec: dur.subsec_nanos() as i32
+            };
+
+            self.wait_inner(mutex, &timeout as *const TimeSpec)
+        }
     }
 
     #[inline]
index 918893097f8411d02f81854509df4e7fab00801d..3483477d40cf62981ecc9d404048048415bea288 100644 (file)
@@ -437,8 +437,7 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
 }
 
 pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    ::sys_common::util::dumb_print(format_args!("Link\n"));
-    unimplemented!();
+    Err(Error::from_raw_os_error(syscall::ENOSYS))
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
index 7c728ebb1af2e097f8d7889b9cf89f80a8d7ba10..4352b72c307735b40d55f4d8da879c706f325e89 100644 (file)
 
 use io::{self, ErrorKind};
 
+pub use libc::strlen;
+pub use self::rand::hashmap_random_keys;
+
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
+pub mod cmath;
 pub mod condvar;
 pub mod env;
 pub mod ext;
index eb28eca38bcd94a51015d281553d63d75f3b440f..3b378f53429ed7e914216209c912deb8b0f2408e 100644 (file)
@@ -8,50 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use io;
-use rand::Rng;
-
-// FIXME: Use rand:
-pub struct OsRng {
-    state: [u64; 2]
-}
-
-impl OsRng {
-    /// Create a new `OsRng`.
-    pub fn new() -> io::Result<OsRng> {
-        Ok(OsRng {
-            state: [0xBADF00D1, 0xDEADBEEF]
-        })
-    }
-}
-
-impl Rng for OsRng {
-    fn next_u32(&mut self) -> u32 {
-        self.next_u64() as u32
-    }
-    fn next_u64(&mut self) -> u64 {
-        // Store the first and second part.
-        let mut x = self.state[0];
-        let y = self.state[1];
-
-        // Put the second part into the first slot.
-        self.state[0] = y;
-        // Twist the first slot.
-        x ^= x << 23;
-        // Update the second slot.
-        self.state[1] = x ^ y ^ (x >> 17) ^ (y >> 26);
-
-        // Generate the final integer.
-        self.state[1].wrapping_add(y)
-
-    }
-    fn fill_bytes(&mut self, buf: &mut [u8]) {
-        for chunk in buf.chunks_mut(8) {
-            let mut rand: u64 = self.next_u64();
-            for b in chunk.iter_mut() {
-                *b = rand as u8;
-                rand = rand >> 8;
-            }
-        }
-    }
+pub fn hashmap_random_keys() -> (u64, u64) {
+    (0, 0)
 }
index c839531cc26c60838966fb8bc192bb96f46120db..3abb094ac34e3d98af5855f15bbb96f7e63d0982 100644 (file)
@@ -70,5 +70,8 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-pub const EBADF_ERR: i32 = ::sys::syscall::EBADF;
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(::sys::syscall::EBADF as i32)
+}
+
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
index 21f0b3724c13066883416d8eaf41e2f7278d1f0a..bc56fd6594ea6940369ecf5e9e4c4296477c0520 100644 (file)
@@ -22,7 +22,7 @@ pub fn resolve_symname<F>(frame: Frame,
 {
     unsafe {
         let mut info: Dl_info = intrinsics::init();
-        let symname = if dladdr(frame.exact_position, &mut info) == 0 ||
+        let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 ||
                          info.dli_sname.is_null() {
             None
         } else {
@@ -41,6 +41,5 @@ struct Dl_info {
 }
 
 extern {
-    fn dladdr(addr: *const libc::c_void,
-              info: *mut Dl_info) -> libc::c_int;
+    fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
 }
index 8bd2d9eccd82a73db84ee6662d4df33e2af8e192..caa60712b1d585bbc59111a3852d270d3aa28ef1 100644 (file)
@@ -20,7 +20,7 @@
 #[cfg(target_os = "emscripten")]
 pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
 where
-    F: FnMut(&[u8], ::libc::c_int) -> io::Result<()>
+    F: FnMut(&[u8], u32) -> io::Result<()>
 {
     Ok(false)
 }
index ecd32aa9462a904d5dea1ca929328892ed3dcebe..400d39cd4bdcbcb93334cf73479cc11b19433050 100644 (file)
@@ -36,8 +36,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
     } as usize;
     for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) {
         *to = Frame {
-            exact_position: *from,
-            symbol_addr: *from,
+            exact_position: *from as *mut u8,
+            symbol_addr: *from as *mut u8,
         };
     }
     Ok((nb_frames as usize, BacktraceContext))
index e3ffbe88acd45c2492d03e9c5eefb339e66efda4..000c08d2e0d198d33c81eb47eebf6f188a63ba3c 100644 (file)
@@ -96,8 +96,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 
     if cx.idx < cx.frames.len() {
         cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr,
-            exact_position: ip,
+            symbol_addr: symaddr as *mut u8,
+            exact_position: ip as *mut u8,
         };
         cx.idx += 1;
     }
diff --git a/src/libstd/sys/unix/cmath.rs b/src/libstd/sys/unix/cmath.rs
new file mode 100644 (file)
index 0000000..2bc9665
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+#![cfg(not(test))]
+
+use libc::{c_float, c_double};
+
+#[link_name = "m"]
+extern {
+    pub fn acos(n: c_double) -> c_double;
+    pub fn acosf(n: c_float) -> c_float;
+    pub fn asin(n: c_double) -> c_double;
+    pub fn asinf(n: c_float) -> c_float;
+    pub fn atan(n: c_double) -> c_double;
+    pub fn atan2(a: c_double, b: c_double) -> c_double;
+    pub fn atan2f(a: c_float, b: c_float) -> c_float;
+    pub fn atanf(n: c_float) -> c_float;
+    pub fn cbrt(n: c_double) -> c_double;
+    pub fn cbrtf(n: c_float) -> c_float;
+    pub fn cosh(n: c_double) -> c_double;
+    pub fn coshf(n: c_float) -> c_float;
+    pub fn expm1(n: c_double) -> c_double;
+    pub fn expm1f(n: c_float) -> c_float;
+    pub fn fdim(a: c_double, b: c_double) -> c_double;
+    pub fn fdimf(a: c_float, b: c_float) -> c_float;
+    pub fn hypot(x: c_double, y: c_double) -> c_double;
+    pub fn hypotf(x: c_float, y: c_float) -> c_float;
+    pub fn log1p(n: c_double) -> c_double;
+    pub fn log1pf(n: c_float) -> c_float;
+    pub fn sinh(n: c_double) -> c_double;
+    pub fn sinhf(n: c_float) -> c_float;
+    pub fn tan(n: c_double) -> c_double;
+    pub fn tanf(n: c_float) -> c_float;
+    pub fn tanh(n: c_double) -> c_double;
+    pub fn tanhf(n: c_float) -> c_float;
+}
index 3e631ad40ac7ff2713111e29ad459e77651b6fc9..2e17fd58e0a1e27658cd19377d5f0dbd0b780c72 100644 (file)
@@ -20,7 +20,9 @@
 use sys_common::{FromInner, AsInner, AsInnerMut};
 use sys::platform::fs::MetadataExt as UnixMetadataExt;
 
-/// Unix-specific extensions to `File`
+/// Unix-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
 #[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Reads a number of bytes starting from a given offset.
@@ -32,8 +34,28 @@ pub trait FileExt {
     ///
     /// The current file cursor is not affected by this function.
     ///
-    /// Note that similar to `File::read`, it is not an error to return with a
+    /// Note that similar to [`File::read`], it is not an error to return with a
     /// short read.
+    ///
+    /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::prelude::FileExt;
+    /// use std::fs::File;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let mut buf = [0u8; 8];
+    /// let file = File::open("foo.txt")?;
+    ///
+    /// // We now read 8 bytes from the offset 10.
+    /// let num_bytes_read = file.read_at(&mut buf, 10)?;
+    /// println!("read {} bytes: {:?}", num_bytes_read, buf);
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
@@ -49,8 +71,26 @@ pub trait FileExt {
     /// When writing beyond the end of the file, the file is appropriately
     /// extended and the intermediate bytes are initialized with the value 0.
     ///
-    /// Note that similar to `File::write`, it is not an error to return a
+    /// Note that similar to [`File::write`], it is not an error to return a
     /// short write.
+    ///
+    /// [`File::write`]: ../../../../std/fs/struct.File.html#write.v
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::prelude::FileExt;
+    /// use std::fs::File;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let file = File::open("foo.txt")?;
+    ///
+    /// // We now write at the offset 10.
+    /// file.write_at(b"sushi", 10)?;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 }
@@ -215,36 +255,282 @@ fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
 // casts and rely on manual lowering to `stat` if the raw type is desired.
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
+    /// Returns the ID of the device containing the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let dev_id = meta.dev();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn dev(&self) -> u64;
+    /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let inode = meta.ino();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ino(&self) -> u64;
+    /// Returns the rights applied to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let mode = meta.mode();
+    /// let user_has_write_access      = mode & 0o200;
+    /// let user_has_read_write_access = mode & 0o600;
+    /// let group_has_read_access      = mode & 0o040;
+    /// let others_have_exec_access    = mode & 0o001;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
+    /// Returns the number of hard links pointing to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nb_hard_links = meta.nlink();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn nlink(&self) -> u64;
+    /// Returns the user ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let user_id = meta.uid();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn uid(&self) -> u32;
+    /// Returns the group ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let group_id = meta.gid();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn gid(&self) -> u32;
+    /// Returns the device ID of this file (if it is a special one).
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let device_id = meta.rdev();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn rdev(&self) -> u64;
+    /// Returns the total size of this file in bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let file_size = meta.size();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn size(&self) -> u64;
+    /// Returns the time of the last access to the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_access_time = meta.atime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime(&self) -> i64;
+    /// Returns the time of the last access to the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_access_time = meta.atime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime_nsec(&self) -> i64;
+    /// Returns the time of the last modification of the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_modification_time = meta.mtime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime(&self) -> i64;
+    /// Returns the time of the last modification of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_modification_time = meta.mtime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime_nsec(&self) -> i64;
+    /// Returns the time of the last status change of the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_status_change_time = meta.ctime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime(&self) -> i64;
+    /// Returns the time of the last status change of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_status_change_time = meta.ctime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime_nsec(&self) -> i64;
+    /// Returns the blocksize for filesystem I/O.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let blocksize = meta.blksize();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn blksize(&self) -> u64;
+    /// Returns the number of blocks allocated to the file, in 512-byte units.
+    ///
+    /// Please note that this may be smaller than `st_size / 512` when the file has holes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let blocks = meta.blocks();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn blocks(&self) -> u64;
 }
@@ -269,19 +555,79 @@ fn blksize(&self) -> u64 { self.st_blksize() }
     fn blocks(&self) -> u64 { self.st_blocks() }
 }
 
-/// Add special unix types (block/char device, fifo and socket)
+/// Add support for special unix types (block/char device, fifo and socket).
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("block_device_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_block_device());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_block_device(&self) -> bool;
     /// Returns whether this file type is a char device.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("char_device_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_char_device());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_char_device(&self) -> bool;
     /// Returns whether this file type is a fifo.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("fifo_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_fifo());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_fifo(&self) -> bool;
     /// Returns whether this file type is a socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("unix.socket")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_socket());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_socket(&self) -> bool;
 }
@@ -294,7 +640,9 @@ fn is_fifo(&self) -> bool { self.as_inner().is(libc::S_IFIFO) }
     fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
 }
 
-/// Unix-specific extension methods for `fs::DirEntry`
+/// Unix-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
 pub trait DirEntryExt {
     /// Returns the underlying `d_ino` field in the contained `dirent`
@@ -354,7 +702,9 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
 }
 
 #[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for unix-specific options.
+/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
index c2772e2e2cc9a35e7317fbb326b22520b80bb82a..9bdea945ea42eacf52a993f91f6912bcbb675a08 100644 (file)
@@ -29,6 +29,9 @@
 #[cfg(all(not(dox), target_os = "fuchsia"))]   pub use os::fuchsia as platform;
 #[cfg(all(not(dox), target_os = "l4re"))]      pub use os::linux as platform;
 
+pub use self::rand::hashmap_random_keys;
+pub use libc::strlen;
+
 #[macro_use]
 pub mod weak;
 
@@ -36,6 +39,7 @@
 pub mod android;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
+pub mod cmath;
 pub mod condvar;
 pub mod env;
 pub mod ext;
index e2d40742c71360741ae65c4d73ad58f7ff4ca9e3..bbffe0f0ffe604b435df9afdf4aeb3cac510a98b 100644 (file)
@@ -8,20 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::imp::OsRng;
-
 use mem;
-
-fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 {
-    let mut buf: [u8; 4] = [0; 4];
-    fill_buf(&mut buf);
-    unsafe { mem::transmute::<[u8; 4], u32>(buf) }
-}
-
-fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
-    let mut buf: [u8; 8] = [0; 8];
-    fill_buf(&mut buf);
-    unsafe { mem::transmute::<[u8; 8], u64>(buf) }
+use slice;
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut v = (0, 0);
+    unsafe {
+        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8,
+                                             mem::size_of_val(&v));
+        imp::fill_bytes(view);
+    }
+    return v
 }
 
 #[cfg(all(unix,
@@ -30,14 +27,9 @@ fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
           not(target_os = "freebsd"),
           not(target_os = "fuchsia")))]
 mod imp {
-    use self::OsRngInner::*;
-    use super::{next_u32, next_u64};
-
     use fs::File;
-    use io;
+    use io::Read;
     use libc;
-    use rand::Rng;
-    use rand::reader::ReaderRng;
     use sys::os::errno;
 
     #[cfg(all(target_os = "linux",
@@ -81,7 +73,7 @@ fn getrandom(buf: &mut [u8]) -> libc::c_long {
                       target_arch = "s390x"))))]
     fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
 
-    fn getrandom_fill_bytes(v: &mut [u8]) {
+    fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
         let mut read = 0;
         while read < v.len() {
             let result = getrandom(&mut v[read..]);
@@ -90,18 +82,7 @@ fn getrandom_fill_bytes(v: &mut [u8]) {
                 if err == libc::EINTR {
                     continue;
                 } else if err == libc::EAGAIN {
-                    // if getrandom() returns EAGAIN it would have blocked
-                    // because the non-blocking pool (urandom) has not
-                    // initialized in the kernel yet due to a lack of entropy
-                    // the fallback we do here is to avoid blocking applications
-                    // which could depend on this call without ever knowing
-                    // they do and don't have a work around. The PRNG of
-                    // /dev/urandom will still be used but not over a completely
-                    // full entropy pool
-                    let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom");
-                    let mut reader_rng = ReaderRng::new(reader);
-                    reader_rng.fill_bytes(&mut v[read..]);
-                    read += v.len();
+                    return false
                 } else {
                     panic!("unexpected getrandom error: {}", err);
                 }
@@ -109,6 +90,8 @@ fn getrandom_fill_bytes(v: &mut [u8]) {
                 read += result as usize;
             }
         }
+
+        return true
     }
 
     #[cfg(all(target_os = "linux",
@@ -120,6 +103,7 @@ fn getrandom_fill_bytes(v: &mut [u8]) {
                   target_arch = "powerpc64",
                   target_arch = "s390x")))]
     fn is_getrandom_available() -> bool {
+        use io;
         use sync::atomic::{AtomicBool, Ordering};
         use sync::Once;
 
@@ -151,89 +135,37 @@ fn is_getrandom_available() -> bool {
                       target_arch = "s390x"))))]
     fn is_getrandom_available() -> bool { false }
 
-    pub struct OsRng {
-        inner: OsRngInner,
-    }
-
-    enum OsRngInner {
-        OsGetrandomRng,
-        OsReaderRng(ReaderRng<File>),
-    }
-
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            if is_getrandom_available() {
-                return Ok(OsRng { inner: OsGetrandomRng });
-            }
-
-            let reader = File::open("/dev/urandom")?;
-            let reader_rng = ReaderRng::new(reader);
-
-            Ok(OsRng { inner: OsReaderRng(reader_rng) })
+    pub fn fill_bytes(v: &mut [u8]) {
+        // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN,
+        // meaning it would have blocked because the non-blocking pool (urandom)
+        // has not initialized in the kernel yet due to a lack of entropy the
+        // fallback we do here is to avoid blocking applications which could
+        // depend on this call without ever knowing they do and don't have a
+        // work around.  The PRNG of /dev/urandom will still be used but not
+        // over a completely full entropy pool
+        if is_getrandom_available() && getrandom_fill_bytes(v) {
+            return
         }
-    }
 
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            match self.inner {
-                OsGetrandomRng => next_u32(&mut getrandom_fill_bytes),
-                OsReaderRng(ref mut rng) => rng.next_u32(),
-            }
-        }
-        fn next_u64(&mut self) -> u64 {
-            match self.inner {
-                OsGetrandomRng => next_u64(&mut getrandom_fill_bytes),
-                OsReaderRng(ref mut rng) => rng.next_u64(),
-            }
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            match self.inner {
-                OsGetrandomRng => getrandom_fill_bytes(v),
-                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
-            }
-        }
+        let mut file = File::open("/dev/urandom")
+            .expect("failed to open /dev/urandom");
+        file.read_exact(v).expect("failed to read /dev/urandom");
     }
 }
 
 #[cfg(target_os = "openbsd")]
 mod imp {
-    use super::{next_u32, next_u64};
-
-    use io;
     use libc;
     use sys::os::errno;
-    use rand::Rng;
-
-    pub struct OsRng {
-        // dummy field to ensure that this struct cannot be constructed outside
-        // of this module
-        _dummy: (),
-    }
-
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            Ok(OsRng { _dummy: () })
-        }
-    }
 
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            next_u32(&mut |v| self.fill_bytes(v))
-        }
-        fn next_u64(&mut self) -> u64 {
-            next_u64(&mut |v| self.fill_bytes(v))
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            // getentropy(2) permits a maximum buffer size of 256 bytes
-            for s in v.chunks_mut(256) {
-                let ret = unsafe {
-                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
-                };
-                if ret == -1 {
-                    panic!("unexpected getentropy error: {}", errno());
-                }
+    pub fn fill_bytes(v: &mut [u8]) {
+        // getentropy(2) permits a maximum buffer size of 256 bytes
+        for s in v.chunks_mut(256) {
+            let ret = unsafe {
+                libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
+            };
+            if ret == -1 {
+                panic!("unexpected getentropy error: {}", errno());
             }
         }
     }
@@ -241,18 +173,9 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
 
 #[cfg(target_os = "ios")]
 mod imp {
-    use super::{next_u32, next_u64};
-
     use io;
-    use ptr;
-    use rand::Rng;
     use libc::{c_int, size_t};
-
-    pub struct OsRng {
-        // dummy field to ensure that this struct cannot be constructed outside
-        // of this module
-        _dummy: (),
-    }
+    use ptr;
 
     enum SecRandom {}
 
@@ -261,79 +184,41 @@ enum SecRandom {}
 
     extern {
         fn SecRandomCopyBytes(rnd: *const SecRandom,
-                              count: size_t, bytes: *mut u8) -> c_int;
+                              count: size_t,
+                              bytes: *mut u8) -> c_int;
     }
 
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            Ok(OsRng { _dummy: () })
-        }
-    }
-
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            next_u32(&mut |v| self.fill_bytes(v))
-        }
-        fn next_u64(&mut self) -> u64 {
-            next_u64(&mut |v| self.fill_bytes(v))
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            let ret = unsafe {
-                SecRandomCopyBytes(kSecRandomDefault, v.len(),
-                                   v.as_mut_ptr())
-            };
-            if ret == -1 {
-                panic!("couldn't generate random bytes: {}",
-                       io::Error::last_os_error());
-            }
+    pub fn fill_bytes(v: &mut [u8]) {
+        let ret = unsafe {
+            SecRandomCopyBytes(kSecRandomDefault,
+                               v.len(),
+                               v.as_mut_ptr())
+        };
+        if ret == -1 {
+            panic!("couldn't generate random bytes: {}",
+                   io::Error::last_os_error());
         }
     }
 }
 
 #[cfg(target_os = "freebsd")]
 mod imp {
-    use super::{next_u32, next_u64};
-
-    use io;
     use libc;
-    use rand::Rng;
     use ptr;
 
-    pub struct OsRng {
-        // dummy field to ensure that this struct cannot be constructed outside
-        // of this module
-        _dummy: (),
-    }
-
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            Ok(OsRng { _dummy: () })
-        }
-    }
-
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            next_u32(&mut |v| self.fill_bytes(v))
-        }
-        fn next_u64(&mut self) -> u64 {
-            next_u64(&mut |v| self.fill_bytes(v))
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            let mib = [libc::CTL_KERN, libc::KERN_ARND];
-            // kern.arandom permits a maximum buffer size of 256 bytes
-            for s in v.chunks_mut(256) {
-                let mut s_len = s.len();
-                let ret = unsafe {
-                    libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
-                                 s.as_mut_ptr() as *mut _, &mut s_len,
-                                 ptr::null(), 0)
-                };
-                if ret == -1 || s_len != s.len() {
-                    panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
-                           ret, s.len(), s_len);
-                }
+    pub fn fill_bytes(v: &mut [u8]) {
+        let mib = [libc::CTL_KERN, libc::KERN_ARND];
+        // kern.arandom permits a maximum buffer size of 256 bytes
+        for s in v.chunks_mut(256) {
+            let mut s_len = s.len();
+            let ret = unsafe {
+                libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
+                             s.as_mut_ptr() as *mut _, &mut s_len,
+                             ptr::null(), 0)
+            };
+            if ret == -1 || s_len != s.len() {
+                panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
+                       ret, s.len(), s_len);
             }
         }
     }
@@ -341,11 +226,6 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
 
 #[cfg(target_os = "fuchsia")]
 mod imp {
-    use super::{next_u32, next_u64};
-
-    use io;
-    use rand::Rng;
-
     #[link(name = "zircon")]
     extern {
         fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
@@ -363,39 +243,18 @@ fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
         }
     }
 
-    pub struct OsRng {
-        // dummy field to ensure that this struct cannot be constructed outside
-        // of this module
-        _dummy: (),
-    }
-
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            Ok(OsRng { _dummy: () })
-        }
-    }
-
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            next_u32(&mut |v| self.fill_bytes(v))
-        }
-        fn next_u64(&mut self) -> u64 {
-            next_u64(&mut |v| self.fill_bytes(v))
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            let mut buf = v;
-            while !buf.is_empty() {
-                let ret = getrandom(buf);
-                match ret {
-                    Err(err) => {
-                        panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
-                            err, buf.len())
-                    }
-                    Ok(actual) => {
-                        let move_buf = buf;
-                        buf = &mut move_buf[(actual as usize)..];
-                    }
+    pub fn fill_bytes(v: &mut [u8]) {
+        let mut buf = v;
+        while !buf.is_empty() {
+            let ret = getrandom(buf);
+            match ret {
+                Err(err) => {
+                    panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
+                        err, buf.len())
+                }
+                Ok(actual) => {
+                    let move_buf = buf;
+                    buf = &mut move_buf[(actual as usize)..];
                 }
             }
         }
index 7a8fe25d98ee1307b0c3280c5ae2421d690081cf..e9b3d4affc7dd6fcb92505e96a99879529676a68 100644 (file)
@@ -70,5 +70,8 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-pub const EBADF_ERR: i32 = ::libc::EBADF as i32;
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(libc::EBADF as i32)
+}
+
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
index cc889454ce9d67e7ff7ec844c49e80dbdba4680f..9da33f5adac140a6db751515978e10a7dbdde9b8 100644 (file)
@@ -87,7 +87,7 @@ pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
         };
 
         extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
-            unsafe { start_thread(main); }
+            unsafe { start_thread(main as *mut u8); }
             ptr::null_mut()
         }
     }
index 26b4cb90e0a89c8f16536667eeb6b462d2894023..176891fff23f8fbcd3fb2d8f3234a3159dca921b 100644 (file)
@@ -95,8 +95,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
                frame.AddrReturn.Offset == 0 { break }
 
             frames[i] = Frame {
-                symbol_addr: (addr - 1) as *const c_void,
-                exact_position: (addr - 1) as *const c_void,
+                symbol_addr: (addr - 1) as *const u8,
+                exact_position: (addr - 1) as *const u8,
             };
             i += 1;
         }
index 3107d78432413ff04b2fbef9dfed39c0a010bceb..5a49b77af8e75a39c92d7b27a99e02d122c94cbd 100644 (file)
@@ -10,7 +10,7 @@
 
 use ffi::CStr;
 use io;
-use libc::{c_ulong, c_int, c_char};
+use libc::{c_ulong, c_char};
 use mem;
 use sys::c;
 use sys::backtrace::BacktraceContext;
@@ -59,7 +59,7 @@ pub fn foreach_symbol_fileline<F>(frame: Frame,
                                   mut f: F,
                                   context: &BacktraceContext)
     -> io::Result<bool>
-    where F: FnMut(&[u8], c_int) -> io::Result<()>
+    where F: FnMut(&[u8], u32) -> io::Result<()>
 {
     let SymGetLineFromAddr64 = sym!(&context.dbghelp,
                                     "SymGetLineFromAddr64",
@@ -76,7 +76,7 @@ pub fn foreach_symbol_fileline<F>(frame: Frame,
                                        &mut line);
         if ret == c::TRUE {
             let name = CStr::from_ptr(line.Filename).to_bytes();
-            f(name, line.LineNumber as c_int)?;
+            f(name, line.LineNumber as u32)?;
         }
         Ok(false)
     }
diff --git a/src/libstd/sys/windows/cmath.rs b/src/libstd/sys/windows/cmath.rs
new file mode 100644 (file)
index 0000000..b665a2c
--- /dev/null
@@ -0,0 +1,103 @@
+// 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.
+
+#![cfg(not(test))]
+
+use libc::{c_float, c_double};
+
+#[link_name = "m"]
+extern {
+    pub fn acos(n: c_double) -> c_double;
+    pub fn asin(n: c_double) -> c_double;
+    pub fn atan(n: c_double) -> c_double;
+    pub fn atan2(a: c_double, b: c_double) -> c_double;
+    pub fn cbrt(n: c_double) -> c_double;
+    pub fn cbrtf(n: c_float) -> c_float;
+    pub fn cosh(n: c_double) -> c_double;
+    pub fn expm1(n: c_double) -> c_double;
+    pub fn expm1f(n: c_float) -> c_float;
+    pub fn fdim(a: c_double, b: c_double) -> c_double;
+    pub fn fdimf(a: c_float, b: c_float) -> c_float;
+    #[cfg_attr(target_env = "msvc", link_name = "_hypot")]
+    pub fn hypot(x: c_double, y: c_double) -> c_double;
+    #[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
+    pub fn hypotf(x: c_float, y: c_float) -> c_float;
+    pub fn log1p(n: c_double) -> c_double;
+    pub fn log1pf(n: c_float) -> c_float;
+    pub fn sinh(n: c_double) -> c_double;
+    pub fn tan(n: c_double) -> c_double;
+    pub fn tanh(n: c_double) -> c_double;
+}
+
+pub use self::shims::*;
+
+#[cfg(not(target_env = "msvc"))]
+mod shims {
+    use libc::c_float;
+
+    extern {
+        pub fn acosf(n: c_float) -> c_float;
+        pub fn asinf(n: c_float) -> c_float;
+        pub fn atan2f(a: c_float, b: c_float) -> c_float;
+        pub fn atanf(n: c_float) -> c_float;
+        pub fn coshf(n: c_float) -> c_float;
+        pub fn sinhf(n: c_float) -> c_float;
+        pub fn tanf(n: c_float) -> c_float;
+        pub fn tanhf(n: c_float) -> c_float;
+    }
+}
+
+// On MSVC these functions aren't defined, so we just define shims which promote
+// everything fo f64, perform the calculation, and then demote back to f32.
+// While not precisely correct should be "correct enough" for now.
+#[cfg(target_env = "msvc")]
+mod shims {
+    use libc::c_float;
+
+    #[inline]
+    pub unsafe fn acosf(n: c_float) -> c_float {
+        f64::acos(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn asinf(n: c_float) -> c_float {
+        f64::asin(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float {
+        f64::atan2(n as f64, b as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn atanf(n: c_float) -> c_float {
+        f64::atan(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn coshf(n: c_float) -> c_float {
+        f64::cosh(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn sinhf(n: c_float) -> c_float {
+        f64::sinh(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn tanf(n: c_float) -> c_float {
+        f64::tan(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn tanhf(n: c_float) -> c_float {
+        f64::tanh(n as f64) as c_float
+    }
+}
index e7a9a121b25195ee0821ebc822816ba8021b5ddc..0d12ecf8fe3a1e12024088e54e202da0c2c8bd41 100644 (file)
 use path::PathBuf;
 use time::Duration;
 
+pub use libc::strlen;
+pub use self::rand::hashmap_random_keys;
+
 #[macro_use] pub mod compat;
 
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod c;
+pub mod cmath;
 pub mod condvar;
 #[cfg(feature = "backtrace")]
 pub mod dynamic_lib;
index 452d720ce59333055bbeb374df16ea38e3d6440f..f3b1185c6ea91d2532b3f88c32257d4afb85ccb5 100644 (file)
 use mem;
 use path::Path;
 use ptr;
-use rand::{self, Rng};
 use slice;
+use sync::atomic::Ordering::SeqCst;
+use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
 use sys::c;
 use sys::fs::{File, OpenOptions};
 use sys::handle::Handle;
+use sys::hashmap_random_keys;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
@@ -71,10 +73,9 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
         let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
         loop {
             tries += 1;
-            let key: u64 = rand::thread_rng().gen();
             name = format!(r"\\.\pipe\__rust_anonymous_pipe1__.{}.{}",
                            c::GetCurrentProcessId(),
-                           key);
+                           random_number());
             let wide_name = OsStr::new(&name)
                                   .encode_wide()
                                   .chain(Some(0))
@@ -156,6 +157,17 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
     }
 }
 
+fn random_number() -> usize {
+    static N: AtomicUsize = ATOMIC_USIZE_INIT;
+    loop {
+        if N.load(SeqCst) != 0 {
+            return N.fetch_add(1, SeqCst)
+        }
+
+        N.store(hashmap_random_keys().0 as usize, SeqCst);
+    }
+}
+
 impl AnonPipe {
     pub fn handle(&self) -> &Handle { &self.inner }
     pub fn into_handle(self) -> Handle { self.inner }
index f66b0a3bdc3f4d382a8e422d771b8b33593c97a1..262323656aa8ca01170ac7a7856cf38e7a37e898 100644 (file)
@@ -8,45 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use io;
 use mem;
-use rand::Rng;
 use sys::c;
 
-pub struct OsRng;
-
-impl OsRng {
-    /// Create a new `OsRng`.
-    pub fn new() -> io::Result<OsRng> {
-        Ok(OsRng)
-    }
-}
-
-impl Rng for OsRng {
-    fn next_u32(&mut self) -> u32 {
-        let mut v = [0; 4];
-        self.fill_bytes(&mut v);
-        unsafe { mem::transmute(v) }
-    }
-
-    fn next_u64(&mut self) -> u64 {
-        let mut v = [0; 8];
-        self.fill_bytes(&mut v);
-        unsafe { mem::transmute(v) }
-    }
-
-    fn fill_bytes(&mut self, v: &mut [u8]) {
-        // RtlGenRandom takes an ULONG (u32) for the length so we need to
-        // split up the buffer.
-        for slice in v.chunks_mut(<c::ULONG>::max_value() as usize) {
-            let ret = unsafe {
-                c::RtlGenRandom(slice.as_mut_ptr(), slice.len() as c::ULONG)
-            };
-            if ret == 0 {
-                panic!("couldn't generate random bytes: {}",
-                       io::Error::last_os_error());
-            }
-        }
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut v = (0, 0);
+    let ret = unsafe {
+        c::RtlGenRandom(&mut v as *mut _ as *mut u8,
+                        mem::size_of_val(&v) as c::ULONG)
+    };
+    if ret == 0 {
+        panic!("couldn't generate random bytes: {}",
+               io::Error::last_os_error());
     }
+    return v
 }
index b5e5b5760f21b9cddcbf70ec5e92b40c6f040a19..b43df20bddd087144faa8b3626de5a72efed7e67 100644 (file)
@@ -218,7 +218,10 @@ fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CO
 const CTRL_Z: u8 = 0x1A;
 const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A
 
-pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
+}
+
 // The default buffer capacity is 64k, but apparently windows
 // doesn't like 64k reads on stdin. See #13304 for details, but the
 // idea is that on windows we use a slightly smaller buffer that's
index c47baaa2434025fe4476fd8ac4b6dc3431c31dad..74786d092855f091d8b51e9d837d2040d72d1a29 100644 (file)
@@ -52,7 +52,7 @@ pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
         };
 
         extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
-            unsafe { start_thread(main); }
+            unsafe { start_thread(main as *mut u8); }
             0
         }
     }
index 8f78c2e6f59d7d384a701fa0fc6c573c1aa15583..9f0214f5f0510c8cc44280305c06755166cac6a0 100644 (file)
@@ -14,7 +14,6 @@
 use env;
 use io::prelude::*;
 use io;
-use libc;
 use str;
 use sync::atomic::{self, Ordering};
 use path::{self, Path};
@@ -39,9 +38,9 @@
 #[derive(Debug, Copy, Clone)]
 pub struct Frame {
     /// Exact address of the call that failed.
-    pub exact_position: *const libc::c_void,
+    pub exact_position: *const u8,
     /// Address of the enclosing function.
-    pub symbol_addr: *const libc::c_void,
+    pub symbol_addr: *const u8,
 }
 
 /// Max number of frames to print.
@@ -201,8 +200,10 @@ fn output(w: &mut Write, idx: usize, frame: Frame,
 ///
 /// See also `output`.
 #[allow(dead_code)]
-fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
-                       format: PrintFormat) -> io::Result<()> {
+fn output_fileline(w: &mut Write,
+                   file: &[u8],
+                   line: u32,
+                   format: PrintFormat) -> io::Result<()> {
     // prior line: "  ##: {:2$} - func"
     w.write_all(b"")?;
     match format {
index 016c840d1541afbe4dd70d46d967c23461b23530..75c6bd5d2a2ba46e73bc213f07f2783f8352fd1c 100644 (file)
 pub fn foreach_symbol_fileline<F>(frame: Frame,
                                   mut f: F,
                                   _: &BacktraceContext) -> io::Result<bool>
-where F: FnMut(&[u8], libc::c_int) -> io::Result<()>
+where F: FnMut(&[u8], u32) -> io::Result<()>
 {
     // pcinfo may return an arbitrary number of file:line pairs,
     // in the order of stack trace (i.e. inlined calls first).
     // in order to avoid allocation, we stack-allocate a fixed size of entries.
     const FILELINE_SIZE: usize = 32;
-    let mut fileline_buf = [(ptr::null(), -1); FILELINE_SIZE];
+    let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE];
     let ret;
     let fileline_count = {
         let state = unsafe { init_state() };
@@ -136,7 +136,7 @@ fn backtrace_pcinfo(state: *mut backtrace_state,
 // helper callbacks
 ////////////////////////////////////////////////////////////////////////
 
-type FileLine = (*const libc::c_char, libc::c_int);
+type FileLine = (*const libc::c_char, u32);
 
 extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
                    _errnum: libc::c_int) {
@@ -162,7 +162,7 @@ fn backtrace_pcinfo(state: *mut backtrace_state,
         // if the buffer is not full, add file:line to the buffer
         // and adjust the buffer for next possible calls to pcinfo_cb.
         if !buffer.is_empty() {
-            buffer[0] = (filename, lineno);
+            buffer[0] = (filename, lineno as u32);
             unsafe { ptr::write(slot, &mut buffer[1..]); }
         }
     }
index 87fb34a9dec06459f95806377a451db8bbc27648..c19424f295226cf7e075c6e15da232a39fd1eb23 100644 (file)
 
 use env;
 use alloc::boxed::FnBox;
-use libc;
 use sync::atomic::{self, Ordering};
 use sys::stack_overflow;
 use sys::thread as imp;
 
-pub unsafe fn start_thread(main: *mut libc::c_void) {
+pub unsafe fn start_thread(main: *mut u8) {
     // Next, set up our stack overflow handler which may get triggered if we run
     // out of stack.
     let _handler = stack_overflow::Handler::new();
index 28a33c7ec1465d04d70ae8e5624cab7b5099be86..ee49bf796b86f9d3da596c7c9d5ca85c58226a8a 100644 (file)
 //!
 //! Fatal logic errors in Rust cause *thread panic*, during which
 //! a thread will unwind the stack, running destructors and freeing
-//! owned resources. Thread panic is unrecoverable from within
-//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
-//! the panic may optionally be detected from a different thread. If
-//! the main thread panics, the application will exit with a non-zero
-//! exit code.
+//! owned resources. While not meant as a 'try/catch' mechanism, panics
+//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with
+//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered
+//! from, or alternatively be resumed with
+//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic
+//! is not caught the thread will exit, but the panic may optionally be
+//! detected from a different thread with [`join`]. If the main thread panics
+//! without the panic being caught, the application will exit with a
+//! non-zero exit code.
 //!
 //! When the main thread of a Rust program terminates, the entire program shuts
 //! down, even if other threads are still running. However, this module provides
index a69bf53ee14a3e1306553758b8694948a0e02936..b6cb3ac13081f462c731c2bc8bb1f4b1972881b2 100644 (file)
@@ -409,6 +409,9 @@ pub fn new() -> Features {
 
     // extern types
     (active, extern_types, "1.23.0", Some(43467)),
+
+    // Allow trait methods with arbitrary self types
+    (active, arbitrary_self_types, "1.23.0", Some(44874)),
 );
 
 declare_features! (
index 74a762f2f622cdf702840e9377fc3d46a39fb312..6564046ffe68f69d3720e683e8e0d863cb4267b7 100644 (file)
@@ -284,17 +284,17 @@ fn from_multispan(msp: &MultiSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
 
     fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
                        -> Vec<DiagnosticSpan> {
-        suggestion.substitution_parts
+        suggestion.substitutions
                       .iter()
                       .flat_map(|substitution| {
-                          substitution.substitutions.iter().map(move |suggestion| {
+                          substitution.parts.iter().map(move |suggestion| {
                               let span_label = SpanLabel {
-                                  span: substitution.span,
+                                  span: suggestion.span,
                                   is_primary: true,
                                   label: None,
                               };
                               DiagnosticSpan::from_span_label(span_label,
-                                                              Some(suggestion),
+                                                              Some(&suggestion.snippet),
                                                               je)
                           })
                       })
index 424f46840ad14ec5717cea439e0932bc998ced42..c1819307928ba0fe18af88ad93b43ebbdb1a4d94 100644 (file)
@@ -360,10 +360,6 @@ fn to_string(&self) -> String {
     }
 }
 
-fn is_ident_or_underscore(t: &token::Token) -> bool {
-    t.is_ident() || *t == token::Underscore
-}
-
 // Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
 // `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
 fn can_continue_type_after_ident(t: &token::Token) -> bool {
@@ -974,11 +970,12 @@ pub fn parse_seq_to_gt_or_return<T, F>(&mut self,
     pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
         let handler = self.diagnostic();
 
-        self.parse_seq_to_before_tokens(kets,
-                                        SeqSep::none(),
-                                        TokenExpectType::Expect,
-                                        |p| Ok(p.parse_token_tree()),
-                                        |mut e| handler.cancel(&mut e));
+        if let Err(ref mut err) = self.parse_seq_to_before_tokens(kets,
+                                                                  SeqSep::none(),
+                                                                  TokenExpectType::Expect,
+                                                                  |p| Ok(p.parse_token_tree())) {
+            handler.cancel(err);
+        }
     }
 
     /// Parse a sequence, including the closing delimiter. The function
@@ -991,7 +988,7 @@ pub fn parse_seq_to_end<T, F>(&mut self,
                                   -> PResult<'a, Vec<T>> where
         F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
     {
-        let val = self.parse_seq_to_before_end(ket, sep, f);
+        let val = self.parse_seq_to_before_end(ket, sep, f)?;
         self.bump();
         Ok(val)
     }
@@ -1003,22 +1000,19 @@ pub fn parse_seq_to_before_end<T, F>(&mut self,
                                          ket: &token::Token,
                                          sep: SeqSep,
                                          f: F)
-                                         -> Vec<T>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>
+                                         -> PResult<'a, Vec<T>>
+        where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
     {
-        self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f, |mut e| e.emit())
+        self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
     }
 
-    // `fe` is an error handler.
-    fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
+    fn parse_seq_to_before_tokens<T, F>(&mut self,
                                             kets: &[&token::Token],
                                             sep: SeqSep,
                                             expect: TokenExpectType,
-                                            mut f: F,
-                                            mut fe: Fe)
-                                            -> Vec<T>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
-              Fe: FnMut(DiagnosticBuilder)
+                                            mut f: F)
+                                            -> PResult<'a, Vec<T>>
+        where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
     {
         let mut first: bool = true;
         let mut v = vec![];
@@ -1031,14 +1025,14 @@ fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
                 if first {
                     first = false;
                 } else {
-                    if let Err(e) = self.expect(t) {
-                        fe(e);
+                    if let Err(mut e) = self.expect(t) {
                         // Attempt to keep parsing if it was a similar separator
                         if let Some(ref tokens) = t.similar_tokens() {
                             if tokens.contains(&self.token) {
                                 self.bump();
                             }
                         }
+                        e.emit();
                         // Attempt to keep parsing if it was an omitted separator
                         match f(self) {
                             Ok(t) => {
@@ -1062,16 +1056,11 @@ fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
                 break;
             }
 
-            match f(self) {
-                Ok(t) => v.push(t),
-                Err(e) => {
-                    fe(e);
-                    break;
-                }
-            }
+            let t = f(self)?;
+            v.push(t);
         }
 
-        v
+        Ok(v)
     }
 
     /// Parse a sequence, including the closing delimiter. The function
@@ -1086,7 +1075,7 @@ pub fn parse_unspanned_seq<T, F>(&mut self,
         F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
     {
         self.expect(bra)?;
-        let result = self.parse_seq_to_before_end(ket, sep, f);
+        let result = self.parse_seq_to_before_end(ket, sep, f)?;
         if self.token == *ket {
             self.bump();
         }
@@ -1105,7 +1094,7 @@ pub fn parse_seq<T, F>(&mut self,
     {
         let lo = self.span;
         self.expect(bra)?;
-        let result = self.parse_seq_to_before_end(ket, sep, f);
+        let result = self.parse_seq_to_before_end(ket, sep, f)?;
         let hi = self.span;
         self.bump();
         Ok(respan(lo.to(hi), result))
@@ -1551,7 +1540,7 @@ fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
         };
 
         let span = lo.to(self.prev_span);
-        let ty = Ty { node: node, span: span, id: ast::DUMMY_NODE_ID };
+        let ty = Ty { node, span, id: ast::DUMMY_NODE_ID };
 
         // Try to recover from use of `+` with incorrect priority.
         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
@@ -1632,23 +1621,19 @@ pub fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
         Ok(MutTy { ty: t, mutbl: mutbl })
     }
 
-    pub fn is_named_argument(&mut self) -> bool {
+    fn is_named_argument(&mut self) -> bool {
         let offset = match self.token {
-            token::BinOp(token::And) |
-            token::AndAnd => 1,
+            token::Interpolated(ref nt) => match nt.0 {
+                token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
+                _ => 0,
+            }
+            token::BinOp(token::And) | token::AndAnd => 1,
             _ if self.token.is_keyword(keywords::Mut) => 1,
-            _ => 0
+            _ => 0,
         };
 
-        debug!("parser is_named_argument offset:{}", offset);
-
-        if offset == 0 {
-            is_ident_or_underscore(&self.token)
-                && self.look_ahead(1, |t| *t == token::Colon)
-        } else {
-            self.look_ahead(offset, |t| is_ident_or_underscore(t))
-                && self.look_ahead(offset + 1, |t| *t == token::Colon)
-        }
+        self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
+        self.look_ahead(offset + 1, |t| t == &token::Colon)
     }
 
     /// This version of parse arg doesn't necessarily require
@@ -1868,8 +1853,11 @@ pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast:
         self.parse_path(style)
     }
 
-    fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle,
-                           enable_warning: bool) -> PResult<'a, ()> {
+    fn parse_path_segments(&mut self,
+                           segments: &mut Vec<PathSegment>,
+                           style: PathStyle,
+                           enable_warning: bool)
+                           -> PResult<'a, ()> {
         loop {
             segments.push(self.parse_path_segment(style, enable_warning)?);
 
@@ -1914,9 +1902,12 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
             } else {
                 // `(T, U) -> R`
                 self.bump(); // `(`
-                let inputs = self.parse_seq_to_end(&token::CloseDelim(token::Paren),
-                                                   SeqSep::trailing_allowed(token::Comma),
-                                                   |p| p.parse_ty())?;
+                let inputs = self.parse_seq_to_before_tokens(
+                    &[&token::CloseDelim(token::Paren)],
+                    SeqSep::trailing_allowed(token::Comma),
+                    TokenExpectType::Expect,
+                    |p| p.parse_ty())?;
+                self.bump(); // `)`
                 let output = if self.eat(&token::RArrow) {
                     Some(self.parse_ty_no_plus()?)
                 } else {
@@ -2784,10 +2775,11 @@ pub fn parse_assoc_expr_with(&mut self,
             if op.precedence() < min_prec {
                 break;
             }
-            // Warn about deprecated ... syntax (until SNAP)
-            if self.token == token::DotDotDot {
-                self.warn_dotdoteq(self.span);
+            // Check for deprecated `...` syntax
+            if self.token == token::DotDotDot && op == AssocOp::DotDotEq {
+                self.err_dotdotdot_syntax(self.span);
             }
+
             self.bump();
             if op.is_comparison() {
                 self.check_no_chained_comparison(&lhs, &op);
@@ -2820,7 +2812,6 @@ pub fn parse_assoc_expr_with(&mut self,
                 //
                 // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
                 // two variants are handled with `parse_prefix_range_expr` call above.
-                // (and `x...y`/`x...` until SNAP)
                 let rhs = if self.is_at_start_of_range_notation_rhs() {
                     Some(self.parse_assoc_expr_with(op.precedence() + 1,
                                                     LhsExpr::NotYetParsed)?)
@@ -3008,22 +2999,22 @@ fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) {
         }
     }
 
-    /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` (and `...expr` until SNAP)
+    /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr`
     fn parse_prefix_range_expr(&mut self,
                                already_parsed_attrs: Option<ThinVec<Attribute>>)
                                -> PResult<'a, P<Expr>> {
-        // SNAP remove DotDotDot
+        // Check for deprecated `...` syntax
+        if self.token == token::DotDotDot {
+            self.err_dotdotdot_syntax(self.span);
+        }
+
         debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token),
-                      "parse_prefix_range_expr: token {:?} is not DotDot/DotDotDot/DotDotEq",
+                      "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
                       self.token);
         let tok = self.token.clone();
         let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
         let lo = self.span;
         let mut hi = self.span;
-        // Warn about deprecated ... syntax (until SNAP)
-        if tok == token::DotDotDot {
-            self.warn_dotdoteq(self.span);
-        }
         self.bump();
         let opt_end = if self.is_at_start_of_range_notation_rhs() {
             // RHS must be parsed with more associativity than the dots.
@@ -3315,10 +3306,12 @@ pub fn parse_expr_res(&mut self, r: Restrictions,
     }
 
     /// Parse the RHS of a local variable declaration (e.g. '= 14;')
-    fn parse_initializer(&mut self) -> PResult<'a, Option<P<Expr>>> {
+    fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
         if self.check(&token::Eq) {
             self.bump();
             Ok(Some(self.parse_expr()?))
+        } else if skip_eq {
+            Ok(Some(self.parse_expr()?))
         } else {
             Ok(None)
         }
@@ -3725,12 +3718,56 @@ fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
         let lo = self.prev_span;
         let pat = self.parse_pat()?;
 
-        let ty = if self.eat(&token::Colon) {
-            Some(self.parse_ty()?)
+        let (err, ty) = if self.eat(&token::Colon) {
+            // Save the state of the parser before parsing type normally, in case there is a `:`
+            // instead of an `=` typo.
+            let parser_snapshot_before_type = self.clone();
+            let colon_sp = self.prev_span;
+            match self.parse_ty() {
+                Ok(ty) => (None, Some(ty)),
+                Err(mut err) => {
+                    // Rewind to before attempting to parse the type and continue parsing
+                    let parser_snapshot_after_type = self.clone();
+                    mem::replace(self, parser_snapshot_before_type);
+
+                    let snippet = self.sess.codemap().span_to_snippet(pat.span).unwrap();
+                    err.span_label(pat.span, format!("while parsing the type for `{}`", snippet));
+                    (Some((parser_snapshot_after_type, colon_sp, err)), None)
+                }
+            }
         } else {
-            None
+            (None, None)
+        };
+        let init = match (self.parse_initializer(err.is_some()), err) {
+            (Ok(init), None) => {  // init parsed, ty parsed
+                init
+            }
+            (Ok(init), Some((_, colon_sp, mut err))) => {  // init parsed, ty error
+                // Could parse the type as if it were the initializer, it is likely there was a
+                // typo in the code: `:` instead of `=`. Add suggestion and emit the error.
+                err.span_suggestion_short(colon_sp,
+                                          "use `=` if you meant to assign",
+                                          "=".to_string());
+                err.emit();
+                // As this was parsed successfuly, continue as if the code has been fixed for the
+                // rest of the file. It will still fail due to the emitted error, but we avoid
+                // extra noise.
+                init
+            }
+            (Err(mut init_err), Some((snapshot, _, ty_err))) => {  // init error, ty error
+                init_err.cancel();
+                // Couldn't parse the type nor the initializer, only raise the type error and
+                // return to the parser state before parsing the type as the initializer.
+                // let x: <parse_error>;
+                mem::replace(self, snapshot);
+                return Err(ty_err);
+            }
+            (Err(err), None) => {  // init error, ty parsed
+                // Couldn't parse the initializer and we're not attempting to recover a failed
+                // parse of the type, return the error.
+                return Err(err);
+            }
         };
-        let init = self.parse_initializer()?;
         let hi = if self.token == token::Semi {
             self.span
         } else {
@@ -4287,9 +4324,13 @@ fn warn_missing_semicolon(&self) {
         }).emit();
     }
 
-    fn warn_dotdoteq(&self, span: Span) {
-        self.diagnostic().struct_span_warn(span, {
-            "`...` is being replaced by `..=`"
+    fn err_dotdotdot_syntax(&self, span: Span) {
+        self.diagnostic().struct_span_err(span, {
+            "`...` syntax cannot be used in expressions"
+        }).help({
+            "Use `..` if you need an exclusive range (a < b)"
+        }).help({
+            "or `..=` if you need an inclusive range (a <= b)"
         }).emit();
     }
 
@@ -4797,14 +4838,14 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
             } else if self.eat(&token::Comma) {
                 let mut fn_inputs = vec![self_arg];
                 fn_inputs.append(&mut self.parse_seq_to_before_end(
-                    &token::CloseDelim(token::Paren), sep, parse_arg_fn)
+                    &token::CloseDelim(token::Paren), sep, parse_arg_fn)?
                 );
                 fn_inputs
             } else {
                 return self.unexpected();
             }
         } else {
-            self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
+            self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
         };
 
         // Parse closing paren and return type.
@@ -4827,9 +4868,8 @@ fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> {
                     &[&token::BinOp(token::Or), &token::OrOr],
                     SeqSep::trailing_allowed(token::Comma),
                     TokenExpectType::NoExpect,
-                    |p| p.parse_fn_block_arg(),
-                    |mut e| e.emit()
-                );
+                    |p| p.parse_fn_block_arg()
+                )?;
                 self.expect_or()?;
                 args
             }
index 09dc05a4167e61c558ab6884d422f2c5e7625960..f83343bf9afa51fe1785c2a0163699e3cc157467 100644 (file)
@@ -222,8 +222,8 @@ pub fn can_begin_expr(&self) -> bool {
             BinOp(Or) | OrOr                  | // closure
             BinOp(And)                        | // reference
             AndAnd                            | // double reference
+            // DotDotDot is no longer supported, but we need some way to display the error
             DotDot | DotDotDot | DotDotEq     | // range notation
-                // SNAP remove DotDotDot
             Lt | BinOp(Shl)                   | // associated path
             ModSep                            | // global path
             Pound                             => true, // expression attributes
index 227db93cf656e0196ee7af197b31b34df95c91e5..38627b40544f5a500c1eec64040c32c04fc92795 100644 (file)
@@ -1987,6 +1987,15 @@ fn print_expr_binary(&mut self,
             Fixity::None => (prec + 1, prec + 1),
         };
 
+        let left_prec = match (&lhs.node, op.node) {
+            // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
+            // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
+            // of `(x as i32) < ...`. We need to convince it _not_ to do that.
+            (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt) |
+            (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Shl) => parser::PREC_FORCE_PAREN,
+            _ => left_prec,
+        };
+
         self.print_expr_maybe_paren(lhs, left_prec)?;
         self.s.space()?;
         self.word_space(op.node.to_string())?;
@@ -2204,7 +2213,7 @@ fn print_expr_outer_attr_style(&mut self,
                 if limits == ast::RangeLimits::HalfOpen {
                     self.s.word("..")?;
                 } else {
-                    self.s.word("...")?;
+                    self.s.word("..=")?;
                 }
                 if let Some(ref e) = *end {
                     self.print_expr_maybe_paren(e, fake_prec)?;
index 590874806d7b5b1d7ade4780d8bc320eeb96ddd0..6014ec5aa92a5b36daac1cbf5a6349ee31bcdc6a 100644 (file)
@@ -106,7 +106,8 @@ pub fn from_token(t: &Token) -> Option<AssocOp> {
             Token::OrOr => Some(LOr),
             Token::DotDot => Some(DotDot),
             Token::DotDotEq => Some(DotDotEq),
-            Token::DotDotDot => Some(DotDotEq), // remove this after SNAP
+            // DotDotDot is no longer supported, but we need some way to display the error
+            Token::DotDotDot => Some(DotDotEq),
             Token::Colon => Some(Colon),
             _ if t.is_keyword(keywords::As) => Some(As),
             _ => None
index 63c533df198d0173239e67e0d202ba42b09d3dc5..ad5bd39a45341f4bda51a3b9724465eee60dc3cb 100644 (file)
@@ -110,6 +110,8 @@ struct Context<'a, 'b: 'a> {
     /// still existed in this phase of processing.
     /// Used only for `all_pieces_simple` tracking in `trans_piece`.
     curarg: usize,
+    /// Keep track of invalid references to positional arguments
+    invalid_refs: Vec<usize>,
 }
 
 /// Parses the arguments from the given list of tokens, returning None
@@ -226,7 +228,7 @@ fn verify_piece(&mut self, p: &parse::Piece) {
                 // argument second, if it's an implicit positional parameter
                 // it's written second, so it should come after width/precision.
                 let pos = match arg.position {
-                    parse::ArgumentIs(i) => Exact(i),
+                    parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => Exact(i),
                     parse::ArgumentNamed(s) => Named(s.to_string()),
                 };
 
@@ -251,23 +253,54 @@ fn verify_count(&mut self, c: parse::Count) {
 
     fn describe_num_args(&self) -> String {
         match self.args.len() {
-            0 => "no arguments given".to_string(),
+            0 => "no arguments were given".to_string(),
             1 => "there is 1 argument".to_string(),
             x => format!("there are {} arguments", x),
         }
     }
 
+    /// Handle invalid references to positional arguments. Output different
+    /// errors for the case where all arguments are positional and for when
+    /// there are named arguments or numbered positional arguments in the
+    /// format string.
+    fn report_invalid_references(&self, numbered_position_args: bool) {
+        let mut e;
+        let mut refs: Vec<String> = self.invalid_refs
+                                        .iter()
+                                        .map(|r| r.to_string())
+                                        .collect();
+
+        if self.names.is_empty() && !numbered_position_args {
+            e = self.ecx.mut_span_err(self.fmtsp,
+                &format!("{} positional argument{} in format string, but {}",
+                         self.pieces.len(),
+                         if self.pieces.len() > 1 { "s" } else { "" },
+                         self.describe_num_args()));
+        } else {
+            let arg_list = match refs.len() {
+                1 => format!("argument {}", refs.pop().unwrap()),
+                _ => format!("arguments {head} and {tail}",
+                             tail=refs.pop().unwrap(),
+                             head=refs.join(", "))
+            };
+
+            e = self.ecx.mut_span_err(self.fmtsp,
+                &format!("invalid reference to positional {} ({})",
+                        arg_list,
+                        self.describe_num_args()));
+            e.note("positional arguments are zero-based");
+        };
+
+        e.emit();
+    }
+
     /// Actually verifies and tracks a given format placeholder
     /// (a.k.a. argument).
     fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
         match arg {
             Exact(arg) => {
                 if self.args.len() <= arg {
-                    let msg = format!("invalid reference to argument `{}` ({})",
-                                      arg,
-                                      self.describe_num_args());
-
-                    self.ecx.span_err(self.fmtsp, &msg[..]);
+                    self.invalid_refs.push(arg);
                     return;
                 }
                 match ty {
@@ -403,7 +436,8 @@ fn trans_piece(&mut self,
                         }
                     };
                     match arg.position {
-                        parse::ArgumentIs(i) => {
+                        parse::ArgumentIs(i)
+                        | parse::ArgumentImplicitlyIs(i) => {
                             // Map to index in final generated argument array
                             // in case of multiple types specified
                             let arg_idx = match arg_index_consumed.get_mut(i) {
@@ -691,6 +725,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         all_pieces_simple: true,
         macsp,
         fmtsp: fmt.span,
+        invalid_refs: Vec::new(),
     };
 
     let fmt_str = &*fmt.node.0.as_str();
@@ -711,6 +746,18 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         }
     }
 
+    let numbered_position_args = pieces.iter().any(|arg: &parse::Piece| {
+        match *arg {
+            parse::String(_) => false,
+            parse::NextArgument(arg) => {
+                match arg.position {
+                    parse::Position::ArgumentIs(_) => true,
+                    _ => false,
+                }
+            }
+        }
+    });
+
     cx.build_index_map();
 
     let mut arg_index_consumed = vec![0usize; cx.arg_index_map.len()];
@@ -736,6 +783,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         cx.str_pieces.push(s);
     }
 
+    if cx.invalid_refs.len() >= 1 {
+        cx.report_invalid_references(numbered_position_args);
+    }
+
     // Make sure that all arguments were used and all arguments have types.
     let num_pos_args = cx.args.len() - cx.names.len();
     let mut errs = vec![];
index 26e6f27e20f40d5f7774d52c12bc8f19450bcc7e..69ddd560213778ac53e0ff871bd87de799f780b1 100644 (file)
@@ -416,7 +416,7 @@ fn interner_tests() {
         // first one is zero:
         assert_eq!(i.intern("dog"), Symbol(0));
         // re-use gets the same entry:
-        assert_eq!(i.intern ("dog"), Symbol(0));
+        assert_eq!(i.intern("dog"), Symbol(0));
         // different string gets a different #:
         assert_eq!(i.intern("cat"), Symbol(1));
         assert_eq!(i.intern("cat"), Symbol(1));
index e8a1242c8145f64bbac2d30a7369f4ceaeed8f78..76abcb83edc53665efd9706c2682a522cd823fde 100644 (file)
@@ -71,6 +71,7 @@
 use std::time::{Instant, Duration};
 
 const TEST_WARN_TIMEOUT_S: u64 = 60;
+const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode
 
 // to be used by rustc to compile tests in libtest
 pub mod test {
@@ -614,7 +615,14 @@ pub fn write_bench(&mut self) -> io::Result<()> {
     pub fn write_short_result(&mut self, verbose: &str, quiet: &str, color: term::color::Color)
                               -> io::Result<()> {
         if self.quiet {
-            self.write_pretty(quiet, color)
+            self.write_pretty(quiet, color)?;
+            if self.current_test_count() % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
+                // we insert a new line every 100 dots in order to flush the
+                // screen when dealing with line-buffered output (e.g. piping to
+                // `stamp` in the rust CI).
+                self.write_plain("\n")?;
+            }
+            Ok(())
         } else {
             self.write_pretty(verbose, color)?;
             self.write_plain("\n")
@@ -771,9 +779,12 @@ pub fn write_outputs(&mut self) -> io::Result<()> {
         Ok(())
     }
 
+    fn current_test_count(&self) -> usize {
+        self.passed + self.failed + self.ignored + self.measured + self.allowed_fail
+    }
+
     pub fn write_run_finish(&mut self) -> io::Result<bool> {
-        assert!(self.passed + self.failed + self.ignored + self.measured +
-                    self.allowed_fail == self.total);
+        assert!(self.current_test_count() == self.total);
 
         if self.options.display_output {
             self.write_outputs()?;
index 83b72cedfd7800ffc983d2855a85c5d06a545aa7..86c7a9985d0855255927d8653ea4d4407de8cc90 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 83b72cedfd7800ffc983d2855a85c5d06a545aa7
+Subproject commit 86c7a9985d0855255927d8653ea4d4407de8cc90
diff --git a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs
new file mode 100644 (file)
index 0000000..59b25d8
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// ignore-tidy-linelength
+// compile-flags:-Zprint-trans-items=lazy
+
+// NB: We do not expect *any* translation item to be generated here.
+
+#![feature(const_fn)]
+#![deny(dead_code)]
+#![crate_type = "rlib"]
+
+pub const fn foo(x: u32) -> u32 {
+    x + 0xf00
+}
diff --git a/src/test/codegen-units/item-collection/unreferenced-inline-function.rs b/src/test/codegen-units/item-collection/unreferenced-inline-function.rs
new file mode 100644 (file)
index 0000000..75d41a3
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// ignore-tidy-linelength
+// compile-flags:-Zprint-trans-items=lazy
+
+// NB: We do not expect *any* translation item to be generated here.
+
+#![deny(dead_code)]
+#![crate_type = "rlib"]
+
+#[inline]
+pub fn foo() -> bool {
+    [1, 2] == [3, 4]
+}
+
index 29528644ed0a055c714fe8ea7082e9dd27c7f46a..da96c5e183d79361a9c85938391b87ba00be6de7 100644 (file)
@@ -16,7 +16,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![allow(dead_code)]
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
-//~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[Internal]
-fn user()
+//~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
+pub fn user()
 {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
-mod mod1 {
+pub mod mod1 {
     use cgu_extern_drop_glue;
 
     struct LocalStruct(cgu_extern_drop_glue::Struct);
 
-    //~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[Internal]
-    fn user()
+    //~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
+    pub fn user()
     {
         //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
index 4bfd35b59bc120a7c20ad86f8ed4c1195d9f2422..01600c03ba2cd1af648ba940c07fa043934720c2 100644 (file)
@@ -35,10 +35,10 @@ pub fn user()
     cgu_explicit_inlining::never_inlined();
 }
 
-mod mod1 {
+pub mod mod1 {
     use cgu_explicit_inlining;
 
-    //~ TRANS_ITEM fn inlining_from_extern_crate::mod1[0]::user[0] @@ inlining_from_extern_crate-mod1[Internal]
+    //~ TRANS_ITEM fn inlining_from_extern_crate::mod1[0]::user[0] @@ inlining_from_extern_crate-mod1[External]
     pub fn user()
     {
         cgu_explicit_inlining::inlined();
@@ -48,10 +48,10 @@ pub fn user()
     }
 }
 
-mod mod2 {
+pub mod mod2 {
     use cgu_explicit_inlining;
 
-    //~ TRANS_ITEM fn inlining_from_extern_crate::mod2[0]::user[0] @@ inlining_from_extern_crate-mod2[Internal]
+    //~ TRANS_ITEM fn inlining_from_extern_crate::mod2[0]::user[0] @@ inlining_from_extern_crate-mod2[External]
     pub fn user()
     {
         cgu_explicit_inlining::always_inlined();
index 65e91343ccfcf2c957678d49949fb4f2be65ec3a..f7c05285ed63c7823e0c40ae2f965c2e5beb38db 100644 (file)
@@ -15,7 +15,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![allow(dead_code)]
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
 struct Struct {
@@ -32,8 +32,8 @@ struct Outer {
     _a: Struct
 }
 
-//~ TRANS_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[Internal]
-fn user()
+//~ TRANS_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[External]
+pub fn user()
 {
     let _ = Outer {
         _a: Struct {
@@ -42,7 +42,7 @@ fn user()
     };
 }
 
-mod mod1
+pub mod mod1
 {
     use super::Struct;
 
@@ -53,8 +53,8 @@ struct Struct2 {
         _b: (u32, Struct),
     }
 
-    //~ TRANS_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[Internal]
-    fn user()
+    //~ TRANS_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[External]
+    pub fn user()
     {
         let _ = Struct2 {
             _a: Struct { _a: 0 },
index 84464a627beb10906cd0500f17416439ada47010..cf197301eec16e151d7bd36fe9e7e5d2217e71fe 100644 (file)
@@ -27,28 +27,28 @@ pub fn inlined_function()
     }
 }
 
-mod user1 {
+pub mod user1 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining_but_not_all::user1[0]::foo[0] @@ local_inlining_but_not_all-user1[Internal]
-    fn foo() {
+    //~ TRANS_ITEM fn local_inlining_but_not_all::user1[0]::foo[0] @@ local_inlining_but_not_all-user1[External]
+    pub fn foo() {
         inline::inlined_function();
     }
 }
 
-mod user2 {
+pub mod user2 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining_but_not_all::user2[0]::bar[0] @@ local_inlining_but_not_all-user2[Internal]
-    fn bar() {
+    //~ TRANS_ITEM fn local_inlining_but_not_all::user2[0]::bar[0] @@ local_inlining_but_not_all-user2[External]
+    pub fn bar() {
         inline::inlined_function();
     }
 }
 
-mod non_user {
+pub mod non_user {
 
-    //~ TRANS_ITEM fn local_inlining_but_not_all::non_user[0]::baz[0] @@ local_inlining_but_not_all-non_user[Internal]
-    fn baz() {
+    //~ TRANS_ITEM fn local_inlining_but_not_all::non_user[0]::baz[0] @@ local_inlining_but_not_all-non_user[External]
+    pub fn baz() {
 
     }
 }
index f31761912412e270191e1707614cb658c8117a48..3502aa59fdccc48a20f59e062be8b246738e5af2 100644 (file)
@@ -28,28 +28,28 @@ pub fn inlined_function()
     }
 }
 
-mod user1 {
+pub mod user1 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining::user1[0]::foo[0] @@ local_inlining-user1[Internal]
-    fn foo() {
+    //~ TRANS_ITEM fn local_inlining::user1[0]::foo[0] @@ local_inlining-user1[External]
+    pub fn foo() {
         inline::inlined_function();
     }
 }
 
-mod user2 {
+pub mod user2 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining::user2[0]::bar[0] @@ local_inlining-user2[Internal]
-    fn bar() {
+    //~ TRANS_ITEM fn local_inlining::user2[0]::bar[0] @@ local_inlining-user2[External]
+    pub fn bar() {
         inline::inlined_function();
     }
 }
 
-mod non_user {
+pub mod non_user {
 
-    //~ TRANS_ITEM fn local_inlining::non_user[0]::baz[0] @@ local_inlining-non_user[Internal]
-    fn baz() {
+    //~ TRANS_ITEM fn local_inlining::non_user[0]::baz[0] @@ local_inlining-non_user[External]
+    pub fn baz() {
 
     }
 }
index bda76a8789f0f07790e6b9c20462627a584fb391..ed883954f3f40e35a5173ea6c0f14e11d52e6ac0 100644 (file)
@@ -15,7 +15,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![allow(dead_code)]
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 mod inline {
 
@@ -37,19 +37,19 @@ pub fn foo() {
     }
 }
 
-mod indirect_user {
+pub mod indirect_user {
     use super::direct_user;
 
-    //~ TRANS_ITEM fn local_transitive_inlining::indirect_user[0]::bar[0] @@ local_transitive_inlining-indirect_user[Internal]
-    fn bar() {
+    //~ TRANS_ITEM fn local_transitive_inlining::indirect_user[0]::bar[0] @@ local_transitive_inlining-indirect_user[External]
+    pub fn bar() {
         direct_user::foo();
     }
 }
 
-mod non_user {
+pub mod non_user {
 
-    //~ TRANS_ITEM fn local_transitive_inlining::non_user[0]::baz[0] @@ local_transitive_inlining-non_user[Internal]
-    fn baz() {
+    //~ TRANS_ITEM fn local_transitive_inlining::non_user[0]::baz[0] @@ local_transitive_inlining-non_user[External]
+    pub fn baz() {
 
     }
 }
index 8cbce12b52cad5256de4bbb35d33ebd722ab1360..12ef34441ff394c023837fb0c0a68c1ffa143d13 100644 (file)
@@ -13,7 +13,7 @@
 // incremental compilation
 // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/statics
 
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 //~ TRANS_ITEM static statics::FOO[0] @@ statics[Internal]
 static FOO: u32 = 0;
@@ -21,8 +21,8 @@
 //~ TRANS_ITEM static statics::BAR[0] @@ statics[Internal]
 static BAR: u32 = 0;
 
-//~ TRANS_ITEM fn statics::function[0] @@ statics[Internal]
-fn function() {
+//~ TRANS_ITEM fn statics::function[0] @@ statics[External]
+pub fn function() {
     //~ TRANS_ITEM static statics::function[0]::FOO[0] @@ statics[Internal]
     static FOO: u32 = 0;
 
@@ -30,15 +30,15 @@ fn function() {
     static BAR: u32 = 0;
 }
 
-mod mod1 {
+pub mod mod1 {
     //~ TRANS_ITEM static statics::mod1[0]::FOO[0] @@ statics-mod1[Internal]
     static FOO: u32 = 0;
 
     //~ TRANS_ITEM static statics::mod1[0]::BAR[0] @@ statics-mod1[Internal]
     static BAR: u32 = 0;
 
-    //~ TRANS_ITEM fn statics::mod1[0]::function[0] @@ statics-mod1[Internal]
-    fn function() {
+    //~ TRANS_ITEM fn statics::mod1[0]::function[0] @@ statics-mod1[External]
+    pub fn function() {
         //~ TRANS_ITEM static statics::mod1[0]::function[0]::FOO[0] @@ statics-mod1[Internal]
         static FOO: u32 = 0;
 
index bd85e303143485915a7531378f64ee2f8decbd6b..342a4f0d085c40c7bec87df2ce769ba709d050de 100644 (file)
@@ -15,7 +15,7 @@
 // Hack to get the correct size for the length part in slices
 // CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
 #[no_mangle]
-fn helper(_: usize) {
+pub fn helper(_: usize) {
 }
 
 // CHECK-LABEL: @no_op_slice_adjustment
index cc13d4a7b68d29572ff0bba14c99fdf6b63909b9..346c5da8d1b8dcc0ba55eca4ddd3ff4dc4ffe123 100644 (file)
 
 #![crate_type = "lib"]
 
-mod tests {
+pub mod tests {
     // CHECK: @f1(i32 inreg %arg0, i32 inreg %arg1, i32 %arg2)
     #[no_mangle]
-    extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
+    pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
 
     // CHECK: @f2(i32* inreg %arg0, i32* inreg %arg1, i32* %arg2)
     #[no_mangle]
-    extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
+    pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
 
     // CHECK: @f3(float %arg0, i32 inreg %arg1, i32 inreg %arg2, i32 %arg3)
     #[no_mangle]
-    extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
+    pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
 
     // CHECK: @f4(i32 inreg %arg0, float %arg1, i32 inreg %arg2, i32 %arg3)
     #[no_mangle]
-    extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
+    pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
 
     // CHECK: @f5(i64 %arg0, i32 %arg1)
     #[no_mangle]
-    extern "fastcall" fn f5(_: i64, _: i32) {}
+    pub extern "fastcall" fn f5(_: i64, _: i32) {}
 
     // CHECK: @f6(i1 inreg zeroext %arg0, i32 inreg %arg1, i32 %arg2)
     #[no_mangle]
-    extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
+    pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
 }
index d4c7fe9e80a1c7d1be448240fecd376c551ab1cf..29e2840c8817e9011f8ccad2e832f0ab6a9737c4 100644 (file)
@@ -93,20 +93,20 @@ pub fn struct_return() -> S {
 // Hack to get the correct size for the length part in slices
 // CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
 #[no_mangle]
-fn helper(_: usize) {
+pub fn helper(_: usize) {
 }
 
 // CHECK: @slice(i8* noalias nonnull readonly %arg0.ptr, [[USIZE]] %arg0.meta)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
-fn slice(_: &[u8]) {
+pub fn slice(_: &[u8]) {
 }
 
 // CHECK: @mutable_slice(i8* nonnull %arg0.ptr, [[USIZE]] %arg0.meta)
 // FIXME #25759 This should also have `nocapture`
 // ... there's this LLVM bug that forces us to not use noalias, see #29485
 #[no_mangle]
-fn mutable_slice(_: &mut [u8]) {
+pub fn mutable_slice(_: &mut [u8]) {
 }
 
 // CHECK: @unsafe_slice(%UnsafeInner* nonnull %arg0.ptr, [[USIZE]] %arg0.meta)
@@ -118,23 +118,23 @@ pub fn unsafe_slice(_: &[UnsafeInner]) {
 // CHECK: @str(i8* noalias nonnull readonly %arg0.ptr, [[USIZE]] %arg0.meta)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
-fn str(_: &[u8]) {
+pub fn str(_: &[u8]) {
 }
 
 // CHECK: @trait_borrow({}* nonnull, {}* noalias nonnull readonly)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
-fn trait_borrow(_: &Drop) {
+pub fn trait_borrow(_: &Drop) {
 }
 
 // CHECK: @trait_box({}* noalias nonnull, {}* noalias nonnull readonly)
 #[no_mangle]
-fn trait_box(_: Box<Drop>) {
+pub fn trait_box(_: Box<Drop>) {
 }
 
 // CHECK: { i16*, [[USIZE]] } @return_slice(i16* noalias nonnull readonly %x.ptr, [[USIZE]] %x.meta)
 #[no_mangle]
-fn return_slice(x: &[u16]) -> &[u16] {
+pub fn return_slice(x: &[u16]) -> &[u16] {
   x
 }
 
index 36602196cefebe38e3bcfcb2e9341f43a3896aa2..884cf59c1c192b02a1a5bce2efd6219daddc033c 100644 (file)
@@ -19,7 +19,7 @@ struct Zst { phantom: PhantomData<Zst> }
 // CHECK-LABEL: @mir
 // CHECK-NOT: store{{.*}}undef
 #[no_mangle]
-fn mir() {
+pub fn mir() {
     let x = Zst { phantom: PhantomData };
     let y = (x, 0);
     drop(y);
index 9883ca6b35d0497b297afff0da37e0f73582dd10..aab5f1bfb4f863825d67206ef1efd378688bbe0b 100644 (file)
 #![feature(naked_functions)]
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal void @naked_empty()
+// CHECK-NEXT: define void @naked_empty()
 #[no_mangle]
 #[naked]
-fn naked_empty() {
+pub fn naked_empty() {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: ret void
 }
@@ -27,8 +27,8 @@ fn naked_empty() {
 // CHECK: Function Attrs: naked uwtable
 #[no_mangle]
 #[naked]
-// CHECK-NEXT: define internal void @naked_with_args(i{{[0-9]+}})
-fn naked_with_args(a: isize) {
+// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+}})
+pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
@@ -36,20 +36,20 @@ fn naked_with_args(a: isize) {
 }
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_return()
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_return()
 #[no_mangle]
 #[naked]
-fn naked_with_return() -> isize {
+pub fn naked_with_return() -> isize {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: ret i{{[0-9]+}} 0
     0
 }
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
 #[no_mangle]
 #[naked]
-fn naked_with_args_and_return(a: isize) -> isize {
+pub fn naked_with_args_and_return(a: isize) -> isize {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
@@ -58,10 +58,10 @@ fn naked_with_args_and_return(a: isize) -> isize {
 }
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal void @naked_recursive()
+// CHECK-NEXT: define void @naked_recursive()
 #[no_mangle]
 #[naked]
-fn naked_recursive() {
+pub fn naked_recursive() {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: call void @naked_empty()
 
index fd1a14020d8102188522ce16f706feed7038d7d1..4b713e28b05253d2cc3527756ff3154761135c20 100644 (file)
@@ -15,7 +15,7 @@
 // Hack to get the correct size for the length part in slices
 // CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
 #[no_mangle]
-fn helper(_: usize) {
+pub fn helper(_: usize) {
 }
 
 // CHECK-LABEL: @ref_dst
diff --git a/src/test/codegen/unchecked-float-casts.rs b/src/test/codegen/unchecked-float-casts.rs
new file mode 100644 (file)
index 0000000..c2fc296
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+// This file tests that we don't generate any code for saturation if
+// -Z saturating-float-casts is not enabled.
+
+#![crate_type = "lib"]
+#![feature(i128_type)]
+
+// CHECK-LABEL: @f32_to_u32
+#[no_mangle]
+pub fn f32_to_u32(x: f32) -> u32 {
+    // CHECK: fptoui
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as u32
+}
+
+// CHECK-LABEL: @f32_to_i32
+#[no_mangle]
+pub fn f32_to_i32(x: f32) -> i32 {
+    // CHECK: fptosi
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as i32
+}
+
+#[no_mangle]
+pub fn f64_to_u16(x: f64) -> u16 {
+    // CHECK: fptoui
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as u16
+}
index 8c79c15e3de5bf8c053da24e8c126aa88c38c281..c2f610ecd2816aed6fbe3b0d5a16fb639abe39da 100644 (file)
@@ -10,6 +10,6 @@
 
 fn main() {
     let _: Box<std::io::Read + std::io::Write>;
-    //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object [E0225]
-    //~| NOTE non-Send/Sync additional trait
+    //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+    //~| NOTE non-auto additional trait
 }
index c285c4d9e00c1b342d806e03a107cab1e9f5e5ea..e125cc0c19c373deedf956e4151fd1e3edb407e1 100644 (file)
@@ -18,5 +18,6 @@
 //~^ ERROR E0259
 //~| NOTE `alloc` reimported here
 //~| NOTE `alloc` must be defined only once in the type namespace of this module
+//~| NOTE You can use `as` to change the binding name of the import
 
 fn main() {}
diff --git a/src/test/compile-fail/E0308-2.rs b/src/test/compile-fail/E0308-2.rs
deleted file mode 100644 (file)
index 8c9fc95..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::rc::Rc;
-
-struct Foo;
-
-impl Foo {
-    fn x(self: Rc<Foo>) {} //~ ERROR E0308
-}
-
-fn main() {
-}
index 8c036e6076d1d4c5d68d3619a1dd1ce05c6537de..fc465b268691eff7b7b8ee3af06b00f068cee75c 100644 (file)
@@ -11,4 +11,6 @@
 #[inline()] //~ ERROR E0534
 pub fn something() {}
 
-fn main() {}
+fn main() {
+    something();
+}
diff --git a/src/test/compile-fail/arbitrary-self-types-not-object-safe.rs b/src/test/compile-fail/arbitrary-self-types-not-object-safe.rs
new file mode 100644 (file)
index 0000000..6b10739
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+trait Foo {
+    fn foo(self: Rc<Self>) -> usize;
+}
+
+trait Bar {
+    fn foo(self: Rc<Self>) -> usize where Self: Sized;
+    fn bar(self: Box<Self>) -> usize;
+}
+
+impl Foo for usize {
+    fn foo(self: Rc<Self>) -> usize {
+        *self
+    }
+}
+
+impl Bar for usize {
+    fn foo(self: Rc<Self>) -> usize {
+        *self
+    }
+
+    fn bar(self: Box<Self>) -> usize {
+        *self
+    }
+}
+
+fn make_foo() {
+    let x = Box::new(5usize) as Box<Foo>;
+    //~^ ERROR E0038
+    //~| NOTE method `foo` has a non-standard `self` type
+    //~| NOTE the trait `Foo` cannot be made into an object
+    //~| ERROR E0038
+    //~| NOTE method `foo` has a non-standard `self` type
+    //~| NOTE the trait `Foo` cannot be made into an object
+    //~| NOTE requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<Foo>>`
+}
+
+fn make_bar() {
+    let x = Box::new(5usize) as Box<Bar>;
+    x.bar();
+}
+
+fn main() {}
index 285a77d6b657ae8bd35d012f2b320cab4441b2c2..5451a20d8166ff9838f28014984d01e22412711d 100644 (file)
@@ -30,7 +30,7 @@ fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
 {
     // x and y here have two distinct lifetimes:
     let z: I::A = if cond { x } else { y };
-    //~^ ERROR cannot infer
+    //~^ ERROR lifetime mismatch
 }
 
 pub fn main() {}
index 0e822aff01e877771ef084835c72736bec3aeacc..a5e8f4068e6619711695c6310fdc4a8de6fe96c5 100644 (file)
@@ -50,9 +50,10 @@ fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
 
 #[cfg(krisskross)] // two instantiations, mixing and matching: BAD
 fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
-   let a = bar(foo, y); //[krisskross]~ ERROR E0495
-   let b = bar(foo, x); //[krisskross]~ ERROR E0495
-   (a, b)
+   let a = bar(foo, y);
+   let b = bar(foo, x);
+   (a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623]
+   //[krisskross]~^ ERROR 55:8: 55:9: lifetime mismatch [E0623]
 }
 
 #[rustc_error]
index 10fe612980d34a114cd374250926afcfb66e39e5..6e4bdd4b21c79c310d45958e9085bdfdd99c8e2a 100644 (file)
@@ -45,8 +45,8 @@ fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
 #[cfg(oneuse)] // one instantiation: BAD
 fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
    let f = foo; // <-- No consistent type can be inferred for `f` here.
-   let a = bar(f, x); //[oneuse]~^ ERROR E0495
-   let b = bar(f, y);
+   let a = bar(f, x);
+   let b = bar(f, y); //[oneuse]~ ERROR 49:19: 49:20: lifetime mismatch [E0623]
    (a, b)
 }
 
@@ -60,9 +60,9 @@ fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
 
 #[cfg(krisskross)] // two instantiations, mixing and matching: BAD
 fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
-   let a = bar(foo, y); //[krisskross]~ ERROR E0495
-   let b = bar(foo, x); //[krisskross]~ ERROR E0495
-   (a, b)
+   let a = bar(foo, y); //[krisskross]~ ERROR E0623
+   let b = bar(foo, x);
+   (a, b) //[krisskross]~ ERROR E0623
 }
 
 #[rustc_error]
index ff872efb7bdb1049f44ecad65feb2ae398a59f9c..175102898759b1070569eb05d5e4768eb4f2bb49 100644 (file)
@@ -52,6 +52,24 @@ pub enum Enum {
 #[deprecated(since = "1.0.0", note = "text")]
 pub struct DeprecatedTupleStruct(pub isize);
 
+pub mod nested {
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedStruct {
+        pub i: isize
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedUnitStruct;
+
+    pub enum Enum {
+        #[deprecated(since = "1.0.0", note = "text")]
+        DeprecatedVariant,
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedTupleStruct(pub isize);
+}
+
 pub struct Stable {
     #[deprecated(since = "1.0.0", note = "text")]
     pub override2: u8,
index cfb64f80767678d250be0cca73e98468115ecd80..2fe94d43acdd1867b9ef7ec40d64911261c0b134 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(repr_simd, platform_intrinsics, core_intrinsics)]
 #![allow(warnings)]
+#![crate_type = "rlib"]
 
 // Bad monomorphizations could previously cause LLVM asserts even though the
 // error was caught in the compiler.
 use std::intrinsics;
 
 #[derive(Copy, Clone)]
-struct Foo(i64);
+pub struct Foo(i64);
 
-unsafe fn test_cttz(v: Foo) -> Foo {
+pub unsafe fn test_cttz(v: Foo) -> Foo {
     intrinsics::cttz(v)
     //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
+pub unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
     intrinsics::fadd_fast(a, b)
     //~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo`
 }
 
-unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
+pub unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
     simd_add(a, b)
     //~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
 }
-
-fn main() {}
index a2e2e5caafe6d0c408cd5a13d2ed7de8c43cb06d..df3da5096bf538d9d57639d729b92b178b0bbcb3 100644 (file)
@@ -12,7 +12,7 @@ trait Trait {}
 
 pub fn main() {
     let x: Vec<Trait + Sized> = Vec::new();
-    //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
+    //~^ ERROR only auto traits can be used as additional traits in a trait object
     //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
     //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
 }
index 0db7eaf0ca7c3ea5e319cef0aa266481ab1256d5..a501a5cd3ec4cc27197c58a54294d461301acd89 100644 (file)
@@ -12,6 +12,6 @@
 
 fn main() {
     let bar = 5;
-    //~^ ERROR let bindings cannot shadow unit structs
+    //~^ ERROR mismatched types
     use foo::bar;
 }
index 8bab6e8dfceac6f849fec7366cd1d302e34207e2..087ced01d8cda162100aea94c64a4b7793827f4c 100644 (file)
@@ -19,6 +19,6 @@ fn main()
     match Some(42) {
         Some(_) if { drop(my_str); false } => {}
         Some(_) => {}
-        None => { foo(my_str); } //~ ERROR (Mir) [E0381]
+        None => { foo(my_str); } //~ ERROR (Mir) [E0382]
     }
 }
index eee407472bf14c12342ce07bf4d20200f88dcfc4..af85e68f5debe8b628ec6a58a913179c8676c34d 100644 (file)
@@ -17,7 +17,7 @@ struct S<'a> {
 
 fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
     S { pointer: &mut *p.pointer }
-    //~^ ERROR cannot infer
+    //~^ ERROR lifetime mismatch
 }
 
 fn main() {
index 957086f6af13f5d394c82369033b53f89f294c3f..8f39ae6c04e43818f855f9d25b794c7eae24c482 100644 (file)
@@ -39,11 +39,11 @@ fn main() {
     let _moved = line1.origin;
     let _ = line1.origin.x + 1; //[ast]~ ERROR use of collaterally moved value: `line1.origin.x`
                                 //[mir]~^       [E0382]
-                                //[mir]~| (Mir) [E0381]
+                                //[mir]~| (Mir) [E0382]
 
     let mut line2 = Line::default();
     let _moved = (line2.origin, line2.middle);
     line2.consume(); //[ast]~ ERROR use of partially moved value: `line2` [E0382]
                      //[mir]~^       [E0382]
-                     //[mir]~| (Mir) [E0381]
+                     //[mir]~| (Mir) [E0382]
 }
diff --git a/src/test/compile-fail/const-pattern-irrefutable.rs b/src/test/compile-fail/const-pattern-irrefutable.rs
deleted file mode 100644 (file)
index 1100306..0000000
+++ /dev/null
@@ -1,29 +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.
-
-mod foo {
-    pub const b: u8 = 2;
-    pub const d: u8 = 2;
-}
-
-use foo::b as c; //~ NOTE is imported here
-use foo::d; //~ NOTE is imported here
-
-const a: u8 = 2; //~ NOTE is defined here
-
-fn main() {
-    let a = 4; //~ ERROR let bindings cannot shadow constants
-               //~^ NOTE cannot be named the same as a constant
-    let c = 4; //~ ERROR let bindings cannot shadow constants
-               //~^ NOTE cannot be named the same as a constant
-    let d = 4; //~ ERROR let bindings cannot shadow constants
-               //~^ NOTE cannot be named the same as a constant
-    fn f() {} // Check that the `NOTE`s still work with an item here (c.f. issue #35115).
-}
index edee24206cd33b43224ea900488cc962929912d8..a058234a64921c33c5c143514f6554bf6f3a514f 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:deprecation-lint.rs
+// ignore-tidy-linelength
 
 #![deny(deprecated)]
 #![allow(warnings)]
@@ -23,76 +24,86 @@ fn test() {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ ERROR use of deprecated item
-        foo.method_deprecated(); //~ ERROR use of deprecated item
-        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-
-        deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
-        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-
-        let _ = DeprecatedStruct { //~ ERROR use of deprecated item
-            i: 0 //~ ERROR use of deprecated item
+        deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated'
+        foo.method_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+
+        deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+
+        let _ = DeprecatedStruct { //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedStruct::i': text
         };
 
-        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedUnitStruct': text
 
-        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
+        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'deprecation_lint::Enum::DeprecatedVariant': text
 
-        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTupleStruct': text
+
+        let _ = nested::DeprecatedStruct { //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedStruct::i': text
+        };
+
+        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedUnitStruct': text
+
+        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'deprecation_lint::nested::Enum::DeprecatedVariant': text
+
+        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedTupleStruct': text
 
         // At the moment, the lint checker only checks stability in
         // in the arguments of macros.
         // Eventually, we will want to lint the contents of the
         // macro in the module *defining* it. Also, stability levels
         // on macros themselves are not yet linted.
-        macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text
-        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
+        macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
     }
 
     struct S;
 
-    impl DeprecatedTrait for S {} //~ ERROR use of deprecated item: text
-    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item: text
+    impl DeprecatedTrait for S {} //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTrait': text
 
     pub fn foo() {
         let x = Stable {
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
         };
 
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
 
         let Stable {
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
         } = x;
         // all fine
         let Stable { .. } = x;
@@ -100,56 +111,56 @@ pub fn foo() {
         let x = Stable2(1, 2, 3);
 
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Stable2::2': text
 
         let Stable2(_,
                    _,
                    _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Stable2::2': text
             = x;
         // all fine
         let Stable2(..) = x;
 
         let x = Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
             inherit: 1,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
         };
 
         let _ = x.inherit;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
 
         let Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
             inherit: _,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
         } = x;
 
         let Deprecated
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
             { .. } = x;
 
         let x = Deprecated2(1, 2, 3);
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
 
         let _ = x.0;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::0': text
         let _ = x.1;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::1': text
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::2': text
 
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
             (_,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::0': text
              _,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::1': text
              _)
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::2': text
             = x;
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
             // the patterns are all fine:
             (..) = x;
     }
@@ -159,7 +170,7 @@ mod inheritance {
     use deprecation_lint::*;
 
     fn test_inheritance() {
-        deprecated_mod::deprecated(); //~ ERROR use of deprecated item
+        deprecated_mod::deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_mod::deprecated': text
     }
 }
 
@@ -209,7 +220,27 @@ pub enum Enum {
     #[deprecated(since = "1.0.0", note = "text")]
     pub struct DeprecatedTupleStruct(isize);
 
+    mod nested {
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub struct DeprecatedStruct {
+            i: isize
+        }
+
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub struct DeprecatedUnitStruct;
+
+        pub enum Enum {
+            #[deprecated(since = "1.0.0", note = "text")]
+            DeprecatedVariant,
+        }
+
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub struct DeprecatedTupleStruct(pub isize);
+    }
+
     fn test() {
+        use self::nested;
+
         // Only the deprecated cases of the following should generate
         // errors, because other stability attributes now have meaning
         // only *across* crates, not within a single crate.
@@ -217,50 +248,61 @@ fn test() {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ ERROR use of deprecated item
-        foo.method_deprecated(); //~ ERROR use of deprecated item
-        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-
-        deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
-        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        deprecated(); //~ ERROR use of deprecated item 'this_crate::deprecated'
+        foo.method_deprecated(); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+
+        deprecated_text(); //~ ERROR use of deprecated item 'this_crate::deprecated_text': text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
 
         let _ = DeprecatedStruct {
-            //~^ ERROR use of deprecated item
-            i: 0 //~ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text
+        };
+
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+
+        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+
+        let _ = nested::DeprecatedStruct {
+            //~^ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
         };
 
-        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
+        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
 
-        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
+        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
 
-        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
+        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
     }
 
     #[deprecated(since = "1.0.0", note = "text")]
@@ -269,6 +311,14 @@ fn fn_in_body() {}
         fn_in_body();
     }
 
+    fn test_fn_closure_body() {
+        let _ = || {
+            #[deprecated]
+            fn bar() { }
+            bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar'
+        };
+    }
+
     impl MethodTester {
         #[deprecated(since = "1.0.0", note = "text")]
         fn test_method_body(&self) {
@@ -284,9 +334,9 @@ fn dummy(&self) { }
 
     struct S;
 
-    impl DeprecatedTrait for S { } //~ ERROR use of deprecated item
+    impl DeprecatedTrait for S { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
 
-    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item
+    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
 }
 
 mod this_crate2 {
@@ -312,15 +362,15 @@ struct Deprecated2(u8,
     pub fn foo() {
         let x = Stable {
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
         };
 
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
 
         let Stable {
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
         } = x;
         // all fine
         let Stable { .. } = x;
@@ -328,57 +378,57 @@ pub fn foo() {
         let x = Stable2(1, 2, 3);
 
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Stable2::2': text
 
         let Stable2(_,
                    _,
                    _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Stable2::2': text
             = x;
         // all fine
         let Stable2(..) = x;
 
         let x = Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
             inherit: 1,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
         };
 
         let _ = x.inherit;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
 
         let Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
             inherit: _,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
         } = x;
 
         let Deprecated
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
             // the patterns are all fine:
             { .. } = x;
 
         let x = Deprecated2(1, 2, 3);
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
 
         let _ = x.0;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::0': text
         let _ = x.1;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::1': text
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::2': text
 
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
             (_,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::0': text
              _,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::1': text
              _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::2': text
             = x;
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
             // the patterns are all fine:
             (..) = x;
     }
index 976a65589b86991ee7102d125361434a9f39da0a..1f19bd2f249b3f803acc102724dd557340270c96 100644 (file)
 #![crate_type="rlib"]
 #![allow(warnings)]
 
-mod a {
+pub mod a {
     #[no_mangle]
     pub extern fn fail() {
     }
 }
 
-mod b {
+pub mod b {
     #[no_mangle]
     pub extern fn fail() {
     //~^ symbol `fail` is already defined
diff --git a/src/test/compile-fail/feature-gate-arbitrary-self-types.rs b/src/test/compile-fail/feature-gate-arbitrary-self-types.rs
new file mode 100644 (file)
index 0000000..ff0306f
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::rc::Rc;
+
+trait Foo {
+    fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
+}
+
+impl Bar {
+    fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/float-int-invalid-const-cast.rs b/src/test/compile-fail/float-int-invalid-const-cast.rs
new file mode 100644 (file)
index 0000000..2efefd9
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(i128_type)]
+#![allow(const_err)] // this test is only about hard errors
+
+use std::{f32, f64};
+
+// Forces evaluation of constants, triggering hard error
+fn force<T>(_: T) {}
+
+fn main() {
+    { const X: u16 = -1. as u16; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = -100. as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f32::NAN as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = f32::NAN as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: u64 = f32::NAN as u64; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f32::NAN as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f32::INFINITY as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: u32 = f32::INFINITY as u32; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f32::INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f32::INFINITY as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: u8 = f32::NEG_INFINITY as u8; force(X); } //~ ERROR constant evaluation error
+    { const X: u16 = f32::NEG_INFINITY as u16; force(X); } //~ ERROR constant evaluation error
+    { const X: i64 = f32::NEG_INFINITY as i64; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f32::NEG_INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f64::NAN as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = f64::NAN as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: u64 = f64::NAN as u64; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f64::NAN as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f64::INFINITY as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: u32 = f64::INFINITY as u32; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f64::INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f64::INFINITY as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: u8 = f64::NEG_INFINITY as u8; force(X); } //~ ERROR constant evaluation error
+    { const X: u16 = f64::NEG_INFINITY as u16; force(X); } //~ ERROR constant evaluation error
+    { const X: i64 = f64::NEG_INFINITY as i64; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f64::NEG_INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: u8 = 256. as u8; force(X); } //~ ERROR constant evaluation error
+    { const X: i8 = -129. as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i8 = 128. as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = 2147483648. as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = -2147483904. as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: u32 = 4294967296. as u32; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = 1e40 as u128; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = 1e40 as i128; force(X); } //~ ERROR constant evaluation error
+}
\ No newline at end of file
index a23b4b077410c20dcdd0c45e3a36cf03cfbae29b..afe9bc152a36ce5321a5151388be59e7e628b8ff 100644 (file)
 fn main() {
     // bad arguments to the format! call
 
-    format!("{}");            //~ ERROR: invalid reference to argument
+    // bad number of arguments, see #44954 (originally #15780)
 
-    format!("{1}", 1);        //~ ERROR: invalid reference to argument `1`
-                            //~^ ERROR: argument never used
-    format!("{foo}");         //~ ERROR: no argument named `foo`
+    format!("{}");
+    //~^ ERROR: 1 positional argument in format string, but no arguments were given
 
-    format!("", 1, 2);                 //~ ERROR: multiple unused formatting arguments
-    format!("{}", 1, 2);               //~ ERROR: argument never used
-    format!("{1}", 1, 2);              //~ ERROR: argument never used
-    format!("{}", 1, foo=2);           //~ ERROR: named argument never used
-    format!("{foo}", 1, foo=2);        //~ ERROR: argument never used
-    format!("", foo=2);                //~ ERROR: named argument never used
+    format!("{1}", 1);
+    //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+    //~^^ ERROR: argument never used
 
-    format!("{foo}", foo=1, foo=2);    //~ ERROR: duplicate argument
-    format!("", foo=1, 2);             //~ ERROR: positional arguments cannot follow
-
-    // bad number of arguments, see #15780
-
-    format!("{0}");
-    //~^ ERROR invalid reference to argument `0` (no arguments given)
+    format!("{} {}");
+    //~^ ERROR: 2 positional arguments in format string, but no arguments were given
 
     format!("{0} {1}", 1);
-    //~^ ERROR invalid reference to argument `1` (there is 1 argument)
+    //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
 
     format!("{0} {1} {2}", 1, 2);
-    //~^ ERROR invalid reference to argument `2` (there are 2 arguments)
-
-    format!("{0} {1}");
-    //~^ ERROR invalid reference to argument `0` (no arguments given)
-    //~^^ ERROR invalid reference to argument `1` (no arguments given)
+    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+
+    format!("{} {value} {} {}", 1, value=2);
+    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+    format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+    //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+
+    format!("{} {foo} {} {bar} {}", 1, 2, 3);
+    //~^ ERROR: there is no argument named `foo`
+    //~^^ ERROR: there is no argument named `bar`
+
+    format!("{foo}");                //~ ERROR: no argument named `foo`
+    format!("", 1, 2);               //~ ERROR: multiple unused formatting arguments
+    format!("{}", 1, 2);             //~ ERROR: argument never used
+    format!("{1}", 1, 2);            //~ ERROR: argument never used
+    format!("{}", 1, foo=2);         //~ ERROR: named argument never used
+    format!("{foo}", 1, foo=2);      //~ ERROR: argument never used
+    format!("", foo=2);              //~ ERROR: named argument never used
+    format!("{} {}", 1, 2, foo=1, bar=2);  //~ ERROR: multiple unused formatting arguments
+
+    format!("{foo}", foo=1, foo=2);  //~ ERROR: duplicate argument
+    format!("", foo=1, 2);           //~ ERROR: positional arguments cannot follow
 
     // bad named arguments, #35082
 
index ad89087d660201ab865620e0ce76aae566c95b6c..93b985b4fb063d9d27d9a422c1fbf0370461476f 100644 (file)
@@ -21,4 +21,8 @@ fn b() {
 fn c() {
 }
 
-fn main() {}
+fn main() {
+    a();
+    b();
+    c();
+}
index ed1634441498be40d5a05f98c51f2c5b8019a02c..590f8073a1a0d33fd1a46f2a02cab905fa36a571 100644 (file)
@@ -22,7 +22,7 @@ fn iter(&'r self) -> Range<usize> {
 fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
 {
     let cont_iter = cont.iter();
-//~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
+//~^ ERROR 24:26: 24:30: explicit lifetime required in the type of `cont` [E0621]
     let result = cont_iter.fold(Some(0), |state, val| {
         state.map_or(None, |mask| {
             let bit = 1 << val;
index 3a5df9e805bdb7e3c066ea9123f96fb55afca95f..dceecee6ca74b0ad6fee883032889bf00a70c502 100644 (file)
@@ -19,7 +19,7 @@ impl Foo for A {}
 struct B<'a>(&'a (Foo+'a));
 
 fn foo<'a>(a: &Foo) -> B<'a> {
-    B(a)    //~ ERROR cannot infer an appropriate lifetime
+    B(a)    //~ ERROR 22:5: 22:9: explicit lifetime required in the type of `a` [E0621]
 }
 
 fn main() {
index 69e10b90bfeba917a6e89378512172d9d93fcb19..a62e46820d3cb1cc64c14d7e3fecea811835c2b2 100644 (file)
@@ -25,7 +25,7 @@ struct Parser<'a> {
 impl<'a> Parser<'a> {
     pub fn new(lexer: &'a mut Lexer) -> Parser<'a> {
         Parser { lexer: lexer }
-        //~^ ERROR cannot infer an appropriate lifetime
+        //~^ ERROR 27:25: 27:30: explicit lifetime required in the type of `lexer` [E0621]
     }
 }
 
index 9724d17bef1eaf446e77c95e0a0d7b59975fe0e1..8516a8ea52e42ddbefb5860043aad9f85781f488 100644 (file)
@@ -21,9 +21,9 @@ trait TraversesWorld {
     fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
         let direction = str_to_direction(directionStr);
         let maybe_room = room.direction_to_room.get(&direction);
-        //~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
         match maybe_room {
             Some(entry) => Ok(entry),
+            //~^ ERROR 25:28: 25:37: lifetime mismatch [E0623]
             _ => Err("Direction does not exist in room.")
         }
     }
index 664d62e87ae61cf2f61a5f45d308275ce6f60856..1d5ef4360dc1ebc9134451f2cdd0b70eab6c7f66 100644 (file)
@@ -15,12 +15,12 @@ struct Foo<'a> {
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
     //~^ mismatched method receiver
-    //~| expected type `&mut Foo<'a>`
-    //~| found type `&mut Foo<'_>`
+    //~| expected type `Foo<'a>`
+    //~| found type `Foo<'_>`
     //~| lifetime mismatch
     //~| mismatched method receiver
-    //~| expected type `&mut Foo<'a>`
-    //~| found type `&mut Foo<'_>`
+    //~| expected type `Foo<'a>`
+    //~| found type `Foo<'_>`
     //~| lifetime mismatch
     }
 }
index eb5c6076440e9c0eee559bf3dec87f1e558ad77d..914a3bd79d4602db7cf9c9aa93cd657103b9edb8 100644 (file)
@@ -23,6 +23,6 @@
             //~| NOTE missing reference to `RHS`
             //~| NOTE because of the default `Self` reference, type parameters must be specified on object types
             //~| ERROR E0225
-            //~| NOTE non-Send/Sync additional trait
+            //~| NOTE non-auto additional trait
 
 fn main() { }
index 65d1d837d7dc3ea9685487617ef40dda2ddf0668..53b0d9f4e9f0ceda022d7453d727e7c2e1459e2a 100644 (file)
@@ -12,6 +12,7 @@
 
 #![recursion_limit = "20"]
 #![type_length_limit = "20000000"]
+#![crate_type = "rlib"]
 
 #[derive(Clone)]
 struct A (B);
@@ -66,5 +67,3 @@ pub fn matches<F: Fn()>(&self, f: &F) {
 pub fn matches() {
     A(B::Variant1).matches(&(|| ()))
 }
-
-fn main() {}
index ef91188c5d166bd1d8de2e11c18a3a82517627f2..7ddd56229ceb772c0a7dd04864b905949a000e92 100644 (file)
@@ -12,7 +12,7 @@
 
 impl S {
     fn f(self: *mut S) -> String { self.0 }
-    //~^ ERROR mismatched method receiver
+    //~^ ERROR invalid `self` type
 }
 
 fn main() { S("".to_owned()).f(); }
index 5f55c550aeb3979de774361b0d5f1df0ebabe703..519e9d06d1b33c1c4558ed19b86f534aa03cce6a 100644 (file)
@@ -13,7 +13,7 @@ struct thing<'a, Q:'a> {
 }
 
 fn thing<'a,Q>(x: &Q) -> thing<'a,Q> {
-    thing{ x: x } //~ ERROR cannot infer
+    thing{ x: x } //~ ERROR 16:5: 16:18: explicit lifetime required in the type of `x` [E0621]
 }
 
 fn main() {
index f146cfbe68b9631f50540cd022caa2c588095100..e97e5a86a9d7d88567f4fd8249ddf996e9d83ddd 100644 (file)
@@ -16,6 +16,6 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
 
 fn main() {
     size_of_copy::<Misc+Copy>();
-    //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
+    //~^ ERROR only auto traits can be used as additional traits in a trait object
     //~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
 }
index bc78d20745a54b96064a6e45cf0a04f2a201257f..1e1994357c77ad3fa29ce96988188b36d63ca809 100644 (file)
@@ -14,6 +14,6 @@
 
 fn main() {
     || {
-        let Test = 1; //~ ERROR let bindings cannot shadow unit structs
+        let Test = 1; //~ ERROR mismatched types
     };
 }
index c1e8cb8b6defb231e9594736b31ae80165decbf8..e16a7ecf6b9087982ec09aa1a31fd79264d0a34c 100644 (file)
@@ -12,12 +12,12 @@ fn prove_static<T: 'static + ?Sized>(_: &'static T) {}
 
 fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
     let mut out = [x];
-    //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
     {
         let slice: &mut [_] = &mut out;
         slice[0] = y;
     }
     out[0]
+    //~^ ERROR 19:5: 19:11: explicit lifetime required in the type of `y` [E0621]
 }
 
 struct Struct<T, U: ?Sized> {
@@ -27,12 +27,12 @@ struct Struct<T, U: ?Sized> {
 
 fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
     let mut out = Struct { head: x, _tail: [()] };
-    //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
     {
         let dst: &mut Struct<_, [()]> = &mut out;
         dst.head = y;
     }
     out.head
+    //~^ ERROR 34:5: 34:13: explicit lifetime required in the type of `y` [E0621]
 }
 
 fn main() {
diff --git a/src/test/compile-fail/issue-45087-unreachable-unsafe.rs b/src/test/compile-fail/issue-45087-unreachable-unsafe.rs
new file mode 100644 (file)
index 0000000..eeb66fa
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+fn main() {
+    return;
+    *(1 as *mut u32) = 42;
+    //~^ ERROR dereference of raw pointer requires unsafe
+}
diff --git a/src/test/compile-fail/issue-45729-unsafe-in-generator.rs b/src/test/compile-fail/issue-45729-unsafe-in-generator.rs
new file mode 100644 (file)
index 0000000..489e917
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators)]
+
+fn main() {
+    let _ = || {
+        *(1 as *mut u32) = 42;
+        //~^ ERROR dereference of raw pointer requires unsafe
+        yield;
+    };
+}
index ef072d4bbb3916f424f6f69ade886c88938f5f26..8dc46558cb0d5ee6f427f9d895ab72309a204628 100644 (file)
 
 extern crate lint_output_format;
 use lint_output_format::{foo, bar};
-//~^ WARNING use of deprecated item: text
+//~^ WARNING use of deprecated item 'lint_output_format::foo': text
 //~| NOTE #[warn(deprecated)] on by default
 
 #[rustc_error]
 fn main() { //~ ERROR: compilation successful
     let _x = foo();
-    //~^ WARNING use of deprecated item: text
+    //~^ WARNING use of deprecated item 'lint_output_format::foo': text
     //~| NOTE #[warn(deprecated)] on by default
     let _y = bar();
 }
index 9bc2c021904aad24dee2886f8a9cf2b8db797e5a..df5c3dddcde321a6e0d3163fe38179031a047f29 100644 (file)
@@ -12,6 +12,7 @@
 // aux-build:inherited_stability.rs
 // aux-build:stability_cfg1.rs
 // aux-build:stability_cfg2.rs
+// ignore-tidy-linelength
 
 #![warn(deprecated)]
 #![allow(dead_code, unused_extern_crates)]
@@ -32,41 +33,41 @@ fn test() {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ WARN use of deprecated item
-        foo.method_deprecated(); //~ WARN use of deprecated item
-        Foo::method_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item
-        foo.trait_deprecated(); //~ WARN use of deprecated item
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
-
-        deprecated_text(); //~ WARN use of deprecated item: text
-        foo.method_deprecated_text(); //~ WARN use of deprecated item: text
-        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-
-        deprecated_unstable(); //~ WARN use of deprecated item
-        foo.method_deprecated_unstable(); //~ WARN use of deprecated item
-        Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item
-        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
-
-        deprecated_unstable_text(); //~ WARN use of deprecated item: text
-        foo.method_deprecated_unstable_text(); //~ WARN use of deprecated item: text
-        Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
-        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text
-        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        deprecated(); //~ WARN use of deprecated item 'lint_stability::deprecated'
+        foo.method_deprecated(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+
+        deprecated_text(); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
+        foo.method_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+
+        deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable'
+        foo.method_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
+        Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
+        <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+
+        deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable_text': text
+        foo.method_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+        Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+        <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
 
         unstable();
         foo.method_unstable();
@@ -106,30 +107,30 @@ fn test() {
 
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
-        //~^ WARN use of deprecated item
+        //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
 
-        let _ = DeprecatedStruct { //~ WARN use of deprecated item
-            i: 0 //~ WARN use of deprecated item
+        let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
+            i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i'
         };
         let _ = DeprecatedUnstableStruct {
-            //~^ WARN use of deprecated item
-            i: 0 //~ WARN use of deprecated item
+            //~^ WARN use of deprecated item 'lint_stability::DeprecatedUnstableStruct'
+            i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i'
         };
         let _ = UnstableStruct { i: 0 };
         let _ = StableStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item
-        let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated item
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item 'lint_stability::DeprecatedUnitStruct'
+        let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct'
         let _ = UnstableUnitStruct;
         let _ = StableUnitStruct;
 
-        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item
-        let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated item
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item 'lint_stability::Enum::DeprecatedVariant'
+        let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant'
         let _ = Enum::UnstableVariant;
         let _ = Enum::StableVariant;
 
-        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item
-        let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated item
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item 'lint_stability::DeprecatedTupleStruct'
+        let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct'
         let _ = UnstableTupleStruct (1);
         let _ = StableTupleStruct (1);
 
@@ -138,28 +139,28 @@ fn test() {
         // Eventually, we will want to lint the contents of the
         // macro in the module *defining* it. Also, stability levels
         // on macros themselves are not yet linted.
-        macro_test_arg!(deprecated_text()); //~ WARN use of deprecated item: text
-        macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated item: text
-        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated item: text
+        macro_test_arg!(deprecated_text()); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
+        macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable_text': text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item
-        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
-        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text
-        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -175,10 +176,10 @@ fn test_method_param<Foo: Trait>(foo: Foo) {
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
-        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item
-        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_stable();
@@ -187,9 +188,9 @@ fn test_method_object(foo: &Trait) {
     struct S;
 
     impl UnstableTrait for S { }
-    impl DeprecatedTrait for S {} //~ WARN use of deprecated item: text
+    impl DeprecatedTrait for S {} //~ WARN use of deprecated item 'lint_stability::DeprecatedTrait': text
     trait LocalTrait : UnstableTrait { }
-    trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated item: text
+    trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated item 'lint_stability::DeprecatedTrait': text
 
     impl Trait for S {
         fn trait_stable(&self) {}
@@ -208,7 +209,7 @@ fn test_inheritance() {
         stable_mod::unstable();
         stable_mod::stable();
 
-        unstable_mod::deprecated(); //~ WARN use of deprecated item
+        unstable_mod::deprecated(); //~ WARN use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
         unstable_mod::unstable();
 
         let _ = Unstable::UnstableVariant;
@@ -330,23 +331,23 @@ fn test() {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ WARN use of deprecated item
-        foo.method_deprecated(); //~ WARN use of deprecated item
-        Foo::method_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item
-        foo.trait_deprecated(); //~ WARN use of deprecated item
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
-
-        deprecated_text(); //~ WARN use of deprecated item: text
-        foo.method_deprecated_text(); //~ WARN use of deprecated item: text
-        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        deprecated(); //~ WARN use of deprecated item 'this_crate::deprecated'
+        foo.method_deprecated(); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+
+        deprecated_text(); //~ WARN use of deprecated item 'this_crate::deprecated_text': text
+        foo.method_deprecated_text(); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
 
         unstable();
         foo.method_unstable();
@@ -385,34 +386,34 @@ fn test() {
         <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct {
-            //~^ WARN use of deprecated item
-            i: 0 //~ WARN use of deprecated item
+            //~^ WARN use of deprecated item 'this_crate::DeprecatedStruct'
+            i: 0 //~ WARN use of deprecated item 'this_crate::DeprecatedStruct::i'
         };
         let _ = UnstableStruct { i: 0 };
         let _ = StableStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item 'this_crate::DeprecatedUnitStruct'
         let _ = UnstableUnitStruct;
         let _ = StableUnitStruct;
 
-        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item 'this_crate::Enum::DeprecatedVariant'
         let _ = Enum::UnstableVariant;
         let _ = Enum::StableVariant;
 
-        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item 'this_crate::DeprecatedTupleStruct'
         let _ = UnstableTupleStruct (1);
         let _ = StableTupleStruct (1);
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -428,8 +429,8 @@ fn test_method_param<Foo: Trait>(foo: Foo) {
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_stable();
@@ -439,7 +440,7 @@ fn test_method_object(foo: &Trait) {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
-        fn_in_body(); //~ WARN use of deprecated item: text
+        fn_in_body(); //~ WARN use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
     }
 
     impl MethodTester {
@@ -447,7 +448,7 @@ impl MethodTester {
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
-            fn_in_body(); //~ WARN use of deprecated item: text
+            fn_in_body(); //~ WARN use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
         }
     }
 
@@ -459,9 +460,9 @@ fn dummy(&self) { }
 
     struct S;
 
-    impl DeprecatedTrait for S { } //~ WARN use of deprecated item
+    impl DeprecatedTrait for S { } //~ WARN use of deprecated item 'this_crate::DeprecatedTrait'
 
-    trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated item
+    trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated item 'this_crate::DeprecatedTrait'
 }
 
 #[rustc_error] fn main() {} //~ ERROR: compilation successful
diff --git a/src/test/compile-fail/name-clash-nullary.rs b/src/test/compile-fail/name-clash-nullary.rs
deleted file mode 100644 (file)
index bfcb0f4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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 std::option::*;
-
-fn main() {
-  let None: isize = 42; //~ ERROR let bindings cannot shadow unit variants
-  log(debug, None);
-  //~^ ERROR cannot find function `log` in this scope
-  //~| ERROR cannot find value `debug` in this scope
-}
index 967c292fa68d241a3c3e3f12f93a806468b978a4..4d2412c34a5faf46984fe06e6326ba2f68b4641d 100644 (file)
@@ -14,7 +14,6 @@ trait Tr {
     fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
                         //~^ WARN was previously accepted
     fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
-                     //~^ WARN was previously accepted
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
     #[allow(anonymous_parameters)]
diff --git a/src/test/compile-fail/no-patterns-in-args-macro.rs b/src/test/compile-fail/no-patterns-in-args-macro.rs
new file mode 100644 (file)
index 0000000..f85ce8f
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+macro_rules! m {
+    ($pat: pat) => {
+        trait Tr {
+            fn trait_method($pat: u8);
+        }
+
+        type A = fn($pat: u8);
+
+        extern {
+            fn foreign_fn($pat: u8);
+        }
+    }
+}
+
+mod good_pat {
+    m!(good_pat); // OK
+}
+
+mod bad_pat {
+    m!((bad, pat));
+    //~^ ERROR patterns aren't allowed in function pointer types
+    //~| ERROR patterns aren't allowed in foreign function declarations
+    //~| ERROR patterns aren't allowed in methods without bodies
+}
+
+fn main() {}
index b0278476998dd54b42a96a1a9b6089bb1a9db957..081d6caaa13c9387b28f2d2eb0754c3c7b877526 100644 (file)
 extern {
     fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
                         //~^ NOTE pattern not allowed in foreign function
-                        //~| NOTE this is a recent error
     fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
                      //~^ NOTE pattern not allowed in foreign function
     fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
                         //~^ NOTE pattern not allowed in foreign function
-                        //~| NOTE this is a recent error
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
     // fn g3(u8); // Not yet
 }
 
 type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
-                           //~^ NOTE this is a recent error
 type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
-                        //~^ NOTE this is a recent error
 type B1 = fn(arg: u8); // OK
 type B2 = fn(_: u8); // OK
 type B3 = fn(u8); // OK
index 50240b475578c6a66f903e1f8cee08cfc476951f..a51a9e518ce5fe7e0d7aac6fd9f6b9b7922ac72f 100644 (file)
 
 #![feature(core_intrinsics)]
 #![allow(warnings)]
+#![crate_type = "rlib"]
 
 use std::intrinsics;
 
 #[derive(Copy, Clone)]
-struct Foo(i64);
-type Bar = &'static Fn();
-type Quux = [u8; 100];
+pub struct Foo(i64);
+pub type Bar = &'static Fn();
+pub type Quux = [u8; 100];
 
-unsafe fn test_bool_load(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
     intrinsics::atomic_load(p);
     //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_bool_store(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
     intrinsics::atomic_load(p);
     //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
     intrinsics::atomic_load(p);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
     intrinsics::atomic_load(p);
     //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
-unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
-unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
-unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
 }
-
-fn main() {}
index c0dd5200f6cb4e97be5e24eddf6f1d699f27052a..c50f425b2c01d744cb41256a10fd0f726010c8bf 100644 (file)
@@ -38,7 +38,7 @@ fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
 fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
     // Here we override the lifetimes explicitly, and so naturally we get an error.
 
-    ss.r = b; //~ ERROR cannot infer an appropriate lifetime
+    ss.r = b; //~ ERROR 41:12: 41:13: explicit lifetime required in the type of `ss` [E0621]
 }
 
 fn main() {
diff --git a/src/test/compile-fail/pattern-binding-disambiguation.rs b/src/test/compile-fail/pattern-binding-disambiguation.rs
new file mode 100644 (file)
index 0000000..c740f6b
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct UnitStruct;
+struct TupleStruct();
+struct BracedStruct{}
+
+enum E {
+    UnitVariant,
+    TupleVariant(),
+    BracedVariant{},
+}
+use E::*;
+
+const CONST: () = ();
+static STATIC: () = ();
+
+fn function() {}
+
+fn main() {
+    let doesnt_matter = 0;
+
+    match UnitStruct {
+        UnitStruct => {} // OK, `UnitStruct` is a unit struct pattern
+    }
+    match doesnt_matter {
+        TupleStruct => {} //~ ERROR match bindings cannot shadow tuple structs
+    }
+    match doesnt_matter {
+        BracedStruct => {} // OK, `BracedStruct` is a fresh binding
+    }
+    match UnitVariant {
+        UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern
+    }
+    match doesnt_matter {
+        TupleVariant => {} //~ ERROR match bindings cannot shadow tuple variants
+    }
+    match doesnt_matter {
+        BracedVariant => {} //~ ERROR match bindings cannot shadow struct variants
+    }
+    match CONST {
+        CONST => {} // OK, `CONST` is a const pattern
+    }
+    match doesnt_matter {
+        STATIC => {} //~ ERROR match bindings cannot shadow statics
+    }
+    match doesnt_matter {
+        function => {} // OK, `function` is a fresh binding
+    }
+
+    let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern
+    let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs
+    let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding
+    let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern
+    let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants
+    let BracedVariant = doesnt_matter; //~ ERROR let bindings cannot shadow struct variants
+    let CONST = CONST; // OK, `CONST` is a const pattern
+    let STATIC = doesnt_matter; //~ ERROR let bindings cannot shadow statics
+    let function = doesnt_matter; // OK, `function` is a fresh binding
+}
index f886c0255ccbf08631500c18f692fafd98c6dd58..e3d96f52e817b857ba091bafaff9c5ecee71198b 100644 (file)
@@ -21,7 +21,7 @@ fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
 fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
     // Here we try to call `foo` but do not know that `'a` and `'b` are
     // related as required.
-    a(x, y); //~ ERROR cannot infer
+    a(x, y); //~ ERROR 24:7: 24:8: lifetime mismatch [E0623]
 }
 
 fn d() {
index bae9608c3f05afa741e68eb59aa52676ec6379a0..d8d12444dddb34bae2979ee6c7086f0f0fa9ba77 100644 (file)
@@ -23,7 +23,7 @@ fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
 fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
     // Here we try to call `foo` but do not know that `'a` and `'b` are
     // related as required.
-    a(x, y, z); //~ ERROR cannot infer
+    a(x, y, z); //~ ERROR 26:7: 26:8: lifetime mismatch [E0623]
 }
 
 fn d() {
index 1eb36e34ab32ee611ceaaa2e70b1547c93b93a07..24e4c5fbd91be47f345f39866404be8991d2f0c2 100644 (file)
@@ -27,7 +27,7 @@ fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) {
 
 fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
     // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
-    a.bigger_region(b) //~ ERROR cannot infer
+    a.bigger_region(b) //~ ERROR 30:7: 30:20: lifetime mismatch [E0623]
 }
 
 fn main() { }
index f13d8a60894cb6b7ae9e3f4162cd52b427e49167..3e9d2aa6c3bff4b04755d25f6a51985e0c075879 100644 (file)
@@ -27,7 +27,7 @@ fn caller1<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
 
 fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
     // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
-    f.method(b); //~ ERROR cannot infer
+    f.method(b); //~ ERROR 30:7: 30:13: lifetime mismatch [E0623]
 }
 
 fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
index 4c8484540aabbb1248695fc550c75ac159ae0908..dcc579d26c18f681f2e02bc1d89edb35233fb5c2 100644 (file)
@@ -14,7 +14,7 @@ enum ast<'a> {
 }
 
 fn mk_add_bad1<'a,'b>(x: &'a ast<'a>, y: &'b ast<'b>) -> ast<'a> {
-    ast::add(x, y) //~ ERROR cannot infer
+    ast::add(x, y) //~ ERROR 17:5: 17:19: lifetime mismatch [E0623]
 }
 
 fn main() {
index 1893395e2b0079e480edad4b4a6c0963e1b3b707..073a4f79b05f006d3143acd11b9862c873b62626 100644 (file)
@@ -20,13 +20,13 @@ fn ordering1<'a, 'b>(x: &'a &'b usize) -> &'a usize {
 
 fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
     // However, it is not safe to assume that 'b <= 'a
-    &*y //~ ERROR cannot infer
+    &*y //~ ERROR 23:5: 23:8: lifetime mismatch [E0623]
 }
 
 fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
     // Do not infer an ordering from the return value.
     let z: &'b usize = &*x;
-    //~^ ERROR cannot infer
+    //~^ ERROR 28:24: 28:27: lifetime mismatch [E0623]
     panic!();
 }
 
index 586a8a183a4e6317bb34d1bde8c4baff8c91f464..843c5f512f8f17d181986ca788ba4584f44a538a 100644 (file)
@@ -22,7 +22,7 @@ pub fn flag<'r>(name: &'r str, desc: &'r str) -> Flag<'r> {
 
     impl<'a> Flag<'a> {
         pub fn set_desc(self, s: &str) -> Flag<'a> {
-            Flag { //~ ERROR cannot infer
+            Flag { //~ ERROR 25:13: 30:14: explicit lifetime required in the type of `s` [E0621]
                 name: self.name,
                 desc: s,
                 max_count: self.max_count,
index 0c250e38258cec518bddb3a48a81e14c965be69b..ec73bf90b6e524e550c8e54a814b597f46d2b795 100644 (file)
@@ -21,7 +21,7 @@ struct not_parameterized2 {
 }
 
 fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
-//~^ ERROR mismatched types
+//~^ ERROR explicit lifetime required in the type of `p`
 
 fn take3(p: not_parameterized1) -> not_parameterized1 { p }
 fn take4(p: not_parameterized2) -> not_parameterized2 { p }
index ef1c58bf972e31ba07c8c9a185fae164f1262958..5955619ea92adde671d8e5a8caa7fa8ae30c2d32 100644 (file)
@@ -21,7 +21,7 @@ fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
 fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
     // Here we try to call `foo` but do not know that `'a` and `'b` are
     // related as required.
-    a(x, y); //~ ERROR E0495
+    a(x, y); //~ ERROR 24:7: 24:8: lifetime mismatch [E0623]
 }
 
 fn d() {
index 9743f11c9667bc1dae70ed4e4a69a254c7b79598..f6f1a189e5ee14dbd5dc6cc57759ef71bd704284 100644 (file)
@@ -11,7 +11,7 @@
 // Issue #8624. Test for reborrowing with 3 levels, not just two.
 
 fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
-    &mut ***p //~ ERROR cannot infer
+    &mut ***p //~ ERROR 14:5: 14:14: lifetime mismatch [E0623]
 }
 
 fn main() {
index 399ebd6a2a72620431e4f89abb7a383b014ea8e7..7270b477d2d88df3badf5762577cc24b78c96d36 100644 (file)
@@ -13,7 +13,7 @@
 // for `'a` (which must be a sublifetime of `'b`).
 
 fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
-    &mut **p //~ ERROR cannot infer
+    &mut **p //~ ERROR 16:5: 16:13: lifetime mismatch [E0623]
 }
 
 fn main() {
index 9753014e7810ae49c17a1b4aeddde670c7711e8a..b2dba3bd61b36301dfb73b81f6c183cf7b84fde5 100644 (file)
@@ -17,7 +17,6 @@ fn f(self::S: S) {}
     fn g(&self::S: &S) {}
     fn h(&mut self::S: &mut S) {}
     fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern
-                             //~^ ERROR expected one of `)` or `mut`, found `'a`
 }
 
 fn main() {}
index 35c368f4cbedb5bb399156b590bbc7ad1f43dfdd..ee08ca05e803fca35452eef49dd4c0affdc46edb 100644 (file)
@@ -27,6 +27,7 @@
     fn simd_sub<T>(x: T, y: T) -> T;
     fn simd_mul<T>(x: T, y: T) -> T;
     fn simd_div<T>(x: T, y: T) -> T;
+    fn simd_rem<T>(x: T, y: T) -> T;
     fn simd_shl<T>(x: T, y: T) -> T;
     fn simd_shr<T>(x: T, y: T) -> T;
     fn simd_and<T>(x: T, y: T) -> T;
@@ -49,8 +50,12 @@ fn main() {
         simd_mul(x, x);
         simd_mul(y, y);
         simd_mul(z, z);
-
+        simd_div(x, x);
+        simd_div(y, y);
         simd_div(z, z);
+        simd_rem(x, x);
+        simd_rem(y, y);
+        simd_rem(z, z);
 
         simd_shl(x, x);
         simd_shl(y, y);
@@ -84,10 +89,6 @@ fn main() {
         //~^ ERROR expected SIMD input type, found non-SIMD `i32`
 
 
-        simd_div(x, x);
-//~^ ERROR unsupported operation on `i32x4` with element `i32`
-        simd_div(y, y);
-//~^ ERROR unsupported operation on `u32x4` with element `u32`
         simd_shl(z, z);
 //~^ ERROR unsupported operation on `f32x4` with element `f32`
         simd_shr(z, z);
diff --git a/src/test/compile-fail/task-rng-isnt-sendable.rs b/src/test/compile-fail/task-rng-isnt-sendable.rs
deleted file mode 100644 (file)
index d85717f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-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(rand)]
-
-// ensure that the ThreadRng isn't/doesn't become accidentally sendable.
-
-use std::__rand::ThreadRng;
-
-fn test_send<S: Send>() {}
-
-pub fn main() {
-    test_send::<ThreadRng>(); //~ ERROR std::marker::Send` is not satisfied
-}
index a98b7cd43090f3768723cdc4fdb175eb4a91d410..a0d1f2dc3312e4b5784ac7d726303659ef0b6b48 100644 (file)
@@ -15,7 +15,8 @@ struct Foo {
 }
 
 impl Foo {
-    fn foo(self: isize, x: isize) -> isize {  //~ ERROR mismatched method receiver
+    fn foo(self: isize, x: isize) -> isize {
+        //~^ ERROR invalid `self` type
         self.f + x
     }
 }
@@ -25,10 +26,12 @@ struct Bar<T> {
 }
 
 impl<T> Bar<T> {
-    fn foo(self: Bar<isize>, x: isize) -> isize { //~ ERROR mismatched method receiver
+    fn foo(self: Bar<isize>, x: isize) -> isize {
+        //~^ ERROR invalid `self` type
         x
     }
-    fn bar(self: &Bar<usize>, x: isize) -> isize {   //~ ERROR mismatched method receiver
+    fn bar(self: &Bar<usize>, x: isize) -> isize {
+        //~^ ERROR invalid `self` type
         x
     }
 }
@@ -45,12 +48,12 @@ fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
     //~^ ERROR mismatched method receiver
     fn dummy3(self: &&Bar<T>) {}
     //~^ ERROR mismatched method receiver
-    //~| expected type `&&'a Bar<T>`
-    //~| found type `&&Bar<T>`
+    //~| expected type `&'a Bar<T>`
+    //~| found type `&Bar<T>`
     //~| lifetime mismatch
     //~| ERROR mismatched method receiver
-    //~| expected type `&&'a Bar<T>`
-    //~| found type `&&Bar<T>`
+    //~| expected type `&'a Bar<T>`
+    //~| found type `&Bar<T>`
     //~| lifetime mismatch
 }
 
index 2d78940ce4b9d195d18ed24112b54acae7a0b6a2..bc9eab2be821bf153bab93d29411cfcacd51a821 100644 (file)
@@ -31,7 +31,7 @@ fn get<'a, G>(get: &G) -> i32
     // This fails to type-check because, without variance, we can't
     // use `G : Get<&'a i32>` as evidence that `G : Get<&'b i32>`,
     // even if `'a : 'b`.
-    pick(get, &22) //~ ERROR cannot infer
+    pick(get, &22) //~ ERROR 34:5: 34:9: explicit lifetime required in the type of `get` [E0621]
 }
 
 fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
index 40067efd57595973a13dc00676ee0347c5681eeb..067ce51d0f7854bb8be86324a59fe6038e74750d 100644 (file)
 // crate. This should not cause anything we use to be invalidated.
 // Regression test for #36168.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
 
 extern crate point;
 
 /// A fn item that calls (public) methods on `Point` from the same impl
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -40,10 +42,10 @@ pub fn check() {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_free_fn {
+pub mod fn_calls_free_fn {
     use point::{self, Point};
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         point::distance_squared(&x);
@@ -51,34 +53,31 @@ pub fn check() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index ac5c0d3b9e72d9c9487ecbcf81b87ba0114bd4a5..b1c566e1739ef8a355aedf5865944f8607d6aa34 100644 (file)
 // Fns with that type used only in their body are also recompiled, but
 // their callers are not.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
 // These are expected to require translation.
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_with_type_in_sig", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-call_fn_with_type_in_sig", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_with_type_in_body", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_write_field", cfg="rpass2")]
-
-#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="rpass2")]
-
-mod point {
-    #[cfg(rpass1)]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_with_type_in_sig", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-call_fn_with_type_in_sig", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_with_type_in_body", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_write_field", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="cfail2")]
+
+pub mod point {
+    #[cfg(cfail1)]
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
-    #[cfg(rpass2)]
+    #[cfg(cfail2)]
     pub struct Point {
         pub x: f32,
         pub y: f32,
@@ -47,18 +49,18 @@ pub struct Point {
 
     impl Point {
         pub fn origin() -> Point {
-            #[cfg(rpass1)]
+            #[cfg(cfail1)]
             return Point { x: 0.0, y: 0.0 };
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return Point { x: 0.0, y: 0.0, z: 0.0 };
         }
 
         pub fn total(&self) -> f32 {
-            #[cfg(rpass1)]
+            #[cfg(cfail1)]
             return self.x + self.y;
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return self.x + self.y + self.z;
         }
 
@@ -75,10 +77,10 @@ pub fn x(&self) -> f32 {
 /// sufficiently "private", we might not need to type-check again.
 /// Rebuilding is probably always necessary since the layout may be
 /// affected.
-mod fn_with_type_in_sig {
+pub mod fn_with_type_in_sig {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn boop(p: Option<&Point>) -> f32 {
         p.map(|p| p.total()).unwrap_or(0.0)
     }
@@ -91,10 +93,10 @@ pub fn boop(p: Option<&Point>) -> f32 {
 /// sufficiently "private", we might not need to type-check again.
 /// Rebuilding is probably always necessary since the layout may be
 /// affected.
-mod call_fn_with_type_in_sig {
+pub mod call_fn_with_type_in_sig {
     use fn_with_type_in_sig;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_sig::boop(None)
     }
@@ -107,10 +109,10 @@ pub fn bip() -> f32 {
 /// sufficiently "private", we might not need to type-check again.
 /// Rebuilding is probably always necessary since the layout may be
 /// affected.
-mod fn_with_type_in_body {
+pub mod fn_with_type_in_body {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn boop() -> f32 {
         Point::origin().total()
     }
@@ -120,44 +122,41 @@ pub fn boop() -> f32 {
 /// body. In this case, the effects of the change should be contained
 /// to Y; X should not have to be rebuilt, nor should it need to be
 /// typechecked again.
-mod call_fn_with_type_in_body {
+pub mod call_fn_with_type_in_body {
     use fn_with_type_in_body;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_body::boop()
     }
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin(p: Point) -> Point {
         Point { ..p }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index abfd55ba52cc7a5bd310fcebaadde581aeb6ef99..d8251a4fbcf6c905031f058409a8403fd8147c92 100644 (file)
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
     fn distance_squared(this: &Point) -> f32 {
-        #[cfg(rpass1)]
+        #[cfg(cfail1)]
         return this.x + this.y;
 
-        #[cfg(rpass2)]
+        #[cfg(cfail2)]
         return this.x * this.x + this.y * this.y;
     }
 
@@ -56,10 +58,10 @@ pub fn translate(&mut self, x: f32, y: f32) {
 }
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -67,10 +69,10 @@ pub fn check() {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -78,34 +80,31 @@ pub fn check() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index dcc1ced635fbf8b6a08a7c03410ef7eff95f2867..af20336806fd432a3e652193256bd775237641ef 100644 (file)
@@ -14,10 +14,10 @@ pub struct Point {
 }
 
 fn distance_squared(this: &Point) -> f32 {
-    #[cfg(rpass1)]
+    #[cfg(cfail1)]
     return this.x + this.y;
 
-    #[cfg(rpass2)]
+    #[cfg(cfail2)]
     return this.x * this.x + this.y * this.y;
 }
 
index a6d029515d74263d23cbeb295eb101fb68618967..b3816b90194e45dd23f6b5248e4aaaefd0554237 100644 (file)
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
 
 extern crate point;
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -39,10 +41,10 @@ pub fn check() {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -50,34 +52,31 @@ pub fn check() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index d8c6cafe596a696880f03a6b17012938350c54fe..c18f95a631205da605c9dd10821b52f982669672 100644 (file)
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
     impl Point {
-        fn distance_squared(&self) -> f32 {
-            #[cfg(rpass1)]
+        pub fn distance_squared(&self) -> f32 {
+            #[cfg(cfail1)]
             return self.x + self.y;
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return self.x * self.x + self.y * self.y;
         }
 
@@ -56,10 +58,10 @@ pub fn translate(&mut self, x: f32, y: f32) {
 }
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -67,10 +69,10 @@ pub fn check() {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -78,34 +80,31 @@ pub fn check() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index 8df1cf54da2b97c3e34abb97abcba9b802f2b239..f5e3a06051cc95b29b3952b7d748f75b89c5555a 100644 (file)
@@ -15,10 +15,10 @@ pub struct Point {
 
 impl Point {
     fn distance_squared(&self) -> f32 {
-        #[cfg(rpass1)]
+        #[cfg(cfail1)]
         return self.x + self.y;
 
-        #[cfg(rpass2)]
+        #[cfg(cfail2)]
         return self.x * self.x + self.y * self.y;
     }
 
index 05c076b9f4bc3b47dd286d658a3221024fef4ef3..55e1dffe9da41e28ee421b4011cdf94dffc3a3ae 100644 (file)
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
 
 extern crate point;
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -40,10 +42,10 @@ pub fn check() {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn dirty() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -51,34 +53,31 @@ pub fn dirty() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index 5b29ee1435f9a70cbb4942e2163a66c2f3e5d053..2cb7ef13f8e526bf281300bc588f554f1756b489 100644 (file)
 
 // Test where we change the body of a public, inherent method.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_changed_method", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_changed_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
@@ -33,10 +35,10 @@ pub struct Point {
 
     impl Point {
         pub fn distance_from_origin(&self) -> f32 {
-            #[cfg(rpass1)]
+            #[cfg(cfail1)]
             return self.x * self.x + self.y * self.y;
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return (self.x * self.x + self.y * self.y).sqrt();
         }
 
@@ -47,10 +49,10 @@ pub fn x(&self) -> f32 {
 }
 
 /// A fn item that calls the method on `Point` which changed
-mod fn_calls_changed_method {
+pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_origin();
@@ -58,10 +60,10 @@ pub fn check() {
 }
 
 /// A fn item that calls a method on `Point` which did not change
-mod fn_calls_another_method {
+pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -69,34 +71,31 @@ pub fn check() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index 4d12b7b390cc91d13e428f6f3156a4e8888d5d41..f2485a876cc60a4db3b017ab40b53a56241f3acc 100644 (file)
 
 // Test where we change the *signature* of a public, inherent method.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
 // These are expected to require translation.
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_calls_changed_method", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_calls_changed_method", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
     impl Point {
-        #[cfg(rpass1)]
+        #[cfg(cfail1)]
         pub fn distance_from_point(&self, p: Option<Point>) -> f32 {
             let p = p.unwrap_or(Point { x: 0.0, y: 0.0 });
             let x_diff = self.x - p.x;
@@ -41,7 +43,7 @@ pub fn distance_from_point(&self, p: Option<Point>) -> f32 {
             return x_diff * x_diff + y_diff * y_diff;
         }
 
-        #[cfg(rpass2)]
+        #[cfg(cfail2)]
         pub fn distance_from_point(&self, p: Option<&Point>) -> f32 {
             const ORIGIN: &Point = &Point { x: 0.0, y: 0.0 };
             let p = p.unwrap_or(ORIGIN);
@@ -57,10 +59,10 @@ pub fn x(&self) -> f32 {
 }
 
 /// A fn item that calls the method that was changed
-mod fn_calls_changed_method {
+pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_point(None);
@@ -68,10 +70,10 @@ pub fn check() {
 }
 
 /// A fn item that calls a method that was not changed
-mod fn_calls_another_method {
+pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -79,34 +81,31 @@ pub fn check() {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
index 0090c2aeef9369f57463a1933f8ea04e71c087e8..b49609cbd17a2d3848bd676c49d8be2a30c75e6c 100644 (file)
@@ -190,7 +190,7 @@ fn method1(&self, _x: char, _y: bool) {}
 }
 
 // Change UFCS Callee Indirectly -----------------------------------------------
-mod change_ufcs_callee_indirectly {
+pub mod change_ufcs_callee_indirectly {
     #[cfg(cfail1)]
     use super::Struct as Struct;
     #[cfg(not(cfail1))]
index f826d47c3e53f003f6a41ccfc6258abc8c9b6ef4..e38fd58d7d277e7bec3807f00710fcbb0ee171c7 100644 (file)
@@ -25,7 +25,7 @@
 #![crate_type="rlib"]
 
 
-enum Enum {
+pub enum Enum {
     Struct {
         x: i32,
         y: i64,
@@ -36,7 +36,7 @@ enum Enum {
 
 // Change field value (struct-like) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_struct_like() -> Enum {
+pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
         y: 1,
@@ -49,7 +49,7 @@ fn change_field_value_struct_like() -> Enum {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_struct_like() -> Enum {
+pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
         y: 2,
@@ -61,7 +61,7 @@ fn change_field_value_struct_like() -> Enum {
 
 // Change field order (struct-like) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_order_struct_like() -> Enum {
+pub fn change_field_order_struct_like() -> Enum {
     Enum::Struct {
         x: 3,
         y: 4,
@@ -76,7 +76,7 @@ fn change_field_order_struct_like() -> Enum {
 #[rustc_metadata_clean(cfg="cfail3")]
 // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
 // would if it were not all constants
-fn change_field_order_struct_like() -> Enum {
+pub fn change_field_order_struct_like() -> Enum {
     Enum::Struct {
         y: 4,
         x: 3,
@@ -85,7 +85,7 @@ fn change_field_order_struct_like() -> Enum {
 }
 
 
-enum Enum2 {
+pub enum Enum2 {
     Struct {
         x: i8,
         y: i8,
@@ -102,7 +102,7 @@ enum Enum2 {
 
 // Change constructor path (struct-like) ------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_struct_like() {
+pub fn change_constructor_path_struct_like() {
     let _ = Enum::Struct {
         x: 0,
         y: 1,
@@ -115,7 +115,7 @@ fn change_constructor_path_struct_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_struct_like() {
+pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
         x: 0,
         y: 1,
@@ -127,7 +127,7 @@ fn change_constructor_path_struct_like() {
 
 // Change variant (regular struct) ------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_variant_struct_like() {
+pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct {
         x: 0,
         y: 1,
@@ -140,7 +140,7 @@ fn change_constructor_variant_struct_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_variant_struct_like() {
+pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
         x: 0,
         y: 1,
@@ -150,7 +150,7 @@ fn change_constructor_variant_struct_like() {
 
 
 // Change constructor path indirectly (struct-like) -------------------------
-mod change_constructor_path_indirectly_struct_like {
+pub mod change_constructor_path_indirectly_struct_like {
     #[cfg(cfail1)]
     use super::Enum as TheEnum;
     #[cfg(not(cfail1))]
@@ -164,7 +164,7 @@ mod change_constructor_path_indirectly_struct_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> TheEnum {
+    pub fn function() -> TheEnum {
         TheEnum::Struct {
             x: 0,
             y: 1,
@@ -175,7 +175,7 @@ fn function() -> TheEnum {
 
 
 // Change constructor variant indirectly (struct-like) ---------------------------
-mod change_constructor_variant_indirectly_struct_like {
+pub mod change_constructor_variant_indirectly_struct_like {
     use super::Enum2;
     #[cfg(cfail1)]
     use super::Enum2::Struct as Variant;
@@ -186,7 +186,7 @@ mod change_constructor_variant_indirectly_struct_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Enum2 {
+    pub fn function() -> Enum2 {
         Variant {
             x: 0,
             y: 1,
@@ -198,7 +198,7 @@ fn function() -> Enum2 {
 
 // Change field value (tuple-like) -------------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_tuple_like() -> Enum {
+pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 2)
 }
 
@@ -207,7 +207,7 @@ fn change_field_value_tuple_like() -> Enum {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_tuple_like() -> Enum {
+pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
 }
 
@@ -215,7 +215,7 @@ fn change_field_value_tuple_like() -> Enum {
 
 // Change constructor path (tuple-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_tuple_like() {
+pub fn change_constructor_path_tuple_like() {
     let _ = Enum::Tuple(0, 1, 2);
 }
 
@@ -227,7 +227,7 @@ fn change_constructor_path_tuple_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_tuple_like() {
+pub fn change_constructor_path_tuple_like() {
     let _ = Enum2::Tuple(0, 1, 2);
 }
 
@@ -235,7 +235,7 @@ fn change_constructor_path_tuple_like() {
 
 // Change constructor variant (tuple-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_variant_tuple_like() {
+pub fn change_constructor_variant_tuple_like() {
     let _ = Enum2::Tuple(0, 1, 2);
 }
 
@@ -247,13 +247,13 @@ fn change_constructor_variant_tuple_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_variant_tuple_like() {
+pub fn change_constructor_variant_tuple_like() {
     let _ = Enum2::Tuple2(0, 1, 2);
 }
 
 
 // Change constructor path indirectly (tuple-like) ---------------------------
-mod change_constructor_path_indirectly_tuple_like {
+pub mod change_constructor_path_indirectly_tuple_like {
     #[cfg(cfail1)]
     use super::Enum as TheEnum;
     #[cfg(not(cfail1))]
@@ -267,7 +267,7 @@ mod change_constructor_path_indirectly_tuple_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> TheEnum {
+    pub fn function() -> TheEnum {
         TheEnum::Tuple(0, 1, 2)
     }
 }
@@ -275,7 +275,7 @@ fn function() -> TheEnum {
 
 
 // Change constructor variant indirectly (tuple-like) ---------------------------
-mod change_constructor_variant_indirectly_tuple_like {
+pub mod change_constructor_variant_indirectly_tuple_like {
     use super::Enum2;
     #[cfg(cfail1)]
     use super::Enum2::Tuple as Variant;
@@ -286,19 +286,19 @@ mod change_constructor_variant_indirectly_tuple_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Enum2 {
+    pub fn function() -> Enum2 {
         Variant(0, 1, 2)
     }
 }
 
 
-enum Clike {
+pub enum Clike {
     A,
     B,
     C
 }
 
-enum Clike2 {
+pub enum Clike2 {
     B,
     C,
     D
@@ -306,7 +306,7 @@ enum Clike2 {
 
 // Change constructor path (C-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_c_like() {
+pub fn change_constructor_path_c_like() {
     let _ = Clike::B;
 }
 
@@ -314,7 +314,7 @@ fn change_constructor_path_c_like() {
 #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_c_like() {
+pub fn change_constructor_path_c_like() {
     let _ = Clike2::B;
 }
 
@@ -322,7 +322,7 @@ fn change_constructor_path_c_like() {
 
 // Change constructor variant (C-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_variant_c_like() {
+pub fn change_constructor_variant_c_like() {
     let _ = Clike::A;
 }
 
@@ -331,13 +331,13 @@ fn change_constructor_variant_c_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_variant_c_like() {
+pub fn change_constructor_variant_c_like() {
     let _ = Clike::C;
 }
 
 
 // Change constructor path indirectly (C-like) ---------------------------
-mod change_constructor_path_indirectly_c_like {
+pub mod change_constructor_path_indirectly_c_like {
     #[cfg(cfail1)]
     use super::Clike as TheEnum;
     #[cfg(not(cfail1))]
@@ -351,7 +351,7 @@ mod change_constructor_path_indirectly_c_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> TheEnum {
+    pub fn function() -> TheEnum {
         TheEnum::B
     }
 }
@@ -359,7 +359,7 @@ fn function() -> TheEnum {
 
 
 // Change constructor variant indirectly (C-like) ---------------------------
-mod change_constructor_variant_indirectly_c_like {
+pub mod change_constructor_variant_indirectly_c_like {
     use super::Clike;
     #[cfg(cfail1)]
     use super::Clike::A as Variant;
@@ -370,7 +370,7 @@ mod change_constructor_variant_indirectly_c_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Clike {
+    pub fn function() -> Clike {
         Variant
     }
 }
index 9351a4b05f15144a75c04fd6f023c6b5d0769ffa..f9e8fb026cabbfb9d14c244f272e9ca0f8833ffe 100644 (file)
@@ -25,7 +25,7 @@
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
-struct Foo;
+pub struct Foo;
 
 // Change Method Name -----------------------------------------------------------
 #[cfg(cfail1)]
@@ -578,3 +578,19 @@ impl<T: Clone> Bar<T> {
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
+
+
+// Force instantiation of some fns so we can check their hash.
+pub fn instantiation_root() {
+    Foo::method_privacy();
+
+    #[cfg(cfail1)]
+    {
+        Bar(0u32).change_impl_self_type();
+    }
+
+    #[cfg(not(cfail1))]
+    {
+        Bar(0u64).change_impl_self_type();
+    }
+}
index 5d4d434fd633f594b932c7442104534dc02f4ac5..4a3e4bc49ce6f0602fef53be9213eca869e80ffd 100644 (file)
@@ -152,13 +152,48 @@ pub fn mod_by_zero(val: i32) -> i32 {
 }
 
 
+// shift left ------------------------------------------------------------------
+#[cfg(cfail1)]
+pub fn shift_left(val: i32, shift: usize) -> i32 {
+    val << shift
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+pub fn shift_left(val: i32, shift: usize) -> i32 {
+    val << shift
+}
+
+
+// shift right ------------------------------------------------------------------
+#[cfg(cfail1)]
+pub fn shift_right(val: i32, shift: usize) -> i32 {
+    val >> shift
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+pub fn shift_right(val: i32, shift: usize) -> i32 {
+    val >> shift
+}
+
 
 // THE FOLLOWING ITEMS SHOULD NOT BE INFLUENCED BY THEIR SOURCE LOCATION
 
 // bitwise ---------------------------------------------------------------------
 #[cfg(cfail1)]
 pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
+    !val & 0x101010101 | 0x45689 ^ 0x2372382
 }
 
 #[cfg(not(cfail1))]
@@ -169,7 +204,7 @@ pub fn bitwise(val: i32) -> i32 {
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
+    !val & 0x101010101 | 0x45689 ^ 0x2372382
 }
 
 
index 231e29b79c41dc0c8d1f3668ff0e0d5864c990b6..67362e31b250233f8c377bfb3cec55ac61e83df1 100644 (file)
@@ -25,7 +25,7 @@
 #![crate_type="rlib"]
 
 
-struct RegularStruct {
+pub struct RegularStruct {
     x: i32,
     y: i64,
     z: i16,
@@ -33,7 +33,7 @@ struct RegularStruct {
 
 // Change field value (regular struct) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_regular_struct() -> RegularStruct {
+pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
         y: 1,
@@ -46,7 +46,7 @@ fn change_field_value_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_regular_struct() -> RegularStruct {
+pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
         y: 2,
@@ -58,7 +58,7 @@ fn change_field_value_regular_struct() -> RegularStruct {
 
 // Change field order (regular struct) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_order_regular_struct() -> RegularStruct {
+pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 3,
         y: 4,
@@ -71,7 +71,7 @@ fn change_field_order_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_order_regular_struct() -> RegularStruct {
+pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         y: 4,
         x: 3,
@@ -83,7 +83,7 @@ fn change_field_order_regular_struct() -> RegularStruct {
 
 // Add field (regular struct) --------------------------------------------------
 #[cfg(cfail1)]
-fn add_field_regular_struct() -> RegularStruct {
+pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -101,7 +101,7 @@ fn add_field_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn add_field_regular_struct() -> RegularStruct {
+pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -119,7 +119,7 @@ fn add_field_regular_struct() -> RegularStruct {
 
 // Change field label (regular struct) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_label_regular_struct() -> RegularStruct {
+pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -138,7 +138,7 @@ fn change_field_label_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_label_regular_struct() -> RegularStruct {
+pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -154,7 +154,7 @@ fn change_field_label_regular_struct() -> RegularStruct {
 
 
 
-struct RegularStruct2 {
+pub struct RegularStruct2 {
     x: i8,
     y: i8,
     z: i8,
@@ -162,7 +162,7 @@ struct RegularStruct2 {
 
 // Change constructor path (regular struct) ------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_regular_struct() {
+pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct {
         x: 0,
         y: 1,
@@ -175,7 +175,7 @@ fn change_constructor_path_regular_struct() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_regular_struct() {
+pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
         x: 0,
         y: 1,
@@ -186,7 +186,7 @@ fn change_constructor_path_regular_struct() {
 
 
 // Change constructor path indirectly (regular struct) -------------------------
-mod change_constructor_path_indirectly_regular_struct {
+pub mod change_constructor_path_indirectly_regular_struct {
     #[cfg(cfail1)]
     use super::RegularStruct as Struct;
     #[cfg(not(cfail1))]
@@ -199,7 +199,7 @@ mod change_constructor_path_indirectly_regular_struct {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Struct {
+    pub fn function() -> Struct {
         Struct {
             x: 0,
             y: 1,
@@ -210,11 +210,11 @@ fn function() -> Struct {
 
 
 
-struct TupleStruct(i32, i64, i16);
+pub struct TupleStruct(i32, i64, i16);
 
 // Change field value (tuple struct) -------------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_tuple_struct() -> TupleStruct {
+pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 2)
 }
 
@@ -223,17 +223,17 @@ fn change_field_value_tuple_struct() -> TupleStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_tuple_struct() -> TupleStruct {
+pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
 }
 
 
 
-struct TupleStruct2(u16, u16, u16);
+pub struct TupleStruct2(u16, u16, u16);
 
 // Change constructor path (tuple struct) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_tuple_struct() {
+pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct(0, 1, 2);
 }
 
@@ -242,14 +242,14 @@ fn change_constructor_path_tuple_struct() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_tuple_struct() {
+pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
 }
 
 
 
 // Change constructor path indirectly (tuple struct) ---------------------------
-mod change_constructor_path_indirectly_tuple_struct {
+pub mod change_constructor_path_indirectly_tuple_struct {
     #[cfg(cfail1)]
     use super::TupleStruct as Struct;
     #[cfg(not(cfail1))]
@@ -262,7 +262,7 @@ mod change_constructor_path_indirectly_tuple_struct {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Struct {
+    pub fn function() -> Struct {
         Struct(0, 1, 2)
     }
 }
index e8e40d57b1ee6b42e514900b0a45a435d95592f4..2e0f0ba083783c34ff7c694a5941c126b41f393b 100644 (file)
 // Check that the hash of `foo` doesn't change just because we ordered
 // the nested items (or even added new ones).
 
-// revisions: rpass1 rpass2
+// revisions: cfail1 cfail2
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 
-#[cfg(rpass1)]
-fn foo() {
-    fn bar() { }
-    fn baz() { }
+#[cfg(cfail1)]
+pub fn foo() {
+    pub fn bar() { }
+    pub fn baz() { }
 }
 
-#[cfg(rpass2)]
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
-fn foo() {
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    fn baz() { } // order is different...
+#[cfg(cfail2)]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+pub fn foo() {
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="HirBody", cfg="cfail2")]
+    pub fn baz() { } // order is different...
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    fn bar() { } // but that doesn't matter.
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="HirBody", cfg="cfail2")]
+    pub fn bar() { } // but that doesn't matter.
 
-    fn bap() { } // neither does adding a new item
+    pub fn bap() { } // neither does adding a new item
 }
-
-fn main() { }
index 410ff69bf69c5391169c13de2c775d876d2847f8..7bb8af74eeb7e6c6e172130e2d33baa8ac295c7c 100644 (file)
@@ -33,10 +33,9 @@ pub fn main() {
 
 mod mod1 {
     pub fn some_fn() {
-        let _ = 1;
-    }
+        #[cfg(rpass2)]
+        {}
 
-    #[cfg(rpass2)]
-    fn _some_other_fn() {
+        let _ = 1;
     }
 }
index ac6cc3e9826f1dac7230367c852c3adef09891a6..bc3e3a78fd6b899ab81d7e89b52c20d4e8f68116 100644 (file)
@@ -8,27 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: rpass1 rpass2
+// revisions: cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
-#![rustc_partition_reused(module="krate_inherent-x", cfg="rpass2")]
+#![rustc_partition_reused(module="krate_inherent-x", cfg="cfail2")]
+#![crate_type = "rlib"]
 
-fn main() { }
-
-mod x {
-    struct Foo;
+pub mod x {
+    pub struct Foo;
     impl Foo {
-        fn foo(&self) { }
+        pub fn foo(&self) { }
     }
 
-    fn method() {
+    pub fn method() {
         let x: Foo = Foo;
         x.foo(); // inherent methods used to add an edge from Krate
     }
 }
 
-#[cfg(rpass1)]
-fn bar() { } // remove this unrelated fn in rpass2, which should not affect `x::method`
+#[cfg(cfail1)]
+pub fn bar() { } // remove this unrelated fn in cfail2, which should not affect `x::method`
 
index 043cb761da0938252a6e5eea3349ce29000dcf94..83b75116c608645e5e67a0404b4b4d478967379c 100644 (file)
 #![rustc_partition_reused(module="krate_inlined-x", cfg="rpass2")]
 
 fn main() {
+    x::method();
+
     #[cfg(rpass2)]
     ()
 }
 
 mod x {
-    fn method() {
+    pub fn method() {
         // use some methods that require inlining HIR from another crate:
         let mut v = vec![];
         v.push(1);
index 4ba33f3bb3d62e9715fabcdf376df010b5470000..3ae26c6aa4517bfca78720248abf8a045acc9754 100644 (file)
 // This test case makes sure that the compiler doesn't crash due to a failing
 // table lookup when a source file is removed.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 
 // Note that we specify -g so that the FileMaps actually get referenced by the
 // incr. comp. cache:
 // compile-flags: -Z query-dep-graph -g
+// must-compile-successfully
 
-#[cfg(rpass1)]
+#![crate_type= "rlib"]
+
+#[cfg(cfail1)]
 mod auxiliary;
 
-#[cfg(rpass1)]
-fn main() {
+#[cfg(cfail1)]
+pub fn foo() {
     auxiliary::print_hello();
 }
 
-#[cfg(rpass2)]
-fn main() {
+#[cfg(cfail2)]
+pub fn foo() {
     println!("hello");
 }
index 7d8e6c9d9d7efd283eef2ecb0ecb760a8c189e5f..e1369d92c5ccb4d9b18886d12f1e27e0f4f9c475 100644 (file)
@@ -14,7 +14,6 @@
 // revisions:rpass1 rpass2
 // compile-flags: -Z query-dep-graph -g
 
-#![rustc_partition_reused(module="spans_in_type_debuginfo", cfg="rpass2")]
 #![rustc_partition_reused(module="spans_in_type_debuginfo-structs", cfg="rpass2")]
 #![rustc_partition_reused(module="spans_in_type_debuginfo-enums", cfg="rpass2")]
 
index 760975b292f95fc01bfc64fc41b679354e76b6e3..3e75fa985acb42f8e561e852dfc2b2228787e469 100644 (file)
@@ -8,47 +8,48 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: rpass1 rpass2
+// revisions: cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
+#![crate_type = "rlib"]
 
 // Here the only thing which changes is the string constant in `x`.
 // Therefore, the compiler deduces (correctly) that typeck is not
 // needed even for callers of `x`.
 
-fn main() { }
 
-mod x {
-    #[cfg(rpass1)]
+pub mod x {
+    #[cfg(cfail1)]
     pub fn x() {
         println!("{}", "1");
     }
 
-    #[cfg(rpass2)]
-    #[rustc_dirty(label="HirBody", cfg="rpass2")]
-    #[rustc_dirty(label="MirOptimized", cfg="rpass2")]
+    #[cfg(cfail2)]
+    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="MirOptimized", cfg="cfail2")]
     pub fn x() {
         println!("{}", "2");
     }
 }
 
-mod y {
+pub mod y {
     use x;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
-    #[rustc_clean(label="MirOptimized", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="MirOptimized", cfg="cfail2")]
     pub fn y() {
         x::x();
     }
 }
 
-mod z {
+pub mod z {
     use y;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
-    #[rustc_clean(label="MirOptimized", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="MirOptimized", cfg="cfail2")]
     pub fn z() {
         y::y();
     }
index d3bf7f68785d568d93e28654985d735bd7331d5e..e7263b4739452a9e1fb7fca8ef639cdd64cfbd40 100644 (file)
@@ -36,7 +36,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-initial.after.mir
+// START rustc.main.SimplifyCfg-initial.after.mir
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const false;
@@ -82,4 +82,4 @@ fn main() {
 //         StorageDead(_1);
 //         return;
 //     }
-// END rustc.node4.SimplifyCfg-initial.after.mir
+// END rustc.main.SimplifyCfg-initial.after.mir
index 5c3b418e950016db67d98ebaac93be5b82db5b92..c782859b126f0971ac6e337a5c00c6c00d8eadb9 100644 (file)
@@ -28,7 +28,7 @@ fn drop(&mut self) {
 }
 
 // END RUST SOURCE
-// START rustc.node4.ElaborateDrops.before.mir
+// START rustc.main.ElaborateDrops.before.mir
 //     let mut _0: ();
 //     scope 1 {
 //         let _1: std::boxed::Box<S>;
@@ -88,4 +88,4 @@ fn drop(&mut self) {
 //         return;
 //     }
 // }
-// END rustc.node4.ElaborateDrops.before.mir
+// END rustc.main.ElaborateDrops.before.mir
index a45e7f21023bf54564d6959a86a72927815d7661..223c65737ad60f4e6f02fd2dcf9fbb7540401c2d 100644 (file)
@@ -13,10 +13,13 @@ fn test(x: u32) -> u32 {
     y
 }
 
-fn main() { }
+fn main() {
+    // Make sure the function actually gets instantiated.
+    test(0);
+}
 
 // END RUST SOURCE
-// START rustc.node4.CopyPropagation.before.mir
+// START rustc.test.CopyPropagation.before.mir
 //  bb0: {
 //      ...
 //      _3 = _1;
@@ -28,12 +31,12 @@ fn main() { }
 //      ...
 //      return;
 //  }
-// END rustc.node4.CopyPropagation.before.mir
-// START rustc.node4.CopyPropagation.after.mir
+// END rustc.test.CopyPropagation.before.mir
+// START rustc.test.CopyPropagation.after.mir
 //  bb0: {
 //      ...
 //      _0 = _1;
 //      ...
 //      return;
 //  }
-// END rustc.node4.CopyPropagation.after.mir
+// END rustc.test.CopyPropagation.after.mir
diff --git a/src/test/mir-opt/copy_propagation_arg.rs b/src/test/mir-opt/copy_propagation_arg.rs
new file mode 100644 (file)
index 0000000..ae30b5f
--- /dev/null
@@ -0,0 +1,116 @@
+// 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.
+
+// Check that CopyPropagation does not propagate an assignment to a function argument
+// (doing so can break usages of the original argument value)
+
+fn dummy(x: u8) -> u8 {
+    x
+}
+
+fn foo(mut x: u8) {
+    // calling `dummy` to make an use of `x` that copyprop cannot eliminate
+    x = dummy(x); // this will assign a local to `x`
+}
+
+fn bar(mut x: u8) {
+    dummy(x);
+    x = 5;
+}
+
+fn baz(mut x: i32) {
+    // self-assignment to a function argument should be eliminated
+    x = x;
+}
+
+fn main() {
+    // Make sure the function actually gets instantiated.
+    foo(0);
+    bar(0);
+    baz(0);
+}
+
+// END RUST SOURCE
+// START rustc.foo.CopyPropagation.before.mir
+// bb0: {
+//     StorageLive(_2);
+//     StorageLive(_3);
+//     _3 = _1;
+//     _2 = const dummy(_3) -> bb1;
+// }
+// bb1: {
+//     StorageDead(_3);
+//     _1 = _2;
+//     StorageDead(_2);
+//     _0 = ();
+//     return;
+// }
+// END rustc.foo.CopyPropagation.before.mir
+// START rustc.foo.CopyPropagation.after.mir
+// bb0: {
+//     StorageLive(_2);
+//     nop;
+//     nop;
+//     _2 = const dummy(_1) -> bb1;
+// }
+// bb1: {
+//     nop;
+//     _1 = _2;
+//     StorageDead(_2);
+//     _0 = ();
+//     return;
+// }
+// END rustc.foo.CopyPropagation.after.mir
+// START rustc.bar.CopyPropagation.before.mir
+// bb0: {
+//     StorageLive(_3);
+//     _3 = _1;
+//     _2 = const dummy(_3) -> bb1;
+// }
+// bb1: {
+//     StorageDead(_3);
+//     _1 = const 5u8;
+//     _0 = ();
+//     return;
+// }
+// END rustc.bar.CopyPropagation.before.mir
+// START rustc.bar.CopyPropagation.after.mir
+// bb0: {
+//     nop;
+//     nop;
+//     _2 = const dummy(_1) -> bb1;
+// }
+// bb1: {
+//     nop;
+//     _1 = const 5u8;
+//     _0 = ();
+//     return;
+// }
+// END rustc.bar.CopyPropagation.after.mir
+// START rustc.baz.CopyPropagation.before.mir
+// bb0: {
+//     StorageLive(_2);
+//     _2 = _1;
+//     _1 = _2;
+//     StorageDead(_2);
+//     _0 = ();
+//     return;
+// }
+// END rustc.baz.CopyPropagation.before.mir
+// START rustc.baz.CopyPropagation.after.mir
+// bb0: {
+//     nop;
+//     nop;
+//     nop;
+//     nop;
+//     _0 = ();
+//     return;
+// }
+// END rustc.baz.CopyPropagation.after.mir
index 9fe17a277a759385859727c7abf104abd1e864ee..d0f4e3bb60b5ad4e212b1bde7d2ab64fdf42fce4 100644 (file)
@@ -18,10 +18,13 @@ fn bar(a: usize) -> Baz {
     Baz { x: a, y: 0.0, z: false }
 }
 
-fn main() {}
+fn main() {
+    // Make sure the function actually gets instantiated.
+    bar(0);
+}
 
 // END RUST SOURCE
-// START rustc.node13.Deaggregator.before.mir
+// START rustc.bar.Deaggregator.before.mir
 // bb0: {
 //     ...
 //     _2 = _1;
@@ -30,8 +33,8 @@ fn main() {}
 //     ...
 //     return;
 // }
-// END rustc.node13.Deaggregator.before.mir
-// START rustc.node13.Deaggregator.after.mir
+// END rustc.bar.Deaggregator.before.mir
+// START rustc.bar.Deaggregator.after.mir
 // bb0: {
 //     ...
 //     _2 = _1;
@@ -42,4 +45,4 @@ fn main() {}
 //     ...
 //     return;
 // }
-// END rustc.node13.Deaggregator.after.mir
+// END rustc.bar.Deaggregator.after.mir
index d2c713b320f53134002fad58dc0303a398b4c02a..9400ae5050ba1b719bcc5c6eeb400e595c9d59ab 100644 (file)
@@ -26,7 +26,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node10.Deaggregator.before.mir
+// START rustc.bar.Deaggregator.before.mir
 // bb0: {
 //     StorageLive(_2);
 //     _2 = _1;
@@ -34,8 +34,8 @@ fn main() {
 //     StorageDead(_2);
 //     return;
 // }
-// END rustc.node10.Deaggregator.before.mir
-// START rustc.node10.Deaggregator.after.mir
+// END rustc.bar.Deaggregator.before.mir
+// START rustc.bar.Deaggregator.after.mir
 // bb0: {
 //     StorageLive(_2);
 //     _2 = _1;
@@ -44,4 +44,4 @@ fn main() {
 //     StorageDead(_2);
 //     return;
 // }
-// END rustc.node10.Deaggregator.after.mir
+// END rustc.bar.Deaggregator.after.mir
index 2780f11b9e6409382910060c09663f998345e2d1..ab62164e80035ec42b337aad61d154c7410f96dd 100644 (file)
@@ -23,10 +23,13 @@ fn test1(x: bool, y: i32) -> Foo {
     }
 }
 
-fn main() {}
+fn main() {
+    // Make sure the function actually gets instantiated.
+    test1(false, 0);
+}
 
 // END RUST SOURCE
-// START rustc.node12.Deaggregator.before.mir
+// START rustc.test1.Deaggregator.before.mir
 //  bb1: {
 //      StorageLive(_4);
 //      _4 = _2;
@@ -41,8 +44,8 @@ fn main() {}
 //      StorageDead(_5);
 //      goto -> bb3;
 //  }
-// END rustc.node12.Deaggregator.before.mir
-// START rustc.node12.Deaggregator.after.mir
+// END rustc.test1.Deaggregator.before.mir
+// START rustc.test1.Deaggregator.after.mir
 //  bb1: {
 //      StorageLive(_4);
 //      _4 = _2;
@@ -59,5 +62,5 @@ fn main() {}
 //      StorageDead(_5);
 //      goto -> bb3;
 //  }
-// END rustc.node12.Deaggregator.after.mir
+// END rustc.test1.Deaggregator.after.mir
 //
index ede3b2e6e299d0be7f7a61e8f45804707fb79c6f..91643e07ed005c1c18a1a85f371afc39bebc4f84 100644 (file)
@@ -19,10 +19,13 @@ enum Foo {
     [Foo::A(x), Foo::A(x)]
 }
 
-fn main() { }
+fn main() {
+    // Make sure the function actually gets instantiated.
+    test(0);
+}
 
 // END RUST SOURCE
-// START rustc.node10.Deaggregator.before.mir
+// START rustc.test.Deaggregator.before.mir
 // bb0: {
 //     ...
 //     _3 = _1;
@@ -36,8 +39,8 @@ fn main() { }
 //     ...
 //     return;
 // }
-// END rustc.node10.Deaggregator.before.mir
-// START rustc.node10.Deaggregator.after.mir
+// END rustc.test.Deaggregator.before.mir
+// START rustc.test.Deaggregator.after.mir
 // bb0: {
 //     ...
 //     _3 = _1;
@@ -53,4 +56,4 @@ fn main() { }
 //     ...
 //     return;
 // }
-// END rustc.node10.Deaggregator.after.mir
+// END rustc.test.Deaggregator.after.mir
index a0edcc82fe18ac888bb25df4c1e4c68f4709020a..640dec0861d045e9b689e411e5012e41b9dfd3a7 100644 (file)
@@ -19,7 +19,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 //     let mut _0: ();
 //     ...
 //     let _1: i32;
@@ -37,4 +37,4 @@ fn main() {
 //         StorageDead(_1);
 //         return;
 //     }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 69042fecc7d721597d78c947832c9c680a97183e..5ee377569dd168f95dbac24189cd928955e160df 100644 (file)
@@ -24,7 +24,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 //     let mut _0: ();
 //     ...
 //     let _2: bool;
@@ -69,4 +69,4 @@ fn main() {
 //         StorageDead(_2);
 //         goto -> bb1;
 //     }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
index da423163e842da82ab482b93c734b4d32b295730..1dbbd74cdf3c358a6aee8aab8e0ec4870512373d 100644 (file)
@@ -25,7 +25,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 //     let mut _0: ();
 //     ...
 //     let mut _1: bool;
@@ -70,4 +70,4 @@ fn main() {
 //         StorageDead(_3);
 //         goto -> bb1;
 //     }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 2087485b913d4c272ac8843994be5fa4db5d6e4f..6b8018e4b2211848c3df51da2d68120ae2a1a687 100644 (file)
@@ -29,7 +29,7 @@ fn foo(i: i32) {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 //     let mut _0: ();
 //     ...
 //     let _1: D;
@@ -76,4 +76,4 @@ fn foo(i: i32) {
 //         StorageDead(_1);
 //         return;
 //     }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 4663b71bd7cb0166720c737fdd94f6bfe5c9e704..9a3cca54ae53ea1c61b558719c1c12812ad78d6f 100644 (file)
@@ -26,7 +26,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 // fn main() -> () {
 //     ...
 //     let mut _0: ();
@@ -64,9 +64,9 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //         return;
 //     }
 // }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
 
-// START rustc.node18.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
 // fn main::{{closure}}(_1: [closure@NodeId(18) d:&'14s D]) -> i32 {
 //    let mut _0: i32;
 //    let mut _2: i32;
@@ -78,4 +78,4 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //        StorageDead(_2);
 //        return;
 //    }
-// END rustc.node18.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
index 7d2868ee4ba57f0813854fb5566fe488d2b094a5..7f0e16eaa0632fa699714496b06693000ddb7a70 100644 (file)
@@ -26,7 +26,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 // fn main() -> () {
 //     let mut _0: ();
 //     ...
@@ -62,9 +62,9 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //         StorageDead(_1);
 //         return;
 //     }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
 
-// START rustc.node22.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
 // fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 {
 //     let mut _0: i32;
 //     ...
@@ -82,4 +82,4 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //         StorageDead(_2);
 //         return;
 //     }
-// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
index 0156c1be7edf95b3f282ec83789494ac26d3304f..7a17afee3e0354341347e724df6c8f69ee6966c0 100644 (file)
@@ -26,7 +26,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 // fn main() -> () {
 //     let mut _0: ();
 //     ...
@@ -70,9 +70,9 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //         return;
 //     }
 // }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
 
-// START rustc.node22.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
 // fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 {
 //     let mut _0: i32;
 //     ...
@@ -94,4 +94,4 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //         return;
 //     }
 // }
-// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
index 6e8cf4204ee9becdc2a5b75033f2c3c019168e4d..1df30995102612ca492201bae302f9809e8b9f69 100644 (file)
@@ -27,7 +27,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 // fn main() -> () {
 //    let mut _0: ();
 //    ...
@@ -69,9 +69,9 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //        return;
 //    }
 // }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
 
-// START rustc.node22.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
 // fn main::{{closure}}(_1: [closure@NodeId(22) r:&'21_1rs D]) -> i32 {
 //     let mut _0: i32;
 //     let mut _2: i32;
@@ -84,4 +84,4 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //         return;
 //     }
 // }
-// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
index fd23d81345229644dda85be4bbcd9207e4d7a7ad..d3482077305423e3d384c5813f784fed9a70fb12 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 // fn main() -> () {
 //     let mut _0: ();
 //     ...
@@ -84,4 +84,4 @@ fn main() {
 //        goto -> bb1;
 //    }
 // }
-// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
index f70f651927544488aca0069eb13b8340768fb757..5eada97ed20ab05eee5a87a5dadd729d0675b9a5 100644 (file)
@@ -39,7 +39,7 @@ fn main() {
 fn query() -> bool { true }
 
 // END RUST SOURCE
-// START rustc.node16.SimplifyCfg-qualify-consts.after.mir
+// START rustc.main.SimplifyCfg-qualify-consts.after.mir
 // fn main() -> () {
 //     let mut _0: ();
 //     scope 1 {
@@ -130,4 +130,4 @@ fn query() -> bool { true }
 //         goto -> bb1;
 //     }
 // }
-// END rustc.node16.SimplifyCfg-qualify-consts.after.mir
+// END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 61dc1d206596178964190166a64b53fb4445401a..12d14df47df7d92dd366c32b5ec41b6990182325 100644 (file)
@@ -60,11 +60,11 @@ fn drop(&mut self) {
 //        transformation encoding the effects of rvalue-promotion.
 //        This may be the simplest and most-likely option; note in
 //        particular that `StorageDead(_6)` goes away below in
-//        rustc.node4.QualifyAndPromoteConstants.after.mir
+//        rustc.main.QualifyAndPromoteConstants.after.mir
 
 // END RUST SOURCE
 
-// START rustc.node4.QualifyAndPromoteConstants.before.mir
+// START rustc.main.QualifyAndPromoteConstants.before.mir
 // fn main() -> () {
 //     let mut _0: ();
 //     let mut _1: &'12ds S1;
@@ -113,9 +113,9 @@ fn drop(&mut self) {
 //         return;
 //     }
 // }
-// END rustc.node4.QualifyAndPromoteConstants.before.mir
+// END rustc.main.QualifyAndPromoteConstants.before.mir
 
-// START rustc.node4.QualifyAndPromoteConstants.after.mir
+// START rustc.main.QualifyAndPromoteConstants.after.mir
 // fn main() -> () {
 //     let mut _0: ();
 //     let mut _1: &'12ds S1;
@@ -158,4 +158,4 @@ fn drop(&mut self) {
 //         return;
 //     }
 // }
-// END rustc.node4.QualifyAndPromoteConstants.after.mir
+// END rustc.main.QualifyAndPromoteConstants.after.mir
index 5a9336e96592d6a287eb159eb6d667375622497d..9415e140d8048e0f44822f31c91a95056ba25e6e 100644 (file)
@@ -21,7 +21,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg-initial.after.mir
+// START rustc.main.SimplifyCfg-initial.after.mir
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const false;
@@ -48,4 +48,4 @@ fn main() {
 //         _2 = ();
 //         goto -> bb1;
 //     }
-// END rustc.node4.SimplifyCfg-initial.after.mir
+// END rustc.main.SimplifyCfg-initial.after.mir
index 384201b7c128d449a48fa527e6aebe446ee1a681..b409d1fb667905c568566a8ba923220453ba4c86 100644 (file)
@@ -14,6 +14,8 @@ fn main() {
     let x = S.other(S.id());
 }
 
+// no_mangle to make sure this gets instantiated even in an executable.
+#[no_mangle]
 pub fn test() {
     let u = S;
     let mut v = S;
@@ -33,7 +35,7 @@ fn other(self, s: Self) {}
 }
 
 // END RUST SOURCE
-// START rustc.node4.ElaborateDrops.after.mir
+// START rustc.main.ElaborateDrops.after.mir
 //    let mut _0: ();
 //    scope 1 {
 //        let _1: ();
@@ -44,8 +46,8 @@ fn other(self, s: Self) {}
 //    let mut _4: S;
 //    let mut _5: bool;
 //    bb0: {
-// END rustc.node4.ElaborateDrops.after.mir
-// START rustc.node13.ElaborateDrops.after.mir
+// END rustc.main.ElaborateDrops.after.mir
+// START rustc.test.ElaborateDrops.after.mir
 //    let mut _0: ();
 //    ...
 //    let _1: S;
@@ -57,4 +59,4 @@ fn other(self, s: Self) {}
 //    let mut _5: S;
 //    let mut _6: bool;
 //    bb0: {
-// END rustc.node13.ElaborateDrops.after.mir
+// END rustc.test.ElaborateDrops.after.mir
index 3f0f5068577c6427a196094168577f15f6925a9c..85cecc5070cd55c97c30eb0623cac7527730aef1 100644 (file)
@@ -23,7 +23,7 @@ fn rc_refcell_test(r: RefCell<i32>) {
 fn main() { }
 
 // END RUST SOURCE
-// START rustc.node5.SimplifyCfg-qualify-consts.after.mir
+// START rustc.rc_refcell_test.SimplifyCfg-qualify-consts.after.mir
 //
 // fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
 //     let mut _0: ();
index 78214dab53913feff7456b56927fbe8b5df9d715..02e9d39668de00106742bfe46e2d9d25cfbaaa3f 100644 (file)
@@ -18,7 +18,9 @@ fn guard2(_:i32) -> bool {
     true
 }
 
-fn full_tested_match() {
+// no_mangle to make sure this gets instantiated even in an executable.
+#[no_mangle]
+pub fn full_tested_match() {
     let _ = match Some(42) {
         Some(x) if guard() => (1, x),
         Some(y) => (2, y),
@@ -26,7 +28,9 @@ fn full_tested_match() {
     };
 }
 
-fn full_tested_match2() {
+// no_mangle to make sure this gets instantiated even in an executable.
+#[no_mangle]
+pub fn full_tested_match2() {
     let _ = match Some(42) {
         Some(x) if guard() => (1, x),
         None => (3, 3),
@@ -45,7 +49,7 @@ fn main() {
 
 // END RUST SOURCE
 //
-// START rustc.node17.SimplifyBranches-initial.before.mir
+// START rustc.full_tested_match.SimplifyBranches-initial.before.mir
 //  bb0: {
 //      ...
 //      _2 = std::option::Option<i32>::Some(const 42i32,);
@@ -100,9 +104,9 @@ fn main() {
 //      ...
 //      return;
 //  }
-// END rustc.node17.SimplifyBranches-initial.before.mir
+// END rustc.full_tested_match.SimplifyBranches-initial.before.mir
 //
-// START rustc.node42.SimplifyBranches-initial.before.mir
+// START rustc.full_tested_match2.SimplifyBranches-initial.before.mir
 //  bb0: {
 //      ...
 //      _2 = std::option::Option<i32>::Some(const 42i32,);
@@ -157,9 +161,9 @@ fn main() {
 //      ...
 //      return;
 //  }
-// END rustc.node42.SimplifyBranches-initial.before.mir
+// END rustc.full_tested_match2.SimplifyBranches-initial.before.mir
 //
-// START rustc.node67.SimplifyBranches-initial.before.mir
+// START rustc.main.SimplifyBranches-initial.before.mir
 // bb0: {
 //     ...
 //     _2 = std::option::Option<i32>::Some(const 1i32,);
@@ -233,4 +237,4 @@ fn main() {
 //     ...
 //     return;
 // }
-// END rustc.node67.SimplifyBranches-initial.before.mir
+// END rustc.main.SimplifyBranches-initial.before.mir
index 873431505f544fb34a57cbf96a6b27b774358ea6..2de3e7d704d567f77f867b9fe1a6358aa3e9a490 100644 (file)
@@ -25,7 +25,7 @@ fn main() {
 // - `_1` is live when `can_panic` is called (because it may be dropped)
 //
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 //    | Live variables on entry to bb0: []
 //    bb0: {
 //            | Live variables at bb0[0]: []
@@ -37,8 +37,8 @@ fn main() {
 //            | Live variables at bb0[3]: [_2]
 //        _1 = const <std::boxed::Box<T>>::new(_2) -> bb1;
 //    }
-// END rustc.node12.nll.0.mir
-// START rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
+// START rustc.main.nll.0.mir
 //    | Live variables on entry to bb1: [_1 (drop)]
 //    bb1: {
 //            | Live variables at bb1[0]: [_1 (drop)]
@@ -48,4 +48,4 @@ fn main() {
 //            | Live variables at bb1[2]: [_1 (drop)]
 //        _3 = const can_panic() -> [return: bb2, unwind: bb4];
 //    }
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index 96fd29dfe2fd9eb0ac3be46b68b9c391dc71a510..5c34479d25958ae75943b4c27f02b9bc5d525e1d 100644 (file)
@@ -24,7 +24,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 //    | Live variables on entry to bb1: []
 //    bb1: {
 //            | Live variables at bb1[0]: []
@@ -38,4 +38,4 @@ fn main() {
 //            | Live variables at bb1[4]: [_4]
 //        _3 = const use_x(_4) -> bb2;
 //    }
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index c557763c004bff84db7f7ea38752d93e36714e39..8217befca6bd5eaea2086fe972bff7ba9c4bd42d 100644 (file)
@@ -28,7 +28,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node18.nll.0.mir
+// START rustc.main.nll.0.mir
 //     | Live variables on entry to bb2: [_1]
 //     bb2: {
 //             | Live variables at bb2[0]: [_1]
@@ -38,13 +38,13 @@ fn main() {
 //             | Live variables at bb2[2]: [_4]
 //         _3 = const make_live(_4) -> bb4;
 //     }
-// END rustc.node18.nll.0.mir
-// START rustc.node18.nll.0.mir
+// END rustc.main.nll.0.mir
+// START rustc.main.nll.0.mir
 //     | Live variables on entry to bb3: []
 //     bb3: {
 //             | Live variables at bb3[0]: []
 //         _5 = const make_dead() -> bb5;
 //     }
-// END rustc.node18.nll.0.mir
+// END rustc.main.nll.0.mir
 
 
diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named-lifetimes-basic.rs
new file mode 100644 (file)
index 0000000..e3f67d8
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Basic test for named lifetime translation. Check that we
+// instantiate the types that appear in function arguments with
+// 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
+// ignore-tidy-linelength
+
+#![allow(warnings)]
+
+fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool { true }
+
+fn main() {
+}
+
+// END RUST SOURCE
+// START rustc.use_x.nll.0.mir
+// | '_#0r: {bb0[0], bb0[1], '_#0r}
+// | '_#1r: {bb0[0], bb0[1], '_#0r, '_#1r}
+// | '_#2r: {bb0[0], bb0[1], '_#2r}
+// ...
+// fn use_x(_1: &'_#0r mut i32, _2: &'_#1r u32, _3: &'_#0r u32, _4: &'_#2r u32) -> bool {
+// END rustc.use_x.nll.0.mir
index 60a4da430b96e5fce16d96359ea8ea40ce8c4077..c3df0c840ded29cefd17033fe31d49f0b47e57f4 100644 (file)
@@ -27,13 +27,13 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node13.nll.0.mir
+// START rustc.main.nll.0.mir
 // | '_#5r: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
 // ...
 // | '_#7r: {bb0[11], bb0[12], bb0[13], bb0[14]}
-// END rustc.node13.nll.0.mir
-// START rustc.node13.nll.0.mir
+// END rustc.main.nll.0.mir
+// START rustc.main.nll.0.mir
 // let _2: &'_#5r mut i32;
 // ...
 // let _4: &'_#7r mut i32;
-// END rustc.node13.nll.0.mir
+// END rustc.main.nll.0.mir
index 7792f0a36f318df3c1b29091a9b2c4201c2edcfa..f7276cb297904c016ac128aeefcb1f9ee4af1b5d 100644 (file)
@@ -30,21 +30,21 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 // | '_#0r: {bb1[1], bb2[0], bb2[1]}
 // | '_#1r: {bb1[1], bb2[0], bb2[1]}
 // ...
 //             let _2: &'_#1r usize;
-// END rustc.node12.nll.0.mir
-// START rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
+// START rustc.main.nll.0.mir
 //    bb1: {
 //            | Live variables at bb1[0]: [_1, _3]
 //        _2 = &'_#0r _1[_3];
 //            | Live variables at bb1[1]: [_2]
 //        switchInt(const true) -> [0u8: bb3, otherwise: bb2];
 //    }
-// END rustc.node12.nll.0.mir
-// START rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
+// START rustc.main.nll.0.mir
 //    bb2: {
 //            | Live variables at bb2[0]: [_2]
 //        StorageLive(_7);
@@ -53,4 +53,4 @@ fn main() {
 //            | Live variables at bb2[2]: [_7]
 //        _6 = const use_x(_7) -> bb4;
 //    }
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index 4f4bb596e5f8fa3ded771b7598a5ff5ed82a0989..6527df26eae7842b218a97f85d670a22118bc109 100644 (file)
@@ -43,6 +43,6 @@ fn drop(&mut self) { }
 }
 
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 // | '_#4r: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1]}
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index 0ddb745b61fd7c9212c41bf0be7e606c2be0812d..aedb3f562a66d0192fdb5d13c0945f039491f6f1 100644 (file)
@@ -45,6 +45,6 @@ fn drop(&mut self) { }
 }
 
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 // | '_#4r: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1], bb2[2], bb3[0], bb3[1], bb3[2], bb4[0], bb4[1], bb4[2], bb6[0], bb7[0], bb7[1], bb7[2], bb8[0]}
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index 664298b937483a7777d9c40f6bd3d6543a45dda5..23809d176f698a5e55b327a3fe391dc9c9634922 100644 (file)
@@ -35,7 +35,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 // | '_#0r: {bb1[1], bb2[0], bb2[1]}
 // ...
 // | '_#2r: {bb7[2], bb7[3], bb7[4]}
@@ -46,4 +46,4 @@ fn main() {
 // _2 = &'_#0r _1[_3];
 // ...
 // _2 = &'_#2r (*_11);
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index 4ae891f5b70eb91004e4d3ce78249a1c74219535..cada9c7b2548d822e386c44f1b1fd4fe2cf4e67b 100644 (file)
@@ -31,12 +31,12 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node12.nll.0.mir
+// START rustc.main.nll.0.mir
 // | '_#0r: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
 // | '_#1r: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
 // | '_#2r: {bb1[5], bb1[6], bb2[0], bb2[1]}
-// END rustc.node12.nll.0.mir
-// START rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
+// START rustc.main.nll.0.mir
 // let _2: &'_#1r usize;
 // ...
 // let _6: &'_#2r usize;
@@ -46,4 +46,4 @@ fn main() {
 // _7 = _2;
 // ...
 // _6 = _7;
-// END rustc.node12.nll.0.mir
+// END rustc.main.nll.0.mir
index cff108246a550da31dd2e116b4460b8409e1f2fc..ad3bbba8d08df2a82230854e4eb47f5d6e5106ab 100644 (file)
@@ -15,13 +15,13 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyBranches-initial.before.mir
+// START rustc.main.SimplifyBranches-initial.before.mir
 // bb0: {
 //     switchInt(const false) -> [0u8: bb2, otherwise: bb1];
 // }
-// END rustc.node4.SimplifyBranches-initial.before.mir
-// START rustc.node4.SimplifyBranches-initial.after.mir
+// END rustc.main.SimplifyBranches-initial.before.mir
+// START rustc.main.SimplifyBranches-initial.after.mir
 // bb0: {
 //     goto -> bb2;
 // }
-// END rustc.node4.SimplifyBranches-initial.after.mir
+// END rustc.main.SimplifyBranches-initial.after.mir
index 370ab599eca708790b0b802fe2a82783eea72ba1..995639e20d67d5a580c8d73b7261b7ca67b7d554 100644 (file)
@@ -44,7 +44,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.mir_map.0.mir
+// START rustc.XXX.mir_map.0.mir
 //    let mut _0: &'static Foo;
 //    let mut _1: &'static Foo;
 //    let mut _2: Foo;
@@ -197,4 +197,4 @@ fn main() {
 //        return;
 //    }
 //}
-// END rustc.node4.mir_map.0.mir
+// END rustc.XXX.mir_map.0.mir
index 7dbcf82af349382222e7d533e64888c012760e06..53cb82bb0f67481f475139bc1a9084dd7621d246 100644 (file)
@@ -19,7 +19,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.TypeckMir.before.mir
+// START rustc.main.TypeckMir.before.mir
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const 0i32;
@@ -40,4 +40,4 @@ fn main() {
 //         StorageDead(_1);
 //         return;
 //      }
-// END rustc.node4.TypeckMir.before.mir
+// END rustc.main.TypeckMir.before.mir
index a97ce4e8cbe5549326e128000b5e2e292c725047..f4d1caa6a95533334a5fd7633aeea4491ee57fc9 100644 (file)
@@ -28,14 +28,14 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node12.EraseRegions.after.mir
+// START rustc.{{impl}}-foo.EraseRegions.after.mir
 //     bb0: {
 //         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[317d]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[317d]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]);
 //         ...
 //         return;
 //     }
-// END rustc.node12.EraseRegions.after.mir
-// START rustc.node23.EraseRegions.after.mir
+// END rustc.{{impl}}-foo.EraseRegions.after.mir
+// START rustc.main.EraseRegions.after.mir
 // fn main() -> () {
 //     ...
 //     bb0: {
@@ -57,8 +57,8 @@ fn main() {
 //         return;
 //     }
 // }
-// END rustc.node23.EraseRegions.after.mir
-// START rustc.node50.EraseRegions.after.mir
+// END rustc.main.EraseRegions.after.mir
+// START rustc.main-{{closure}}.EraseRegions.after.mir
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 {
 //     ...
 //     bb0: {
@@ -76,4 +76,4 @@ fn main() {
 //         return;
 //     }
 // }
-// END rustc.node50.EraseRegions.after.mir
+// END rustc.main-{{closure}}.EraseRegions.after.mir
index aacf5a5ed0f5afd0ee71579e2d47332f523d211e..5f3dad5efde15d402d71cf863fc6d8abd230ae8f 100644 (file)
@@ -16,7 +16,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.EraseRegions.after.mir
+// START rustc.main.EraseRegions.after.mir
 // fn main() -> () {
 //     ...
 //     bb1: {
@@ -32,4 +32,4 @@ fn main() {
 //     }
 //     ...
 // }
-// END rustc.node4.EraseRegions.after.mir
+// END rustc.main.EraseRegions.after.mir
index d7d3e023c9ed6a51496c62d9d395d5e2cfc3ef29..50c410039e2c51a6c2e5d52bbd9c84c16ab0ae6b 100644 (file)
@@ -28,7 +28,7 @@ fn _unused2(x: *const i32) -> i32 { unsafe { *x }}
 }
 
 // END RUST SOURCE
-// START rustc.node16.EraseRegions.after.mir
+// START rustc.main.EraseRegions.after.mir
 // fn main() -> () {
 //     ...
 //     let mut _5: &ReErased i32;
@@ -62,4 +62,4 @@ fn _unused2(x: *const i32) -> i32 { unsafe { *x }}
 //         return;
 //     }
 // }
-// END rustc.node16.EraseRegions.after.mir
+// END rustc.main.EraseRegions.after.mir
index 3585ac0b8be76529025ed7ab98a849a94b731cf4..80224ddc58668c531e272f9f4b3cf6d6762e58ae 100644 (file)
@@ -36,7 +36,7 @@ fn main() {
 // contain name of the source file, so we cannot test for it.
 
 // END RUST SOURCE
-// START rustc.node4.EraseRegions.after.mir
+// START rustc.write_42.EraseRegions.after.mir
 // fn write_42(_1: *mut i32) -> bool {
 //     ...
 //     bb0: {
@@ -46,8 +46,8 @@ fn main() {
 //         return;
 //     }
 // }
-// END rustc.node4.EraseRegions.after.mir
-// START rustc.node22.EraseRegions.after.mir
+// END rustc.write_42.EraseRegions.after.mir
+// START rustc.write_42-{{closure}}.EraseRegions.after.mir
 // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () {
 //     ...
 //     bb0: {
@@ -57,8 +57,8 @@ fn main() {
 //         return;
 //     }
 // }
-// END rustc.node22.EraseRegions.after.mir
-// START rustc.node31.EraseRegions.after.mir
+// END rustc.write_42-{{closure}}.EraseRegions.after.mir
+// START rustc.test.EraseRegions.after.mir
 // fn test(_1: &ReErased mut i32) -> () {
 //     ...
 //     bb0: {
@@ -73,8 +73,8 @@ fn main() {
 //         ...
 //     }
 // }
-// END rustc.node31.EraseRegions.after.mir
-// START rustc.node60.EraseRegions.after.mir
+// END rustc.test.EraseRegions.after.mir
+// START rustc.main-{{closure}}.EraseRegions.after.mir
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
@@ -86,4 +86,4 @@ fn main() {
 //     }
 //     ...
 // }
-// END rustc.node60.EraseRegions.after.mir
+// END rustc.main-{{closure}}.EraseRegions.after.mir
index ae09d72942e55808e3ce1b9c60f9868014f6be49..a945b7dbc5fa82db047564d34fc92ae63140c214 100644 (file)
@@ -33,7 +33,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node17.EraseRegions.after.mir
+// START rustc.test.EraseRegions.after.mir
 // fn test(_1: &ReErased mut i32) -> () {
 //     ...
 //     bb0: {
@@ -44,8 +44,8 @@ fn main() {
 //     }
 //     ...
 // }
-// END rustc.node17.EraseRegions.after.mir
-// START rustc.node46.EraseRegions.after.mir
+// END rustc.test.EraseRegions.after.mir
+// START rustc.main-{{closure}}.EraseRegions.after.mir
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
@@ -63,4 +63,4 @@ fn main() {
 //     }
 //     ...
 // }
-// END rustc.node46.EraseRegions.after.mir
+// END rustc.main-{{closure}}.EraseRegions.after.mir
index 699af8ca7ab4fda5bfce891b768c19f32308d7a3..25ae7b4c55a2b306e055810179f80643967eeeb2 100644 (file)
@@ -12,5 +12,4 @@
 
 impl S {
     fn f(*, a: u8) -> u8 {} //~ ERROR expected pattern, found `*`
-    //~^ ERROR expected one of `)`, `-`, `box`, `false`, `mut`, `ref`, or `true`, found `*`
 }
diff --git a/src/test/parse-fail/range_inclusive_dotdotdot.rs b/src/test/parse-fail/range_inclusive_dotdotdot.rs
new file mode 100644 (file)
index 0000000..a4c36a2
--- /dev/null
@@ -0,0 +1,38 @@
+// 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: -Z parse-only -Z continue-parse-after-error
+
+// Make sure that inclusive ranges with `...` syntax don't parse.
+
+#![feature(inclusive_range_syntax, inclusive_range)]
+
+use std::ops::RangeToInclusive;
+
+fn return_range_to() -> RangeToInclusive<i32> {
+    return ...1; //~ERROR `...` syntax cannot be used in expressions
+                 //~^HELP  Use `..` if you need an exclusive range (a < b)
+                 //~^^HELP or `..=` if you need an inclusive range (a <= b)
+}
+
+pub fn main() {
+    let x = ...0;    //~ERROR `...` syntax cannot be used in expressions
+                     //~^HELP  Use `..` if you need an exclusive range (a < b)
+                     //~^^HELP or `..=` if you need an inclusive range (a <= b)
+
+    let x = 5...5;   //~ERROR `...` syntax cannot be used in expressions
+                     //~^HELP  Use `..` if you need an exclusive range (a < b)
+                     //~^^HELP or `..=` if you need an inclusive range (a <= b)
+
+    for _ in 0...1 {} //~ERROR `...` syntax cannot be used in expressions
+                     //~^HELP  Use `..` if you need an exclusive range (a < b)
+                     //~^^HELP or `..=` if you need an inclusive range (a <= b)
+}
+
diff --git a/src/test/pretty/cast-lt.pp b/src/test/pretty/cast-lt.pp
new file mode 100644 (file)
index 0000000..b21158a
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use std::prelude::v1::*;
+#[macro_use]
+extern crate std as std;
+// 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.
+
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:cast-lt.pp
+
+macro_rules! negative(( $ e : expr ) => { $ e < 0 });
+
+fn main() { (1 as i32) < 0; }
+
diff --git a/src/test/pretty/cast-lt.rs b/src/test/pretty/cast-lt.rs
new file mode 100644 (file)
index 0000000..87b5274
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:cast-lt.pp
+
+macro_rules! negative {
+      ($e:expr) => { $e < 0 }
+}
+
+fn main() {
+      negative!(1 as i32);
+}
+
index 6c39b33be086e279f5580e39998707473fc2dfa5..b75c82afb53d0c592f260a9ea5fca7894325e82b 100644 (file)
@@ -13,6 +13,7 @@ fn outer<T>() {
     fn inner() -> u32 {
         8675309
     }
+    inner();
 }
 
 extern "C" fn outer_foreign<T>() {
@@ -20,6 +21,7 @@ extern "C" fn outer_foreign<T>() {
     fn inner() -> u32 {
         11235813
     }
+    inner();
 }
 
 fn main() {
index bfa2162e27dd211eb05a9b779c83ae5b10889df6..64a76e9e0edabb532cc85578d2e3253a43457ee7 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+
+
 fn magic_fn() -> usize {
     1234
 }
@@ -24,4 +26,8 @@ pub fn magic_fn() -> usize {
     }
 }
 
-fn main() { }
+fn main() {
+    magic_fn();
+    a::magic_fn();
+    b::magic_fn();
+}
index ff56ed62869d0360bbc5c37e0006cc3f4b2e7020..b9285b24cd63f2c612b1ab5390a46c52e06919d2 100644 (file)
@@ -14,7 +14,8 @@
 trait Foo { fn dummy(&self) { } }
 impl Foo for usize {}
 
-pub fn dummy() {
+#[no_mangle]
+pub extern "C" fn dummy() {
     // force the vtable to be created
     let _x = &1usize as &Foo;
 }
index 1c478ed2598e4cd89d9aca33b701f52eabd80f13..d84f1617db53aedf6c514efb03c91ea12e726c93 100644 (file)
@@ -17,3 +17,8 @@ pub fn new(id: i32) -> Def {
         Def { id: id }
     }
 }
+
+#[no_mangle]
+pub fn user() {
+    let _ = Def::new(0);
+}
diff --git a/src/test/run-pass-fulldeps/binary-heap-panic-safe.rs b/src/test/run-pass-fulldeps/binary-heap-panic-safe.rs
new file mode 100644 (file)
index 0000000..6139a7d
--- /dev/null
@@ -0,0 +1,101 @@
+// 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.
+
+#![feature(rustc_private, std_panic)]
+
+extern crate rand;
+
+use rand::{thread_rng, Rng};
+use std::panic::{self, AssertUnwindSafe};
+
+use std::collections::BinaryHeap;
+use std::cmp;
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+
+static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
+
+// old binaryheap failed this test
+//
+// Integrity means that all elements are present after a comparison panics,
+// even if the order may not be correct.
+//
+// Destructors must be called exactly once per element.
+fn test_integrity() {
+    #[derive(Eq, PartialEq, Ord, Clone, Debug)]
+    struct PanicOrd<T>(T, bool);
+
+    impl<T> Drop for PanicOrd<T> {
+        fn drop(&mut self) {
+            // update global drop count
+            DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
+        }
+    }
+
+    impl<T: PartialOrd> PartialOrd for PanicOrd<T> {
+        fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
+            if self.1 || other.1 {
+                panic!("Panicking comparison");
+            }
+            self.0.partial_cmp(&other.0)
+        }
+    }
+    let mut rng = thread_rng();
+    const DATASZ: usize = 32;
+    const NTEST: usize = 10;
+
+    // don't use 0 in the data -- we want to catch the zeroed-out case.
+    let data = (1..DATASZ + 1).collect::<Vec<_>>();
+
+    // since it's a fuzzy test, run several tries.
+    for _ in 0..NTEST {
+        for i in 1..DATASZ + 1 {
+            DROP_COUNTER.store(0, Ordering::SeqCst);
+
+            let mut panic_ords: Vec<_> = data.iter()
+                                             .filter(|&&x| x != i)
+                                             .map(|&x| PanicOrd(x, false))
+                                             .collect();
+            let panic_item = PanicOrd(i, true);
+
+            // heapify the sane items
+            rng.shuffle(&mut panic_ords);
+            let mut heap = BinaryHeap::from(panic_ords);
+            let inner_data;
+
+            {
+                // push the panicking item to the heap and catch the panic
+                let thread_result = {
+                    let mut heap_ref = AssertUnwindSafe(&mut heap);
+                    panic::catch_unwind(move || {
+                        heap_ref.push(panic_item);
+                    })
+                };
+                assert!(thread_result.is_err());
+
+                // Assert no elements were dropped
+                let drops = DROP_COUNTER.load(Ordering::SeqCst);
+                assert!(drops == 0, "Must not drop items. drops={}", drops);
+                inner_data = heap.clone().into_vec();
+                drop(heap);
+            }
+            let drops = DROP_COUNTER.load(Ordering::SeqCst);
+            assert_eq!(drops, DATASZ);
+
+            let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::<Vec<_>>();
+            data_sorted.sort();
+            assert_eq!(data_sorted, data);
+        }
+    }
+}
+
+fn main() {
+    test_integrity();
+}
+
diff --git a/src/test/run-pass-fulldeps/env.rs b/src/test/run-pass-fulldeps/env.rs
new file mode 100644 (file)
index 0000000..cf2ea73
--- /dev/null
@@ -0,0 +1,99 @@
+// 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: --test
+
+#![feature(rustc_private, std_panic)]
+
+extern crate rand;
+
+use std::env::*;
+use std::iter::repeat;
+use std::ffi::{OsString, OsStr};
+
+use rand::Rng;
+
+fn make_rand_name() -> OsString {
+    let mut rng = rand::thread_rng();
+    let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
+                                 .collect::<String>());
+    let n = OsString::from(n);
+    assert!(var_os(&n).is_none());
+    n
+}
+
+fn eq(a: Option<OsString>, b: Option<&str>) {
+    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
+}
+
+#[test]
+fn test_set_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    eq(var_os(&n), Some("VALUE"));
+}
+
+#[test]
+fn test_remove_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_set_var_overwrite() {
+    let n = make_rand_name();
+    set_var(&n, "1");
+    set_var(&n, "2");
+    eq(var_os(&n), Some("2"));
+    set_var(&n, "");
+    eq(var_os(&n), Some(""));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_var_big() {
+    let mut s = "".to_string();
+    let mut i = 0;
+    while i < 100 {
+        s.push_str("aaaaaaaaaa");
+        i += 1;
+    }
+    let n = make_rand_name();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_env_set_get_huge() {
+    let n = make_rand_name();
+    let s = repeat("x").take(10000).collect::<String>();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_env_set_var() {
+    let n = make_rand_name();
+
+    let mut e = vars_os();
+    set_var(&n, "VALUE");
+    assert!(!e.any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+
+    assert!(vars_os().any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+}
index 0a4c15a9236b9bc6042b4f510b228a119aed5e95..f17a0494a69c48d9e4d8b6acf39cc3df6086962f 100644 (file)
@@ -41,8 +41,8 @@ fn main() {
     let raw_byte_string_lit_kind = LitKind::ByteStr(Rc::new(b"#\"two\"#".to_vec()));
     assert_eq!(raw_byte_string.node, ExprKind::Lit(P(dummy_spanned(raw_byte_string_lit_kind))));
 
-    // check dotdotdot
-    let closed_range = quote_expr!(&cx, 0 ... 1);
+    // check dotdoteq
+    let closed_range = quote_expr!(&cx, 0 ..= 1);
     assert_eq!(closed_range.node, ExprKind::Range(
         Some(quote_expr!(&cx, 0)),
         Some(quote_expr!(&cx, 1)),
diff --git a/src/test/run-pass-fulldeps/vector-sort-panic-safe.rs b/src/test/run-pass-fulldeps/vector-sort-panic-safe.rs
new file mode 100644 (file)
index 0000000..8230504
--- /dev/null
@@ -0,0 +1,182 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-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-emscripten no threads support
+
+#![feature(rustc_private)]
+#![feature(sort_unstable)]
+#![feature(const_atomic_usize_new)]
+
+extern crate rand;
+
+use rand::{thread_rng, Rng};
+use std::cell::Cell;
+use std::cmp::Ordering;
+use std::panic;
+use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize};
+use std::sync::atomic::Ordering::Relaxed;
+use std::thread;
+
+const MAX_LEN: usize = 80;
+
+static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
+    // FIXME #5244: AtomicUsize is not Copy.
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+];
+
+static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT;
+
+#[derive(Clone, Eq)]
+struct DropCounter {
+    x: u32,
+    id: usize,
+    version: Cell<usize>,
+}
+
+impl PartialEq for DropCounter {
+    fn eq(&self, other: &Self) -> bool {
+        self.partial_cmp(other) == Some(Ordering::Equal)
+    }
+}
+
+impl PartialOrd for DropCounter {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.version.set(self.version.get() + 1);
+        other.version.set(other.version.get() + 1);
+        VERSIONS.fetch_add(2, Relaxed);
+        self.x.partial_cmp(&other.x)
+    }
+}
+
+impl Ord for DropCounter {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.partial_cmp(other).unwrap()
+    }
+}
+
+impl Drop for DropCounter {
+    fn drop(&mut self) {
+        DROP_COUNTS[self.id].fetch_add(1, Relaxed);
+        VERSIONS.fetch_sub(self.version.get(), Relaxed);
+    }
+}
+
+macro_rules! test {
+    ($input:ident, $func:ident) => {
+        let len = $input.len();
+
+        // Work out the total number of comparisons required to sort
+        // this array...
+        let mut count = 0usize;
+        $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) });
+
+        // ... and then panic on each and every single one.
+        for panic_countdown in 0..count {
+            // Refresh the counters.
+            VERSIONS.store(0, Relaxed);
+            for i in 0..len {
+                DROP_COUNTS[i].store(0, Relaxed);
+            }
+
+            let v = $input.to_owned();
+            let _ = thread::spawn(move || {
+                let mut v = v;
+                let mut panic_countdown = panic_countdown;
+                v.$func(|a, b| {
+                    if panic_countdown == 0 {
+                        SILENCE_PANIC.with(|s| s.set(true));
+                        panic!();
+                    }
+                    panic_countdown -= 1;
+                    a.cmp(b)
+                })
+            }).join();
+
+            // Check that the number of things dropped is exactly
+            // what we expect (i.e. the contents of `v`).
+            for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
+                let count = c.load(Relaxed);
+                assert!(count == 1,
+                        "found drop count == {} for i == {}, len == {}",
+                        count, i, len);
+            }
+
+            // Check that the most recent versions of values were dropped.
+            assert_eq!(VERSIONS.load(Relaxed), 0);
+        }
+    }
+}
+
+thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
+
+fn main() {
+    let prev = panic::take_hook();
+    panic::set_hook(Box::new(move |info| {
+        if !SILENCE_PANIC.with(|s| s.get()) {
+            prev(info);
+        }
+    }));
+
+    let mut rng = thread_rng();
+
+    for len in (1..20).chain(70..MAX_LEN) {
+        for &modulus in &[5, 20, 50] {
+            for &has_runs in &[false, true] {
+                let mut input = (0..len)
+                    .map(|id| {
+                        DropCounter {
+                            x: rng.next_u32() % modulus,
+                            id: id,
+                            version: Cell::new(0),
+                        }
+                    })
+                    .collect::<Vec<_>>();
+
+                if has_runs {
+                    for c in &mut input {
+                        c.x = c.id as u32;
+                    }
+
+                    for _ in 0..5 {
+                        let a = rng.gen::<usize>() % len;
+                        let b = rng.gen::<usize>() % len;
+                        if a < b {
+                            input[a..b].reverse();
+                        } else {
+                            input.swap(a, b);
+                        }
+                    }
+                }
+
+                test!(input, sort_by);
+                test!(input, sort_unstable_by);
+            }
+        }
+    }
+}
diff --git a/src/test/run-pass/arbitrary_self_types_silly.rs b/src/test/run-pass/arbitrary_self_types_silly.rs
new file mode 100644 (file)
index 0000000..755a8d7
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types)]
+
+struct Foo;
+struct Bar;
+
+impl std::ops::Deref for Bar {
+    type Target = Foo;
+
+    fn deref(&self) -> &Foo {
+        &Foo
+    }
+}
+
+impl Foo {
+    fn bar(self: Bar) -> i32 { 3 }
+}
+
+fn main() {
+    assert_eq!(3, Bar.bar());
+}
diff --git a/src/test/run-pass/arbitrary_self_types_struct.rs b/src/test/run-pass/arbitrary_self_types_struct.rs
new file mode 100644 (file)
index 0000000..961717d
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+struct Foo {
+    x: i32,
+    y: i32,
+}
+
+impl Foo {
+    fn x(self: &Rc<Self>) -> i32 {
+        self.x
+    }
+
+    fn y(self: Rc<Self>) -> i32 {
+        self.y
+    }
+}
+
+fn main() {
+    let foo = Rc::new(Foo {x: 3, y: 4});
+    assert_eq!(3, foo.x());
+    assert_eq!(4, foo.y());
+}
diff --git a/src/test/run-pass/arbitrary_self_types_trait.rs b/src/test/run-pass/arbitrary_self_types_trait.rs
new file mode 100644 (file)
index 0000000..e74d614
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+trait Trait {
+    fn trait_method<'a>(self: &'a Box<Rc<Self>>) -> &'a [i32];
+}
+
+impl Trait for Vec<i32> {
+    fn trait_method<'a>(self: &'a Box<Rc<Self>>) -> &'a [i32] {
+        &***self
+    }
+}
+
+fn main() {
+    let v = vec![1,2,3];
+
+    assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method());
+}
diff --git a/src/test/run-pass/arbitrary_self_types_unsized_struct.rs b/src/test/run-pass/arbitrary_self_types_unsized_struct.rs
new file mode 100644 (file)
index 0000000..8dc40e7
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+struct Foo<T: ?Sized>(T);
+
+impl Foo<[u8]> {
+    fn len(self: Rc<Self>) -> usize {
+        self.0.len()
+    }
+}
+
+fn main() {
+    let rc = Rc::new(Foo([1u8,2,3])) as Rc<Foo<[u8]>>;
+    assert_eq!(3, rc.len());
+}
diff --git a/src/test/run-pass/assert-eq-trailing-comma.rs b/src/test/run-pass/assert-eq-trailing-comma.rs
new file mode 100644 (file)
index 0000000..d98baf6
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+    assert_eq!(1, 1,);
+}
diff --git a/src/test/run-pass/assert-ne-trailing-comma.rs b/src/test/run-pass/assert-ne-trailing-comma.rs
new file mode 100644 (file)
index 0000000..4d3c29d
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+    assert_ne!(1, 2,);
+}
index 752f5a11375adc68bc48a85fb368963f6c758496..e42aca9ccbd1378c29cff2e7c80765e2237b5e88 100644 (file)
@@ -33,4 +33,7 @@ fn main() {
     take_auto(AutoBool(true));
     take_auto_unsafe(0);
     take_auto_unsafe(AutoBool(true));
+
+    /// Auto traits are allowed in trait object bounds.
+    let _: &(Send + Auto) = &0;
 }
diff --git a/src/test/run-pass/binary-heap-panic-safe.rs b/src/test/run-pass/binary-heap-panic-safe.rs
deleted file mode 100644 (file)
index 93d3345..0000000
+++ /dev/null
@@ -1,99 +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.
-
-#![feature(rand, std_panic)]
-
-use std::__rand::{thread_rng, Rng};
-use std::panic::{self, AssertUnwindSafe};
-
-use std::collections::BinaryHeap;
-use std::cmp;
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
-
-static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
-
-// old binaryheap failed this test
-//
-// Integrity means that all elements are present after a comparison panics,
-// even if the order may not be correct.
-//
-// Destructors must be called exactly once per element.
-fn test_integrity() {
-    #[derive(Eq, PartialEq, Ord, Clone, Debug)]
-    struct PanicOrd<T>(T, bool);
-
-    impl<T> Drop for PanicOrd<T> {
-        fn drop(&mut self) {
-            // update global drop count
-            DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
-        }
-    }
-
-    impl<T: PartialOrd> PartialOrd for PanicOrd<T> {
-        fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
-            if self.1 || other.1 {
-                panic!("Panicking comparison");
-            }
-            self.0.partial_cmp(&other.0)
-        }
-    }
-    let mut rng = thread_rng();
-    const DATASZ: usize = 32;
-    const NTEST: usize = 10;
-
-    // don't use 0 in the data -- we want to catch the zeroed-out case.
-    let data = (1..DATASZ + 1).collect::<Vec<_>>();
-
-    // since it's a fuzzy test, run several tries.
-    for _ in 0..NTEST {
-        for i in 1..DATASZ + 1 {
-            DROP_COUNTER.store(0, Ordering::SeqCst);
-
-            let mut panic_ords: Vec<_> = data.iter()
-                                             .filter(|&&x| x != i)
-                                             .map(|&x| PanicOrd(x, false))
-                                             .collect();
-            let panic_item = PanicOrd(i, true);
-
-            // heapify the sane items
-            rng.shuffle(&mut panic_ords);
-            let mut heap = BinaryHeap::from(panic_ords);
-            let inner_data;
-
-            {
-                // push the panicking item to the heap and catch the panic
-                let thread_result = {
-                    let mut heap_ref = AssertUnwindSafe(&mut heap);
-                    panic::catch_unwind(move || {
-                        heap_ref.push(panic_item);
-                    })
-                };
-                assert!(thread_result.is_err());
-
-                // Assert no elements were dropped
-                let drops = DROP_COUNTER.load(Ordering::SeqCst);
-                assert!(drops == 0, "Must not drop items. drops={}", drops);
-                inner_data = heap.clone().into_vec();
-                drop(heap);
-            }
-            let drops = DROP_COUNTER.load(Ordering::SeqCst);
-            assert_eq!(drops, DATASZ);
-
-            let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::<Vec<_>>();
-            data_sorted.sort();
-            assert_eq!(data_sorted, data);
-        }
-    }
-}
-
-fn main() {
-    test_integrity();
-}
-
diff --git a/src/test/run-pass/enum-non-c-like-repr-int.rs b/src/test/run-pass/enum-non-c-like-repr-int.rs
new file mode 100644 (file)
index 0000000..6e147b0
--- /dev/null
@@ -0,0 +1,173 @@
+// 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.
+
+// This test deserializes an enum in-place by transmuting to a union that
+// should have the same layout, and manipulating the tag and payloads
+// independently. This verifies that `repr(some_int)` has a stable representation,
+// and that we don't miscompile these kinds of manipulations.
+
+use std::time::Duration;
+use std::mem;
+
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+enum MyEnum {
+    A(u32),                 // Single primitive value
+    B { x: u8, y: i16 },    // Composite, and the offset of `y` depends on tag being internal
+    C,                      // Empty
+    D(Option<u32>),         // Contains an enum
+    E(Duration),            // Contains a struct
+}
+
+#[allow(non_snake_case)]
+#[repr(C)]
+union MyEnumRepr {
+    A: MyEnumVariantA,
+    B: MyEnumVariantB,
+    C: MyEnumVariantC,
+    D: MyEnumVariantD,
+    E: MyEnumVariantE,
+}
+
+#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
+#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32);
+#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 }
+#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag);
+#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option<u32>);
+#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration);
+
+fn main() {
+    let result: Vec<Result<MyEnum, ()>> = vec![
+        Ok(MyEnum::A(17)),
+        Ok(MyEnum::B { x: 206, y: 1145 }),
+        Ok(MyEnum::C),
+        Err(()),
+        Ok(MyEnum::D(Some(407))),
+        Ok(MyEnum::D(None)),
+        Ok(MyEnum::E(Duration::from_secs(100))),
+        Err(()),
+    ];
+
+    // Binary serialized version of the above (little-endian)
+    let input: Vec<u8> = vec![
+        0,  17, 0, 0, 0,
+        1,  206,  121, 4,
+        2,
+        8,  /* invalid tag value */
+        3,  0,  151, 1, 0, 0,
+        3,  1,
+        4,  100, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
+        0,  /* incomplete value */
+    ];
+
+    let mut output = vec![];
+    let mut buf = &input[..];
+
+    unsafe {
+        // This should be safe, because we don't match on it unless it's fully formed,
+        // and it doesn't have a destructor.
+        let mut dest: MyEnum = mem::uninitialized();
+        while buf.len() > 0 {
+            match parse_my_enum(&mut dest, &mut buf) {
+                Ok(()) => output.push(Ok(dest)),
+                Err(()) => output.push(Err(())),
+            }
+        }
+    }
+
+    assert_eq!(output, result);
+}
+
+fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
+    unsafe {
+        // Should be correct to do this transmute.
+        let dest: &'a mut MyEnumRepr = mem::transmute(dest);
+        let tag = read_u8(buf)?;
+
+        dest.A.0 = match tag {
+            0 => MyEnumTag::A,
+            1 => MyEnumTag::B,
+            2 => MyEnumTag::C,
+            3 => MyEnumTag::D,
+            4 => MyEnumTag::E,
+            _ => return Err(()),
+        };
+
+        match dest.B.tag {
+            MyEnumTag::A => {
+                dest.A.1 = read_u32_le(buf)?;
+            }
+            MyEnumTag::B => {
+                dest.B.x = read_u8(buf)?;
+                dest.B.y = read_u16_le(buf)? as i16;
+            }
+            MyEnumTag::C => {
+                /* do nothing */
+            }
+            MyEnumTag::D => {
+                let is_some = read_u8(buf)? == 0;
+                if is_some {
+                    dest.D.1 = Some(read_u32_le(buf)?);
+                } else {
+                    dest.D.1 = None;
+                }
+            }
+            MyEnumTag::E => {
+                let secs = read_u64_le(buf)?;
+                let nanos = read_u32_le(buf)?;
+                dest.E.1 = Duration::new(secs, nanos);
+            }
+        }
+        Ok(())
+    }
+}
+
+
+
+// reader helpers
+
+fn read_u64_le(buf: &mut &[u8]) -> Result<u64, ()> {
+    if buf.len() < 8 { return Err(()) }
+    let val = (buf[0] as u64) << 0
+            | (buf[1] as u64) << 8
+            | (buf[2] as u64) << 16
+            | (buf[3] as u64) << 24
+            | (buf[4] as u64) << 32
+            | (buf[5] as u64) << 40
+            | (buf[6] as u64) << 48
+            | (buf[7] as u64) << 56;
+    *buf = &buf[8..];
+    Ok(val)
+}
+
+fn read_u32_le(buf: &mut &[u8]) -> Result<u32, ()> {
+    if buf.len() < 4 { return Err(()) }
+    let val = (buf[0] as u32) << 0
+            | (buf[1] as u32) << 8
+            | (buf[2] as u32) << 16
+            | (buf[3] as u32) << 24;
+    *buf = &buf[4..];
+    Ok(val)
+}
+
+fn read_u16_le(buf: &mut &[u8]) -> Result<u16, ()> {
+    if buf.len() < 2 { return Err(()) }
+    let val = (buf[0] as u16) << 0
+            | (buf[1] as u16) << 8;
+    *buf = &buf[2..];
+    Ok(val)
+}
+
+fn read_u8(buf: &mut &[u8]) -> Result<u8, ()> {
+    if buf.len() < 1 { return Err(()) }
+    let val = buf[0];
+    *buf = &buf[1..];
+    Ok(val)
+}
diff --git a/src/test/run-pass/env.rs b/src/test/run-pass/env.rs
deleted file mode 100644 (file)
index e602fb2..0000000
+++ /dev/null
@@ -1,98 +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.
-
-// compile-flags: --test
-
-#![feature(rand, std_panic)]
-
-use std::env::*;
-use std::__rand as rand;
-use std::__rand::Rng;
-use std::iter::repeat;
-use std::ffi::{OsString, OsStr};
-
-
-fn make_rand_name() -> OsString {
-    let mut rng = rand::thread_rng();
-    let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
-                                 .collect::<String>());
-    let n = OsString::from(n);
-    assert!(var_os(&n).is_none());
-    n
-}
-
-fn eq(a: Option<OsString>, b: Option<&str>) {
-    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
-}
-
-#[test]
-fn test_set_var() {
-    let n = make_rand_name();
-    set_var(&n, "VALUE");
-    eq(var_os(&n), Some("VALUE"));
-}
-
-#[test]
-fn test_remove_var() {
-    let n = make_rand_name();
-    set_var(&n, "VALUE");
-    remove_var(&n);
-    eq(var_os(&n), None);
-}
-
-#[test]
-fn test_set_var_overwrite() {
-    let n = make_rand_name();
-    set_var(&n, "1");
-    set_var(&n, "2");
-    eq(var_os(&n), Some("2"));
-    set_var(&n, "");
-    eq(var_os(&n), Some(""));
-}
-
-#[test]
-#[cfg_attr(target_os = "emscripten", ignore)]
-fn test_var_big() {
-    let mut s = "".to_string();
-    let mut i = 0;
-    while i < 100 {
-        s.push_str("aaaaaaaaaa");
-        i += 1;
-    }
-    let n = make_rand_name();
-    set_var(&n, &s);
-    eq(var_os(&n), Some(&s));
-}
-
-#[test]
-#[cfg_attr(target_os = "emscripten", ignore)]
-fn test_env_set_get_huge() {
-    let n = make_rand_name();
-    let s = repeat("x").take(10000).collect::<String>();
-    set_var(&n, &s);
-    eq(var_os(&n), Some(&s));
-    remove_var(&n);
-    eq(var_os(&n), None);
-}
-
-#[test]
-fn test_env_set_var() {
-    let n = make_rand_name();
-
-    let mut e = vars_os();
-    set_var(&n, "VALUE");
-    assert!(!e.any(|(k, v)| {
-        &*k == &*n && &*v == "VALUE"
-    }));
-
-    assert!(vars_os().any(|(k, v)| {
-        &*k == &*n && &*v == "VALUE"
-    }));
-}
diff --git a/src/test/run-pass/issue-45731.rs b/src/test/run-pass/issue-45731.rs
new file mode 100644 (file)
index 0000000..ec35035
--- /dev/null
@@ -0,0 +1,34 @@
+// 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:--test -g
+
+use std::{env, panic, fs};
+
+#[cfg(target_os = "macos")]
+#[test]
+fn simple_test() {
+    // Find our dSYM and replace the DWARF binary with an empty file
+    let mut dsym_path = env::current_exe().unwrap();
+    let executable_name = dsym_path.file_name().unwrap().to_str().unwrap().to_string();
+    assert!(dsym_path.pop()); // Pop executable
+    dsym_path.push(format!("{}.dSYM/Contents/Resources/DWARF/{0}", executable_name));
+    {
+        let file = fs::OpenOptions::new().read(false).write(true).truncate(true).create(false)
+            .open(&dsym_path).unwrap();
+    }
+
+    env::set_var("RUST_BACKTRACE", "1");
+
+    // We don't need to die of panic, just trigger a backtrace
+    let _ = panic::catch_unwind(|| {
+        assert!(false);
+    });
+}
diff --git a/src/test/run-pass/saturating-float-casts.rs b/src/test/run-pass/saturating-float-casts.rs
new file mode 100644 (file)
index 0000000..c8fa49c
--- /dev/null
@@ -0,0 +1,144 @@
+// 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.
+
+// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction.
+// compile-flags: -Z saturating-float-casts
+
+#![feature(test, i128, i128_type, stmt_expr_attributes)]
+#![deny(overflowing_literals)]
+extern crate test;
+
+use std::{f32, f64};
+use std::{u8, i8, u16, i16, u32, i32, u64, i64};
+#[cfg(not(target_os="emscripten"))]
+use std::{u128, i128};
+use test::black_box;
+
+macro_rules! test {
+    ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => (
+        // black_box disables constant evaluation to test run-time conversions:
+        assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected,
+                    "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+    );
+
+    ($fval:expr, f* -> $ity:ident, $ival:expr) => (
+        test!($fval, f32 -> $ity, $ival);
+        test!($fval, f64 -> $ity, $ival);
+    )
+}
+
+// This macro tests const eval in addition to run-time evaluation.
+// If and when saturating casts are adopted, this macro should be merged with test!() to ensure
+// that run-time and const eval agree on inputs that currently trigger a const eval error.
+macro_rules! test_c {
+    ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ({
+        test!($val, $src_ty -> $dest_ty, $expected);
+        {
+            const X: $src_ty = $val;
+            const Y: $dest_ty = X as $dest_ty;
+            assert_eq!(Y, $expected,
+                        "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+        }
+    });
+
+    ($fval:expr, f* -> $ity:ident, $ival:expr) => (
+        test_c!($fval, f32 -> $ity, $ival);
+        test_c!($fval, f64 -> $ity, $ival);
+    )
+}
+
+macro_rules! common_fptoi_tests {
+    ($fty:ident -> $($ity:ident)+) => ({ $(
+        test!($fty::NAN, $fty -> $ity, 0);
+        test!($fty::INFINITY, $fty -> $ity, $ity::MAX);
+        test!($fty::NEG_INFINITY, $fty -> $ity, $ity::MIN);
+        // These two tests are not solely float->int tests, in particular the latter relies on
+        // `u128::MAX as f32` not being UB. But that's okay, since this file tests int->float
+        // as well, the test is just slightly misplaced.
+        test!($ity::MIN as $fty, $fty -> $ity, $ity::MIN);
+        test!($ity::MAX as $fty, $fty -> $ity, $ity::MAX);
+        test_c!(0., $fty -> $ity, 0);
+        test_c!($fty::MIN_POSITIVE, $fty -> $ity, 0);
+        test!(-0.9, $fty -> $ity, 0);
+        test_c!(1., $fty -> $ity, 1);
+        test_c!(42., $fty -> $ity, 42);
+    )+ });
+
+    (f* -> $($ity:ident)+) => ({
+        common_fptoi_tests!(f32 -> $($ity)+);
+        common_fptoi_tests!(f64 -> $($ity)+);
+    })
+}
+
+macro_rules! fptoui_tests {
+    ($fty: ident -> $($ity: ident)+) => ({ $(
+        test!(-0., $fty -> $ity, 0);
+        test!(-$fty::MIN_POSITIVE, $fty -> $ity, 0);
+        test!(-0.99999994, $fty -> $ity, 0);
+        test!(-1., $fty -> $ity, 0);
+        test!(-100., $fty -> $ity, 0);
+        test!(#[allow(overflowing_literals)] -1e50, $fty -> $ity, 0);
+        test!(#[allow(overflowing_literals)] -1e130, $fty -> $ity, 0);
+    )+ });
+
+    (f* -> $($ity:ident)+) => ({
+        fptoui_tests!(f32 -> $($ity)+);
+        fptoui_tests!(f64 -> $($ity)+);
+    })
+}
+
+pub fn main() {
+    common_fptoi_tests!(f* -> i8 i16 i32 i64 u8 u16 u32 u64);
+    fptoui_tests!(f* -> u8 u16 u32 u64);
+    // FIXME emscripten does not support i128
+    #[cfg(not(target_os="emscripten"))] {
+        common_fptoi_tests!(f* -> i128 u128);
+        fptoui_tests!(f* -> u128);
+    }
+
+    // The following tests cover edge cases for some integer types.
+
+    // # u8
+    test_c!(254., f* -> u8, 254);
+    test!(256., f* -> u8, 255);
+
+    // # i8
+    test_c!(-127., f* -> i8, -127);
+    test!(-129., f* -> i8, -128);
+    test_c!(126., f* -> i8, 126);
+    test!(128., f* -> i8, 127);
+
+    // # i32
+    // -2147483648. is i32::MIN (exactly)
+    test_c!(-2147483648., f* -> i32, i32::MIN);
+    // 2147483648. is i32::MAX rounded up
+    test!(2147483648., f32 -> i32, 2147483647);
+    // With 24 significand bits, floats with magnitude in [2^30 + 1, 2^31] are rounded to
+    // multiples of 2^7. Therefore, nextDown(round(i32::MAX)) is 2^31 - 128:
+    test_c!(2147483520., f32 -> i32, 2147483520);
+    // Similarly, nextUp(i32::MIN) is i32::MIN + 2^8 and nextDown(i32::MIN) is i32::MIN - 2^7
+    test!(-2147483904., f* -> i32, i32::MIN);
+    test_c!(-2147483520., f* -> i32, -2147483520);
+
+    // # u32
+    // round(MAX) and nextUp(round(MAX))
+    test_c!(4294967040., f* -> u32, 4294967040);
+    test!(4294967296., f* -> u32, 4294967295);
+
+    // # u128
+    #[cfg(not(target_os="emscripten"))]
+    {
+        // float->int:
+        test_c!(f32::MAX, f32 -> u128, 0xffffff00000000000000000000000000);
+        // nextDown(f32::MAX) = 2^128 - 2 * 2^104
+        const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.;
+        test_c!(SECOND_LARGEST_F32, f32 -> u128, 0xfffffe00000000000000000000000000);
+    }
+}
index 5d4ecbb5f81722a4f32f24f50905cd56056c00ef..1894cd0084bcb167a4c4d8e50da6efaf6390fb92 100644 (file)
@@ -35,6 +35,7 @@ macro_rules! all_eq {
     fn simd_sub<T>(x: T, y: T) -> T;
     fn simd_mul<T>(x: T, y: T) -> T;
     fn simd_div<T>(x: T, y: T) -> T;
+    fn simd_rem<T>(x: T, y: T) -> T;
     fn simd_shl<T>(x: T, y: T) -> T;
     fn simd_shr<T>(x: T, y: T) -> T;
     fn simd_and<T>(x: T, y: T) -> T;
@@ -72,9 +73,22 @@ fn main() {
         all_eq!(simd_sub(z2, z1), f32x4(1.0, 1.0, 1.0, 1.0));
         all_eq!(simd_sub(z1, z2), f32x4(-1.0, -1.0, -1.0, -1.0));
 
+        all_eq!(simd_div(x1, x1), i32x4(1, 1, 1, 1));
+        all_eq!(simd_div(i32x4(2, 4, 6, 8), i32x4(2, 2, 2, 2)), x1);
+        all_eq!(simd_div(y1, y1), u32x4(1, 1, 1, 1));
+        all_eq!(simd_div(u32x4(2, 4, 6, 8), u32x4(2, 2, 2, 2)), y1);
+        all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0));
         all_eq!(simd_div(z1, z2), f32x4(1.0/2.0, 2.0/3.0, 3.0/4.0, 4.0/5.0));
         all_eq!(simd_div(z2, z1), f32x4(2.0/1.0, 3.0/2.0, 4.0/3.0, 5.0/4.0));
 
+        all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0));
+        all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1));
+        all_eq!(simd_rem(y1, y1), u32x4(0, 0, 0, 0));
+        all_eq!(simd_rem(y2, y1), u32x4(0, 1, 1, 1));
+        all_eq!(simd_rem(z1, z1), f32x4(0.0, 0.0, 0.0, 0.0));
+        all_eq!(simd_rem(z1, z2), z1);
+        all_eq!(simd_rem(z2, z1), f32x4(0.0, 1.0, 1.0, 1.0));
+
         all_eq!(simd_shl(x1, x2), i32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5));
         all_eq!(simd_shl(x2, x1), i32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4));
         all_eq!(simd_shl(y1, y2), u32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5));
diff --git a/src/test/run-pass/u128-as-f32.rs b/src/test/run-pass/u128-as-f32.rs
new file mode 100644 (file)
index 0000000..117e520
--- /dev/null
@@ -0,0 +1,58 @@
+// 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.
+
+// ignore-emscripten u128 not supported
+
+#![feature(test, i128, i128_type)]
+#![deny(overflowing_literals)]
+extern crate test;
+
+use std::f32;
+use std::u128;
+use test::black_box;
+
+macro_rules! test {
+    ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ({
+        {
+            const X: $src_ty = $val;
+            const Y: $dest_ty = X as $dest_ty;
+            assert_eq!(Y, $expected,
+                        "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+        }
+        // black_box disables constant evaluation to test run-time conversions:
+        assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected,
+                    "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+    });
+}
+
+pub fn main() {
+    // nextDown(f32::MAX) = 2^128 - 2 * 2^104
+    const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.;
+
+    // f32::MAX - 0.5 ULP and smaller should be rounded down
+    test!(0xfffffe00000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32);
+    test!(0xfffffe7fffffffffffffffffffffffff, u128 -> f32, SECOND_LARGEST_F32);
+    test!(0xfffffe80000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32);
+    // numbers within < 0.5 ULP of f32::MAX it should be rounded to f32::MAX
+    test!(0xfffffe80000000000000000000000001, u128 -> f32, f32::MAX);
+    test!(0xfffffeffffffffffffffffffffffffff, u128 -> f32, f32::MAX);
+    test!(0xffffff00000000000000000000000000, u128 -> f32, f32::MAX);
+    test!(0xffffff00000000000000000000000001, u128 -> f32, f32::MAX);
+    test!(0xffffff7fffffffffffffffffffffffff, u128 -> f32, f32::MAX);
+    // f32::MAX + 0.5 ULP and greater should be rounded to infinity
+    test!(0xffffff80000000000000000000000000, u128 -> f32, f32::INFINITY);
+    test!(0xffffff80000000f00000000000000000, u128 -> f32, f32::INFINITY);
+    test!(0xffffff87ffffffffffffffff00000001, u128 -> f32, f32::INFINITY);
+
+    // u128->f64 should not be affected by the u128->f32 checks
+    test!(0xffffff80000000000000000000000000, u128 -> f64,
+          340282356779733661637539395458142568448.0);
+    test!(u128::MAX, u128 -> f64, 340282366920938463463374607431768211455.0);
+}
diff --git a/src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs b/src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs
new file mode 100644 (file)
index 0000000..d902ebc
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+#![allow(unused)]
+
+fn foo<F>(f: F)
+    where F: FnOnce()
+{
+}
+
+fn main() {
+    // Test that this closure is inferred to `FnOnce`
+    // because it moves from `y.as<Option::Some>.0`:
+    let x = Some(vec![1, 2, 3]);
+    foo(|| {
+        match x {
+            Some(y) => { }
+            None => { }
+        }
+    });
+
+    // Test that this closure is inferred to `FnOnce`
+    // because it moves from `y.0`:
+    let y = (vec![1, 2, 3], 0);
+    foo(|| {
+        let x = y.0;
+    });
+}
diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs
deleted file mode 100644 (file)
index c6a1859..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-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-emscripten no threads support
-
-#![feature(rand)]
-#![feature(sort_unstable)]
-#![feature(const_atomic_usize_new)]
-
-use std::__rand::{thread_rng, Rng};
-use std::cell::Cell;
-use std::cmp::Ordering;
-use std::panic;
-use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize};
-use std::sync::atomic::Ordering::Relaxed;
-use std::thread;
-
-const MAX_LEN: usize = 80;
-
-static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
-    // FIXME #5244: AtomicUsize is not Copy.
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-];
-
-static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT;
-
-#[derive(Clone, Eq)]
-struct DropCounter {
-    x: u32,
-    id: usize,
-    version: Cell<usize>,
-}
-
-impl PartialEq for DropCounter {
-    fn eq(&self, other: &Self) -> bool {
-        self.partial_cmp(other) == Some(Ordering::Equal)
-    }
-}
-
-impl PartialOrd for DropCounter {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        self.version.set(self.version.get() + 1);
-        other.version.set(other.version.get() + 1);
-        VERSIONS.fetch_add(2, Relaxed);
-        self.x.partial_cmp(&other.x)
-    }
-}
-
-impl Ord for DropCounter {
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.partial_cmp(other).unwrap()
-    }
-}
-
-impl Drop for DropCounter {
-    fn drop(&mut self) {
-        DROP_COUNTS[self.id].fetch_add(1, Relaxed);
-        VERSIONS.fetch_sub(self.version.get(), Relaxed);
-    }
-}
-
-macro_rules! test {
-    ($input:ident, $func:ident) => {
-        let len = $input.len();
-
-        // Work out the total number of comparisons required to sort
-        // this array...
-        let mut count = 0usize;
-        $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) });
-
-        // ... and then panic on each and every single one.
-        for panic_countdown in 0..count {
-            // Refresh the counters.
-            VERSIONS.store(0, Relaxed);
-            for i in 0..len {
-                DROP_COUNTS[i].store(0, Relaxed);
-            }
-
-            let v = $input.to_owned();
-            let _ = thread::spawn(move || {
-                let mut v = v;
-                let mut panic_countdown = panic_countdown;
-                v.$func(|a, b| {
-                    if panic_countdown == 0 {
-                        SILENCE_PANIC.with(|s| s.set(true));
-                        panic!();
-                    }
-                    panic_countdown -= 1;
-                    a.cmp(b)
-                })
-            }).join();
-
-            // Check that the number of things dropped is exactly
-            // what we expect (i.e. the contents of `v`).
-            for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
-                let count = c.load(Relaxed);
-                assert!(count == 1,
-                        "found drop count == {} for i == {}, len == {}",
-                        count, i, len);
-            }
-
-            // Check that the most recent versions of values were dropped.
-            assert_eq!(VERSIONS.load(Relaxed), 0);
-        }
-    }
-}
-
-thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
-
-fn main() {
-    let prev = panic::take_hook();
-    panic::set_hook(Box::new(move |info| {
-        if !SILENCE_PANIC.with(|s| s.get()) {
-            prev(info);
-        }
-    }));
-
-    let mut rng = thread_rng();
-
-    for len in (1..20).chain(70..MAX_LEN) {
-        for &modulus in &[5, 20, 50] {
-            for &has_runs in &[false, true] {
-                let mut input = (0..len)
-                    .map(|id| {
-                        DropCounter {
-                            x: rng.next_u32() % modulus,
-                            id: id,
-                            version: Cell::new(0),
-                        }
-                    })
-                    .collect::<Vec<_>>();
-
-                if has_runs {
-                    for c in &mut input {
-                        c.x = c.id as u32;
-                    }
-
-                    for _ in 0..5 {
-                        let a = rng.gen::<usize>() % len;
-                        let b = rng.gen::<usize>() % len;
-                        if a < b {
-                            input[a..b].reverse();
-                        } else {
-                            input.swap(a, b);
-                        }
-                    }
-                }
-
-                test!(input, sort_by);
-                test!(input, sort_unstable_by);
-            }
-        }
-    }
-}
diff --git a/src/test/rustdoc/issue-45584.rs b/src/test/rustdoc/issue-45584.rs
new file mode 100644 (file)
index 0000000..6d6ae3d
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+#![crate_name = "foo"]
+
+pub trait Bar<T, U> {}
+
+// @has 'foo/struct.Foo1.html'
+pub struct Foo1;
+// @count - '//*[@class="impl"]' 1
+// @has - '//*[@class="impl"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
+impl Bar<Foo1, &'static Foo1> for Foo1 {}
+
+// @has 'foo/struct.Foo2.html'
+pub struct Foo2;
+// @count - '//*[@class="impl"]' 1
+// @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8"
+impl Bar<&'static Foo2, Foo2> for u8 {}
index f0d55ef6e9fcd1cc5760886c5aebe5df5f2eca84..478477dea61ed9b3fa54a36436cd764b77b93d15 100644 (file)
@@ -21,4 +21,4 @@
 pub fn dummy() {}
 
 // ensure that `extern crate foo;` was inserted into code snips automatically:
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=extern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run"
index 9eb8dec51a7f2f6f86489eb04b49df533cdc2952..8e193efaf85047f95779e5df6629333add9f66fd 100644 (file)
@@ -34,6 +34,6 @@
 //! }
 //! ```
 
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run"
diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs
new file mode 100644 (file)
index 0000000..9be4044
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// @has foo/trait.Foo.html
+// @has - '//*[@class="sidebar-title"][@href="#required-methods"]' 'Required Methods'
+// @has - '//*[@class="sidebar-links"]/a' 'bar'
+// @has - '//*[@class="sidebar-title"][@href="#provided-methods"]' 'Provided Methods'
+// @has - '//*[@class="sidebar-links"]/a' 'foo'
+// @has - '//*[@class="sidebar-title"][@href="#associated-const"]' 'Associated Constants'
+// @has - '//*[@class="sidebar-links"]/a' 'BAR'
+// @has - '//*[@class="sidebar-title"][@href="#associated-types"]' 'Associated Types'
+// @has - '//*[@class="sidebar-links"]/a' 'Output'
+pub trait Foo {
+    const BAR: u32 = 0;
+    type Output: ?Sized;
+
+    fn foo() {}
+    fn bar() -> Self::Output;
+}
+
+// @has foo/struct.Bar.html
+// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u'
+// @!has - '//*[@class="sidebar-links"]/a' 'w'
+pub struct Bar {
+    pub f: u32,
+    pub u: u32,
+    w: u32,
+}
+
+// @has foo/enum.En.html
+// @has - '//*[@class="sidebar-title"][@href="#variants"]' 'Variants'
+// @has - '//*[@class="sidebar-links"]/a' 'foo'
+// @has - '//*[@class="sidebar-links"]/a' 'bar'
+pub enum En {
+    foo,
+    bar,
+}
+
+// @has foo/union.MyUnion.html
+// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2'
+// @!has - '//*[@class="sidebar-links"]/a' 'w'
+pub union MyUnion {
+    pub f1: u32,
+    pub f2: f32,
+    w: u32,
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.rs b/src/test/ui/borrowck/borrowck-closures-two-mut.rs
new file mode 100644 (file)
index 0000000..182b3d7
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that two closures cannot simultaneously have mutable
+// access to the variable, whether that mutable access be used
+// for direct assignment or for taking mutable ref. Issue #6801.
+
+// compile-flags: -Z emit-end-regions -Z borrowck-mir
+
+#![feature(box_syntax)]
+
+fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
+
+fn a() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 4);
+    let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+}
+
+fn set(x: &mut isize) {
+    *x = 4;
+}
+
+fn b() {
+    let mut x = 3;
+    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
+}
+
+fn c() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 5);
+    let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+}
+
+fn d() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 5);
+    let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+    //~^ ERROR cannot borrow `x` as mutable more than once
+}
+
+fn g() {
+    struct Foo {
+        f: Box<isize>
+    }
+
+    let mut x: Box<_> = box Foo { f: box 3 };
+    let c1 = to_fn_mut(|| set(&mut *x.f));
+    let c2 = to_fn_mut(|| set(&mut *x.f));
+    //~^ ERROR cannot borrow `x` as mutable more than once
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr
new file mode 100644 (file)
index 0000000..fc8a7f2
--- /dev/null
@@ -0,0 +1,146 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:24:24
+   |
+23 |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+24 |     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
+25 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:34:24
+   |
+33 |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+34 |     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
+35 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:40:24
+   |
+39 |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+40 |     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
+41 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:46:24
+   |
+45 |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+46 |     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
+47 |     //~^ ERROR cannot borrow `x` as mutable more than once
+48 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:57:24
+   |
+56 |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+57 |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+58 |     //~^ ERROR cannot borrow `x` as mutable more than once
+59 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:24:24
+   |
+23 |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+24 |     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
+25 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:34:24
+   |
+33 |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+34 |     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
+35 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:40:24
+   |
+39 |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+40 |     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
+41 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:46:24
+   |
+45 |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+46 |     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
+47 |     //~^ ERROR cannot borrow `x` as mutable more than once
+48 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:57:24
+   |
+56 |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+57 |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+58 |     //~^ ERROR cannot borrow `x` as mutable more than once
+59 | }
+   | - first borrow ends here
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/borrowck/borrowck-reinit.rs b/src/test/ui/borrowck/borrowck-reinit.rs
new file mode 100644 (file)
index 0000000..5547cb3
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+// compile-flags: -Z borrowck-mir -Z emit-end-regions
+
+fn main() {
+    let mut x = Box::new(0);
+    let _u = x; // error shouldn't note this move
+    x = Box::new(1);
+    drop(x);
+    let _ = (1,x);
+}
diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr
new file mode 100644 (file)
index 0000000..767d65c
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0382]: use of moved value: `x` (Ast)
+  --> $DIR/borrowck-reinit.rs:18:16
+   |
+17 |     drop(x);
+   |          - value moved here
+18 |     let _ = (1,x);
+   |                ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x` (Mir)
+  --> $DIR/borrowck-reinit.rs:18:16
+   |
+17 |     drop(x);
+   |          - value moved here
+18 |     let _ = (1,x);
+   |                ^ value use here after move
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-pattern-irrefutable.rs b/src/test/ui/const-pattern-irrefutable.rs
new file mode 100644 (file)
index 0000000..af0b95e
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+mod foo {
+    pub const b: u8 = 2;
+    pub const d: u8 = 2;
+}
+
+use foo::b as c;
+use foo::d;
+
+const a: u8 = 2;
+
+fn main() {
+    let a = 4; //~ ERROR refutable pattern in local binding: `_` not covered
+    let c = 4; //~ ERROR refutable pattern in local binding: `_` not covered
+    let d = 4; //~ ERROR refutable pattern in local binding: `_` not covered
+    fn f() {} // Check that the `NOTE`s still work with an item here (c.f. issue #35115).
+}
diff --git a/src/test/ui/const-pattern-irrefutable.stderr b/src/test/ui/const-pattern-irrefutable.stderr
new file mode 100644 (file)
index 0000000..af48b77
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0005]: refutable pattern in local binding: `_` not covered
+  --> $DIR/const-pattern-irrefutable.rs:22:9
+   |
+22 |     let a = 4; //~ ERROR refutable pattern in local binding: `_` not covered
+   |         ^ interpreted as a constant pattern, not new variable
+
+error[E0005]: refutable pattern in local binding: `_` not covered
+  --> $DIR/const-pattern-irrefutable.rs:23:9
+   |
+23 |     let c = 4; //~ ERROR refutable pattern in local binding: `_` not covered
+   |         ^ interpreted as a constant pattern, not new variable
+
+error[E0005]: refutable pattern in local binding: `_` not covered
+  --> $DIR/const-pattern-irrefutable.rs:24:9
+   |
+24 |     let d = 4; //~ ERROR refutable pattern in local binding: `_` not covered
+   |         ^ interpreted as a constant pattern, not new variable
+
+error: aborting due to 3 previous errors
+
index 84db85ac092dbfbf3d199d7d489ca97983da83db..4dad6d60b402ea2172c52fe359e0cebbe43eedce 100644 (file)
@@ -1,4 +1,4 @@
-error: invalid reference to argument `0` (no arguments given)
+error: 1 positional argument in format string, but no arguments were given
   --> $DIR/main.rs:16:5
    |
 16 |     myprintln!("{}"); //~ ERROR in this macro
diff --git a/src/test/ui/issue-33941.rs b/src/test/ui/issue-33941.rs
new file mode 100644 (file)
index 0000000..eb111d3
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::HashMap;
+
+fn main() {
+    for _ in HashMap::new().iter().cloned() {}
+}
diff --git a/src/test/ui/issue-33941.stderr b/src/test/ui/issue-33941.stderr
new file mode 100644 (file)
index 0000000..5a8d1fa
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:14:36
+   |
+14 |     for _ in HashMap::new().iter().cloned() {}
+   |                                    ^^^^^^ expected tuple, found reference
+   |
+   = note: expected type `(&_, &_)`
+              found type `&_`
+
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:14:5
+   |
+14 |     for _ in HashMap::new().iter().cloned() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |
+   = note: expected type `(&_, &_)`
+              found type `&_`
+   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+
+error: aborting due to 2 previous errors
+
index 9beae91540abfd09a1ebdd8e6d68c2b72e8b2c69..e7afbb574efd7d4705ec3859d407be566d5de9f7 100644 (file)
@@ -13,14 +13,5 @@ error: expected type, found keyword `true`
 18 |     foo!(true);
    |          ^^^^ expecting a type here because of type ascription
 
-error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true`
-  --> $DIR/issue-44406.rs:18:10
-   |
-13 |         bar(baz: $rest)
-   |                 - expected one of 20 possible tokens here
-...
-18 |     foo!(true);
-   |          ^^^^ unexpected token
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.rs
new file mode 100644 (file)
index 0000000..833fc28
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+#[deny(unused_unsafe)]
+fn main() {
+    let mut v = Vec::<i32>::with_capacity(24);
+
+    unsafe {
+        let f = |v: &mut Vec<_>| {
+            unsafe {
+                v.set_len(24);
+                |w: &mut Vec<u32>| { unsafe {
+                    w.set_len(32);
+                } };
+            }
+            |x: &mut Vec<u32>| { unsafe {
+                x.set_len(40);
+            } };
+        };
+
+        v.set_len(0);
+        f(&mut v);
+    }
+
+    |y: &mut Vec<u32>| { unsafe {
+        y.set_len(48);
+    } };
+}
diff --git a/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.stderr b/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.stderr
new file mode 100644 (file)
index 0000000..5c58b19
--- /dev/null
@@ -0,0 +1,71 @@
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:17:13
+   |
+17 | /             unsafe {
+18 | |                 v.set_len(24);
+19 | |                 |w: &mut Vec<u32>| { unsafe {
+20 | |                     w.set_len(32);
+21 | |                 } };
+22 | |             }
+   | |_____________^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:11:8
+   |
+11 | #[deny(unused_unsafe)]
+   |        ^^^^^^^^^^^^^
+note: because it's nested under this `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:15:5
+   |
+15 | /     unsafe {
+16 | |         let f = |v: &mut Vec<_>| {
+17 | |             unsafe {
+18 | |                 v.set_len(24);
+...  |
+29 | |         f(&mut v);
+30 | |     }
+   | |_____^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:19:38
+   |
+19 |                   |w: &mut Vec<u32>| { unsafe {
+   |  ______________________________________^
+20 | |                     w.set_len(32);
+21 | |                 } };
+   | |_________________^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:17:13
+   |
+17 | /             unsafe {
+18 | |                 v.set_len(24);
+19 | |                 |w: &mut Vec<u32>| { unsafe {
+20 | |                     w.set_len(32);
+21 | |                 } };
+22 | |             }
+   | |_____________^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:23:34
+   |
+23 |               |x: &mut Vec<u32>| { unsafe {
+   |  __________________________________^
+24 | |                 x.set_len(40);
+25 | |             } };
+   | |_____________^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:15:5
+   |
+15 | /     unsafe {
+16 | |         let f = |v: &mut Vec<_>| {
+17 | |             unsafe {
+18 | |                 v.set_len(24);
+...  |
+29 | |         f(&mut v);
+30 | |     }
+   | |_____^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/issue-45730.rs b/src/test/ui/issue-45730.rs
new file mode 100644 (file)
index 0000000..f725d69
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+fn main() {
+    let x: *const _ = 0 as _;
+
+    let x: *const _ = 0 as *const _;
+    let y: Option<*const fmt::Debug> = Some(x) as _;
+
+    let x = 0 as *const i32 as *const _ as *mut _;
+}
diff --git a/src/test/ui/issue-45730.stderr b/src/test/ui/issue-45730.stderr
new file mode 100644 (file)
index 0000000..c4f2e85
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:13:23
+   |
+13 |     let x: *const _ = 0 as _;
+   |                       ^^^^^-
+   |                            |
+   |                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:15:23
+   |
+15 |     let x: *const _ = 0 as *const _;
+   |                       ^^^^^--------
+   |                            |
+   |                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:18:13
+   |
+18 |     let x = 0 as *const i32 as *const _ as *mut _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------
+   |                                            |
+   |                                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.rs b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.rs
new file mode 100644 (file)
index 0000000..04112c3
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+    field: i32,
+}
+
+fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
+    if true {
+        let p: &i32 = &a.field;
+        &*p
+    } else {
+        &*x
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr
new file mode 100644 (file)
index 0000000..613c903
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/42701_one_named_and_one_anonymous.rs:20:9
+   |
+15 | fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
+   |                         - consider changing the type of `x` to `&'a i32`
+...
+20 |         &*x
+   |         ^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs
new file mode 100644 (file)
index 0000000..55752f7
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Clone)]
+enum Foo<'a> {
+    Bar(&'a str),
+}
+
+impl<'a> Foo<'a> {
+    fn bar(&self, other: Foo) -> Foo<'a> {
+        match *self {
+            Foo::Bar(s) => {
+                if s == "test" {
+                    other
+                } else {
+                    self.clone()
+                }
+            }
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr
new file mode 100644 (file)
index 0000000..d1660a6
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `other`
+  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21
+   |
+17 |     fn bar(&self, other: Foo) -> Foo<'a> {
+   |                   ----- consider changing the type of `other` to `Foo<'a>`
+...
+21 |                     other
+   |                     ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
new file mode 100644 (file)
index 0000000..5d18200
--- /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.
+trait Foo<'a> {}
+impl<'a, T> Foo<'a> for T {}
+
+fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+    where i32: Foo<'a>,
+          u32: Foo<'b>
+{
+    x.push(y);
+}
+fn main() {
+let x = baz;
+}
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr
new file mode 100644 (file)
index 0000000..980f14a
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12
+   |
+13 | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+   |                                       - consider changing the type of `y` to `&'a T`
+...
+17 |     x.push(y);
+   |            ^ lifetime `'a` required
+
+error: aborting due to previous error
+
index 7356fc11862f6e104d004cd642852161b18e5e1b..495af8ae208f640acc74d4a986432503449a515f 100644 (file)
@@ -1,35 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/ex2c-push-inference-variable.rs:16:13
-   |
-16 |     let z = Ref { data: y.data };
-   |             ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
-  --> $DIR/ex2c-push-inference-variable.rs:15:1
-   |
-15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-16 | |     let z = Ref { data: y.data };
-17 | |     x.push(z);
-18 | | }
-   | |_^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/ex2c-push-inference-variable.rs:16:25
-   |
-16 |     let z = Ref { data: y.data };
-   |                         ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
-  --> $DIR/ex2c-push-inference-variable.rs:15:1
-   |
-15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-16 | |     let z = Ref { data: y.data };
-17 | |     x.push(z);
-18 | | }
-   | |_^
-note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _>)
+error[E0623]: lifetime mismatch
   --> $DIR/ex2c-push-inference-variable.rs:17:12
    |
+15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+16 |     let z = Ref { data: y.data };
 17 |     x.push(z);
-   |            ^
+   |            ^ ...but data from `y` flows into `x` here
 
 error: aborting due to previous error
 
index 38b0acf9339e0e89595a6c0ee889abca1f2c221e..1f250a888472c55f43c03fcd82c8e56d8b789728 100644 (file)
@@ -1,37 +1,10 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/ex2d-push-inference-variable-2.rs:17:13
-   |
-17 |     let b = Ref { data: y.data };
-   |             ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
-  --> $DIR/ex2d-push-inference-variable-2.rs:15:1
-   |
-15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-16 | |     let a: &mut Vec<Ref<i32>> = x;
-17 | |     let b = Ref { data: y.data };
-18 | |     a.push(b);
-19 | | }
-   | |_^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/ex2d-push-inference-variable-2.rs:17:25
-   |
-17 |     let b = Ref { data: y.data };
-   |                         ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
-  --> $DIR/ex2d-push-inference-variable-2.rs:15:1
-   |
-15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-16 | |     let a: &mut Vec<Ref<i32>> = x;
-17 | |     let b = Ref { data: y.data };
-18 | |     a.push(b);
-19 | | }
-   | |_^
-note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i32>>, found &mut std::vec::Vec<Ref<'b, i32>>)
+error[E0623]: lifetime mismatch
   --> $DIR/ex2d-push-inference-variable-2.rs:16:33
    |
+15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
 16 |     let a: &mut Vec<Ref<i32>> = x;
-   |                                 ^
+   |                                 ^ ...but data from `y` flows into `x` here
 
 error: aborting due to previous error
 
index 035e516e8628e9b933157645e651ef281f272c01..343c35b871edea38764ecdaa671978a50a32935c 100644 (file)
@@ -1,37 +1,10 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/ex2e-push-inference-variable-3.rs:17:13
-   |
-17 |     let b = Ref { data: y.data };
-   |             ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
-  --> $DIR/ex2e-push-inference-variable-3.rs:15:1
-   |
-15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-16 | |     let a: &mut Vec<Ref<i32>> = x;
-17 | |     let b = Ref { data: y.data };
-18 | |     Vec::push(a, b);
-19 | | }
-   | |_^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/ex2e-push-inference-variable-3.rs:17:25
-   |
-17 |     let b = Ref { data: y.data };
-   |                         ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
-  --> $DIR/ex2e-push-inference-variable-3.rs:15:1
-   |
-15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
-16 | |     let a: &mut Vec<Ref<i32>> = x;
-17 | |     let b = Ref { data: y.data };
-18 | |     Vec::push(a, b);
-19 | | }
-   | |_^
-note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i32>>, found &mut std::vec::Vec<Ref<'b, i32>>)
+error[E0623]: lifetime mismatch
   --> $DIR/ex2e-push-inference-variable-3.rs:16:33
    |
+15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
 16 |     let a: &mut Vec<Ref<i32>> = x;
-   |                                 ^
+   |                                 ^ ...but data from `y` flows into `x` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs
deleted file mode 100644 (file)
index 5d18200..0000000
+++ /dev/null
@@ -1,21 +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<'a> {}
-impl<'a, T> Foo<'a> for T {}
-
-fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
-    where i32: Foo<'a>,
-          u32: Foo<'b>
-{
-    x.push(y);
-}
-fn main() {
-let x = baz;
-}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr
deleted file mode 100644 (file)
index 58f2cb9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-earlybound-regions.rs:17:12
-   |
-13 | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
-   |                               -----      -- these two types are declared with different lifetimes...
-...
-17 |     x.push(y);
-   |            ^ ...but data from `y` flows into `x` here
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/macros/assert_eq_trailing_comma.rs b/src/test/ui/macros/assert_eq_trailing_comma.rs
deleted file mode 100644 (file)
index d98baf6..0000000
+++ /dev/null
@@ -1,13 +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.
-
-fn main() {
-    assert_eq!(1, 1,);
-}
diff --git a/src/test/ui/macros/assert_eq_trailing_comma.stderr b/src/test/ui/macros/assert_eq_trailing_comma.stderr
deleted file mode 100644 (file)
index 1b46e94..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: unexpected end of macro invocation
-  --> $DIR/assert_eq_trailing_comma.rs:12:20
-   |
-12 |     assert_eq!(1, 1,);
-   |                    ^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/macros/assert_ne_trailing_comma.rs b/src/test/ui/macros/assert_ne_trailing_comma.rs
deleted file mode 100644 (file)
index 4d3c29d..0000000
+++ /dev/null
@@ -1,13 +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.
-
-fn main() {
-    assert_ne!(1, 2,);
-}
diff --git a/src/test/ui/macros/assert_ne_trailing_comma.stderr b/src/test/ui/macros/assert_ne_trailing_comma.stderr
deleted file mode 100644 (file)
index 33d2cb0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: unexpected end of macro invocation
-  --> $DIR/assert_ne_trailing_comma.rs:12:20
-   |
-12 |     assert_ne!(1, 2,);
-   |                    ^
-
-error: aborting due to previous error
-
index f21253bb67fb0c10e46458e63aa3997d639283cf..3e782294484e795570a7d284e9c876bd0a849b2b 100644 (file)
@@ -1,4 +1,4 @@
-error: invalid reference to argument `0` (no arguments given)
+error: 1 positional argument in format string, but no arguments were given
   --> $DIR/macro-backtrace-println.rs:24:30
    |
 24 |     ($fmt:expr) => (myprint!(concat!($fmt, "/n")));
diff --git a/src/test/ui/nll/named-region-basic.rs b/src/test/ui/nll/named-region-basic.rs
new file mode 100644 (file)
index 0000000..539c201
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// 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
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
+    &*x
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/named-region-basic.stderr b/src/test/ui/nll/named-region-basic.stderr
new file mode 100644 (file)
index 0000000..42b2aea
--- /dev/null
@@ -0,0 +1,29 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/named-region-basic.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error[E0597]: `*x` does not live long enough
+  --> $DIR/named-region-basic.rs:19:6
+   |
+19 |     &*x
+   |      ^^ does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+note: ...but borrowed value is only valid for the lifetime 'a as defined on the function body at 18:1
+  --> $DIR/named-region-basic.rs:18:1
+   |
+18 | / fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
+19 | |     &*x
+20 | | }
+   | |_^
+
+error: free region `'a` does not outlive `'b`
+  --> $DIR/named-region-basic.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/name-clash-nullary.rs b/src/test/ui/resolve/name-clash-nullary.rs
new file mode 100644 (file)
index 0000000..adf52c6
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+  let None: isize = 42; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/resolve/name-clash-nullary.stderr b/src/test/ui/resolve/name-clash-nullary.stderr
new file mode 100644 (file)
index 0000000..014b1fe
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/name-clash-nullary.rs:12:7
+   |
+12 |   let None: isize = 42; //~ ERROR mismatched types
+   |       ^^^^ expected isize, found enum `std::option::Option`
+   |
+   = note: expected type `isize`
+              found type `std::option::Option<_>`
+
+error: aborting due to previous error
+
index 281c21f6f85eeee1fd4b9198a4ddfae81615eff5..6bd63f4fbbb899b43a55139376f281a079d6529b 100644 (file)
@@ -28,29 +28,11 @@ error: expected expression, found `;`
 14 |     foo(bar(;
    |             ^
 
-error: expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `for`, `if`, `loop`, `match`, `move`, `return`, `true`, `unsafe`, `while`, `yield`, or an operator, found `;`
-  --> $DIR/token-error-correct.rs:14:13
-   |
-14 |     foo(bar(;
-   |             ^ expected one of 19 possible tokens here
-
 error: expected expression, found `)`
   --> $DIR/token-error-correct.rs:23:1
    |
 23 | }
    | ^
 
-error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/token-error-correct.rs:14:5
-   |
-14 |     foo(bar(;
-   |     ^^^ not found in this scope
-
-error[E0425]: cannot find function `bar` in this scope
-  --> $DIR/token-error-correct.rs:14:9
-   |
-14 |     foo(bar(;
-   |         ^^^ not found in this scope
-
-error: aborting due to 7 previous errors
+error: aborting due to 4 previous errors
 
index 17558cc05c612cec6910b84ae9629d2041d48616..f9219436c780a0df8400a4127d69ad4d919c0467 100644 (file)
@@ -11,4 +11,6 @@
 #[inline(unknown)] //~ ERROR E0535
 pub fn something() {}
 
-fn main() {}
+fn main() {
+    something();
+}
index 117b109780b152de90c24f45dd97f8697ea3d84b..e12fb57f15dc9aa45d74746b009e6613a362fa2d 100644 (file)
@@ -1,11 +1,11 @@
-error[E0308]: mismatched method receiver
+error[E0307]: invalid `self` type: &SomeType
   --> $DIR/issue-27522.rs:16:22
    |
 16 |     fn handler(self: &SomeType);
-   |                      ^^^^^^^^^ expected Self, found struct `SomeType`
+   |                      ^^^^^^^^^
    |
-   = note: expected type `&Self`
-              found type `&SomeType`
+   = note: type must be `Self` or a type that dereferences to it`
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
 error: aborting due to previous error
 
index 1fa5f94aa4ca6e29970c2932c13aa9814a57e299..f4998e08907a387f55b897ab80f5cc47e203d540 100644 (file)
@@ -65,12 +65,14 @@ note: because it's nested under this `unsafe` block
    | |_____^
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:40:9
+  --> $DIR/lint-unused-unsafe.rs:39:5
    |
-40 | /         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+39 | /     unsafe {                             //~ ERROR: unnecessary `unsafe` block
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
-   | |_________^ unnecessary `unsafe` block
+43 | |     }
+   | |_____^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` fn
   --> $DIR/lint-unused-unsafe.rs:38:1
@@ -85,14 +87,12 @@ note: because it's nested under this `unsafe` fn
    | |_^
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:39:5
+  --> $DIR/lint-unused-unsafe.rs:40:9
    |
-39 | /     unsafe {                             //~ ERROR: unnecessary `unsafe` block
-40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+40 | /         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
-43 | |     }
-   | |_____^ unnecessary `unsafe` block
+   | |_________^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` fn
   --> $DIR/lint-unused-unsafe.rs:38:1
index f73dff4f73d0ee43ba06369bcfed4a5a6f3ca13a..adeabd91302ce9e6925b1d95e4c5f800337f5cd9 100644 (file)
@@ -1,10 +1,15 @@
-error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required lifetime
+error[E0478]: lifetime bound not satisfied
   --> $DIR/static-lifetime.rs:13:20
    |
 13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
    |                    ^^^^^^^^^
    |
-   = note: type must satisfy the static lifetime
+note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 13:1
+  --> $DIR/static-lifetime.rs:13:1
+   |
+13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: but lifetime parameter must outlive the static lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/auxiliary/m1.rs b/src/test/ui/suggestions/auxiliary/m1.rs
new file mode 100644 (file)
index 0000000..b61667c
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn foo() {}
diff --git a/src/test/ui/suggestions/auxiliary/m2.rs b/src/test/ui/suggestions/auxiliary/m2.rs
new file mode 100644 (file)
index 0000000..94ff5e4
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn bar() {}
diff --git a/src/test/ui/suggestions/extern-crate-rename.rs b/src/test/ui/suggestions/extern-crate-rename.rs
new file mode 100644 (file)
index 0000000..b3fa587
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:m1.rs
+// aux-build:m2.rs
+
+
+extern crate m1;
+extern crate m2 as m1;
+
+fn main() {}
diff --git a/src/test/ui/suggestions/extern-crate-rename.stderr b/src/test/ui/suggestions/extern-crate-rename.stderr
new file mode 100644 (file)
index 0000000..c15e238
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0259]: the name `m1` is defined multiple times
+  --> $DIR/extern-crate-rename.rs:16:1
+   |
+15 | extern crate m1;
+   | ---------------- previous import of the extern crate `m1` here
+16 | extern crate m2 as m1;
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | `m1` reimported here
+   | You can use `as` to change the binding name of the import
+   |
+   = note: `m1` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs b/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs
new file mode 100644 (file)
index 0000000..bcd965f
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+    let x: Vec::with_capacity(10, 20);
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr b/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr
new file mode 100644 (file)
index 0000000..647e3f8
--- /dev/null
@@ -0,0 +1,17 @@
+error: expected type, found `10`
+  --> $DIR/type-ascription-instead-of-initializer.rs:12:31
+   |
+12 |     let x: Vec::with_capacity(10, 20);
+   |         --                    ^^
+   |         ||
+   |         |help: use `=` if you meant to assign
+   |         while parsing the type for `x`
+
+error[E0061]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/type-ascription-instead-of-initializer.rs:12:31
+   |
+12 |     let x: Vec::with_capacity(10, 20);
+   |                               ^^^^^^ expected 1 parameter
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs
new file mode 100644 (file)
index 0000000..14ef3b5
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+#![allow(unused)]
+
+fn foo<F>(f: F)
+    where F: Fn()
+{
+}
+
+fn main() {
+    // Test that this closure is inferred to `FnOnce` because it moves
+    // from `y.0`. This affects the error output (the error is that
+    // the closure implements `FnOnce`, not that it moves from inside
+    // a `Fn` closure.)
+    let y = (vec![1, 2, 3], 0);
+    let c = || drop(y.0);
+    foo(c);
+}
diff --git a/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr
new file mode 100644 (file)
index 0000000..d968c40
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:24:13
+   |
+24 |     let c = || drop(y.0);
+   |             ^^^^^^^^^^^^
+25 |     foo(c);
+   |     --- the requirement to implement `Fn` derives from here
+   |
+note: closure is `FnOnce` because it moves the variable `y` out of its environment
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:24:21
+   |
+24 |     let c = || drop(y.0);
+   |                     ^
+
+error: aborting due to previous error
+
index 859c2305b5d7ff820d7f7af158bbca999cbd8bf3..abd137ad14a8f352b48f24b11c3995d716deb260 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 859c2305b5d7ff820d7f7af158bbca999cbd8bf3
+Subproject commit abd137ad14a8f352b48f24b11c3995d716deb260
index f8282cc5f8d9b0f5f4482e26677fb79d59ab756c..d4d567e63c017748b2c606d02d50b0e2829e830a 100644 (file)
@@ -11,3 +11,7 @@ getopts = "0.2"
 log = "0.3"
 rustc-serialize = "0.3"
 libc = "0.2"
+
+[target.'cfg(windows)'.dependencies]
+miow = "0.2"
+winapi = "0.2"
index 191958387912e811f29114e0443b05a01a2f5f3e..e03d9f89e5d8c61ca8713bd44b71126b2b65a249 100644 (file)
@@ -259,9 +259,9 @@ pub fn from_aux_file(&self,
         props
     }
 
-    pub fn from_file(testfile: &Path, config: &Config) -> Self {
+    pub fn from_file(testfile: &Path, cfg: Option<&str>, config: &Config) -> Self {
         let mut props = TestProps::new();
-        props.load_from(testfile, None, config);
+        props.load_from(testfile, cfg, config);
         props
     }
 
@@ -269,10 +269,10 @@ pub fn from_file(testfile: &Path, config: &Config) -> Self {
     /// tied to a particular revision `foo` (indicated by writing
     /// `//[foo]`), then the property is ignored unless `cfg` is
     /// `Some("foo")`.
-    pub fn load_from(&mut self,
-                     testfile: &Path,
-                     cfg: Option<&str>,
-                     config: &Config) {
+    fn load_from(&mut self,
+                 testfile: &Path,
+                 cfg: Option<&str>,
+                 config: &Config) {
         iter_header(testfile,
                     cfg,
                     &mut |ln| {
index 1701c8a3e43eec5194cac204527bad1590e6e694..6da37df19279a6c5969dc9ff94c46407ba88024f 100644 (file)
 #![crate_name = "compiletest"]
 
 #![feature(test)]
+#![feature(slice_rotate)]
 
 #![deny(warnings)]
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(unix)]
 extern crate libc;
 extern crate test;
 extern crate getopts;
@@ -47,6 +48,7 @@
 pub mod common;
 pub mod errors;
 mod raise_fd_limit;
+mod read2;
 
 fn main() {
     env_logger::init().unwrap();
@@ -491,6 +493,7 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf {
                              config.stage_id);
     config.build_base.canonicalize()
           .unwrap_or_else(|_| config.build_base.clone())
+          .join(&testpaths.relative_dir)
           .join(stamp_name)
 }
 
@@ -522,6 +525,10 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
         let lib = lib.unwrap();
         inputs.push(mtime(&lib.path()));
     }
+    if let Some(ref rustdoc_path) = config.rustdoc_path {
+        inputs.push(mtime(&rustdoc_path));
+        inputs.push(mtime(&rust_src_dir.join("src/etc/htmldocck.py")));
+    }
     inputs.iter().any(|input| *input > stamp)
 }
 
diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs
new file mode 100644 (file)
index 0000000..1d8816c
--- /dev/null
@@ -0,0 +1,208 @@
+// 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.
+
+// FIXME: This is a complete copy of `cargo/src/cargo/util/read2.rs`
+// Consider unify the read2() in libstd, cargo and this to prevent further code duplication.
+
+pub use self::imp::read2;
+
+#[cfg(not(any(unix, windows)))]
+mod imp {
+    use std::io::{self, Read};
+    use std::process::{ChildStdout, ChildStderr};
+
+    pub fn read2(out_pipe: ChildStdout,
+                 err_pipe: ChildStderr,
+                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
+        let mut buffer = Vec::new();
+        out_pipe.read_to_end(&mut buffer)?;
+        data(true, &mut buffer, true);
+        buffer.clear();
+        err_pipe.read_to_end(&mut buffer)?;
+        data(false, &mut buffer, true);
+        Ok(())
+    }
+}
+
+#[cfg(unix)]
+mod imp {
+    use std::io::prelude::*;
+    use std::io;
+    use std::mem;
+    use std::os::unix::prelude::*;
+    use std::process::{ChildStdout, ChildStderr};
+    use libc;
+
+    pub fn read2(mut out_pipe: ChildStdout,
+                 mut err_pipe: ChildStderr,
+                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
+        unsafe {
+            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
+            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
+        }
+
+        let mut out_done = false;
+        let mut err_done = false;
+        let mut out = Vec::new();
+        let mut err = Vec::new();
+
+        let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
+        fds[0].fd = out_pipe.as_raw_fd();
+        fds[0].events = libc::POLLIN;
+        fds[1].fd = err_pipe.as_raw_fd();
+        fds[1].events = libc::POLLIN;
+        loop {
+            // wait for either pipe to become readable using `select`
+            let r = unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) };
+            if r == -1 {
+                let err = io::Error::last_os_error();
+                if err.kind() == io::ErrorKind::Interrupted {
+                    continue
+                }
+                return Err(err)
+            }
+
+            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
+            // EAGAIN. If we hit EOF, then this will happen because the underlying
+            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
+            // this case we flip the other fd back into blocking mode and read
+            // whatever's leftover on that file descriptor.
+            let handle = |res: io::Result<_>| {
+                match res {
+                    Ok(_) => Ok(true),
+                    Err(e) => {
+                        if e.kind() == io::ErrorKind::WouldBlock {
+                            Ok(false)
+                        } else {
+                            Err(e)
+                        }
+                    }
+                }
+            };
+            if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? {
+                out_done = true;
+            }
+            data(true, &mut out, out_done);
+            if !err_done && fds[1].revents != 0 && handle(err_pipe.read_to_end(&mut err))? {
+                err_done = true;
+            }
+            data(false, &mut err, err_done);
+
+            if out_done && err_done {
+                return Ok(())
+            }
+        }
+    }
+}
+
+#[cfg(windows)]
+mod imp {
+    extern crate miow;
+    extern crate winapi;
+
+    use std::io;
+    use std::os::windows::prelude::*;
+    use std::process::{ChildStdout, ChildStderr};
+    use std::slice;
+
+    use self::miow::iocp::{CompletionPort, CompletionStatus};
+    use self::miow::pipe::NamedPipe;
+    use self::miow::Overlapped;
+    use self::winapi::ERROR_BROKEN_PIPE;
+
+    struct Pipe<'a> {
+        dst: &'a mut Vec<u8>,
+        overlapped: Overlapped,
+        pipe: NamedPipe,
+        done: bool,
+    }
+
+    pub fn read2(out_pipe: ChildStdout,
+                 err_pipe: ChildStderr,
+                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
+        let mut out = Vec::new();
+        let mut err = Vec::new();
+
+        let port = CompletionPort::new(1)?;
+        port.add_handle(0, &out_pipe)?;
+        port.add_handle(1, &err_pipe)?;
+
+        unsafe {
+            let mut out_pipe = Pipe::new(out_pipe, &mut out);
+            let mut err_pipe = Pipe::new(err_pipe, &mut err);
+
+            out_pipe.read()?;
+            err_pipe.read()?;
+
+            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];
+
+            while !out_pipe.done || !err_pipe.done {
+                for status in port.get_many(&mut status, None)? {
+                    if status.token() == 0 {
+                        out_pipe.complete(status);
+                        data(true, out_pipe.dst, out_pipe.done);
+                        out_pipe.read()?;
+                    } else {
+                        err_pipe.complete(status);
+                        data(false, err_pipe.dst, err_pipe.done);
+                        err_pipe.read()?;
+                    }
+                }
+            }
+
+            Ok(())
+        }
+    }
+
+    impl<'a> Pipe<'a> {
+        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
+            Pipe {
+                dst: dst,
+                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
+                overlapped: Overlapped::zero(),
+                done: false,
+            }
+        }
+
+        unsafe fn read(&mut self) -> io::Result<()> {
+            let dst = slice_to_end(self.dst);
+            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
+                Ok(_) => Ok(()),
+                Err(e) => {
+                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
+                        self.done = true;
+                        Ok(())
+                    } else {
+                        Err(e)
+                    }
+                }
+            }
+        }
+
+        unsafe fn complete(&mut self, status: &CompletionStatus) {
+            let prev = self.dst.len();
+            self.dst.set_len(prev + status.bytes_transferred() as usize);
+            if status.bytes_transferred() == 0 {
+                self.done = true;
+            }
+        }
+    }
+
+    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
+        if v.capacity() == 0 {
+            v.reserve(16);
+        }
+        if v.capacity() == v.len() {
+            v.reserve(1);
+        }
+        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
+                                  v.capacity() - v.len())
+    }
+}
index 16c48ccfdd1cd440b36cc1ea639bf41fe10447e1..2ff3eb7678f1a2970400de4b78a618b272f46e2d 100644 (file)
@@ -29,7 +29,7 @@
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output, ExitStatus, Stdio};
+use std::process::{Command, Output, ExitStatus, Stdio, Child};
 use std::str;
 
 use extract_gdb_version;
@@ -69,7 +69,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
         print!("\n\n");
     }
     debug!("running {:?}", testpaths.file.display());
-    let base_props = TestProps::from_file(&testpaths.file, &config);
+    let base_props = TestProps::from_file(&testpaths.file, None, &config);
 
     let base_cx = TestCx { config: &config,
                            props: &base_props,
@@ -81,8 +81,9 @@ pub fn run(config: Config, testpaths: &TestPaths) {
         base_cx.run_revision()
     } else {
         for revision in &base_props.revisions {
-            let mut revision_props = base_props.clone();
-            revision_props.load_from(&testpaths.file, Some(revision), &config);
+            let revision_props = TestProps::from_file(&testpaths.file,
+                                                      Some(revision),
+                                                      &config);
             let rev_cx = TestCx {
                 config: &config,
                 props: &revision_props,
@@ -1344,12 +1345,14 @@ fn compose_and_run(&self,
         if let Some(input) = input {
             child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
         }
-        let Output { status, stdout, stderr } = child.wait_with_output().unwrap();
+
+        let Output { status, stdout, stderr } = read2_abbreviated(child)
+            .expect("failed to read output");
 
         let result = ProcRes {
             status,
-            stdout: String::from_utf8(stdout).unwrap(),
-            stderr: String::from_utf8(stderr).unwrap(),
+            stdout: String::from_utf8_lossy(&stdout).into_owned(),
+            stderr: String::from_utf8_lossy(&stderr).into_owned(),
             cmdline,
         };
 
@@ -1384,6 +1387,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
 
         if let Some(ref incremental_dir) = self.props.incremental_dir {
             rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
+            rustc.args(&["-Z", "incremental-verify-ich"]);
         }
 
         match self.config.mode {
@@ -1634,7 +1638,9 @@ fn try_print_open_handles(&self) {
         cmd.arg("-a").arg("-u");
         cmd.arg(filename);
         cmd.arg("-nobanner");
-        let output = match cmd.output() {
+        cmd.stdout(Stdio::piped());
+        cmd.stderr(Stdio::piped());
+        let output = match cmd.spawn().and_then(read2_abbreviated) {
             Ok(output) => output,
             Err(_) => return,
         };
@@ -2094,6 +2100,8 @@ fn run_rmake_test(&self) {
 
         let mut cmd = Command::new(make);
         cmd.current_dir(&self.testpaths.file)
+           .stdout(Stdio::piped())
+           .stderr(Stdio::piped())
            .env("TARGET", &self.config.target)
            .env("PYTHON", &self.config.docck_python)
            .env("S", src_root)
@@ -2142,7 +2150,7 @@ fn run_rmake_test(&self) {
             }
         }
 
-        let output = cmd.output().expect("failed to spawn `make`");
+        let output = cmd.spawn().and_then(read2_abbreviated).expect("failed to spawn `make`");
         if !output.status.success() {
             let res = ProcRes {
                 status: output.status,
@@ -2535,3 +2543,76 @@ fn nocomment_mir_line(line: &str) -> &str {
         line
     }
 }
+
+fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
+    use std::mem::replace;
+    use read2::read2;
+
+    const HEAD_LEN: usize = 160 * 1024;
+    const TAIL_LEN: usize = 256 * 1024;
+
+    enum ProcOutput {
+        Full(Vec<u8>),
+        Abbreviated {
+            head: Vec<u8>,
+            skipped: usize,
+            tail: Box<[u8]>,
+        }
+    }
+
+    impl ProcOutput {
+        fn extend(&mut self, data: &[u8]) {
+            let new_self = match *self {
+                ProcOutput::Full(ref mut bytes) => {
+                    bytes.extend_from_slice(data);
+                    let new_len = bytes.len();
+                    if new_len <= HEAD_LEN + TAIL_LEN {
+                        return;
+                    }
+                    let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice();
+                    let head = replace(bytes, Vec::new());
+                    let skipped = new_len - HEAD_LEN - TAIL_LEN;
+                    ProcOutput::Abbreviated { head, skipped, tail }
+                }
+                ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => {
+                    *skipped += data.len();
+                    if data.len() <= TAIL_LEN {
+                        tail[..data.len()].copy_from_slice(data);
+                        tail.rotate(data.len());
+                    } else {
+                        tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
+                    }
+                    return;
+                }
+            };
+            *self = new_self;
+        }
+
+        fn into_bytes(self) -> Vec<u8> {
+            match self {
+                ProcOutput::Full(bytes) => bytes,
+                ProcOutput::Abbreviated { mut head, skipped, tail } => {
+                    write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
+                    head.extend_from_slice(&tail);
+                    head
+                }
+            }
+        }
+    }
+
+    let mut stdout = ProcOutput::Full(Vec::new());
+    let mut stderr = ProcOutput::Full(Vec::new());
+
+    drop(child.stdin.take());
+    read2(child.stdout.take().unwrap(), child.stderr.take().unwrap(), &mut |is_stdout, data, _| {
+        if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
+        data.clear();
+    })?;
+    let status = child.wait()?;
+
+    Ok(Output {
+        status,
+        stdout: stdout.into_bytes(),
+        stderr: stderr.into_bytes(),
+    })
+}
index 48fd42fe92175ce93a5b67f78c195254ee94493d..015073b7c8a192584c15b2c1bd34a92025cf6836 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 48fd42fe92175ce93a5b67f78c195254ee94493d
+Subproject commit 015073b7c8a192584c15b2c1bd34a92025cf6836
index cf0d494dda7447bacaab743a70c47e28bea55c6f..291dbe8d87701f3617ccdd70caa49df1c27af0e0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cf0d494dda7447bacaab743a70c47e28bea55c6f
+Subproject commit 291dbe8d87701f3617ccdd70caa49df1c27af0e0
index 11d5dbe736e81cdd39230a536bfd35210ad10131..f6e42c8dc17b1908a6f5787f12ce82f18baaf65c 100644 (file)
@@ -31,9 +31,9 @@ pub fn check(path: &Path, bad: &mut bool) {
     if let Ok(mut file) = fs::File::open("/proc/version") {
         let mut contents = String::new();
         file.read_to_string(&mut contents).unwrap();
-        // Probably on Windows Linux Subsystem, all files will be marked as
-        // executable, so skip checking.
-        if contents.contains("Microsoft") {
+        // Probably on Windows Linux Subsystem or Docker via VirtualBox,
+        // all files will be marked as executable, so skip checking.
+        if contents.contains("Microsoft") || contents.contains("boot2docker") {
             return;
         }
     }
index 9dd420c14586d5add18cde7756c6af237e51d04a..f1684f4c5acbe42f5f8eb94ba87a3408b9bd5bc9 100644 (file)
@@ -29,7 +29,7 @@ miri = "Broken"
 clippy = "Broken"
 
 # ping @nrc
-rls = "Broken"
+rls = "Testing"
 
 # ping @nrc
-rustfmt = "Broken"
+rustfmt = "Testing"