]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #53830 - davidtwco:issue-53228, r=nikomatsakis
authorbors <bors@rust-lang.org>
Fri, 7 Sep 2018 09:57:27 +0000 (09:57 +0000)
committerbors <bors@rust-lang.org>
Fri, 7 Sep 2018 09:57:27 +0000 (09:57 +0000)
Add help message for missing IndexMut impl with NLL

Fixes #53228.

r? @nikomatsakis

678 files changed:
.gitignore
.gitmodules
CONTRIBUTING.md
src/.gitignore [new file with mode: 0644]
src/Cargo.lock
src/bootstrap/bin/rustdoc.rs
src/bootstrap/dist.rs
src/bootstrap/flags.rs
src/bootstrap/job.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/util.rs
src/ci/docker/dist-various-1/Dockerfile
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/language-features/custom-test-frameworks.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/doc-cfg.md
src/etc/rust-gdbgui [new file with mode: 0755]
src/liballoc/Cargo.toml
src/liballoc/borrow.rs
src/liballoc/collections/linked_list.rs
src/liballoc/lib.rs
src/liballoc/sync.rs
src/liballoc/tests/lib.rs
src/liballoc/tests/slice.rs
src/liballoc/tests/str.rs
src/liballoc_system/lib.rs
src/libcompiler_builtins
src/libcore/Cargo.toml
src/libcore/benches/any.rs
src/libcore/cmp.rs
src/libcore/iter/range.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/tests/num/flt2dec/random.rs
src/libcore/tests/slice.rs
src/libpanic_unwind/seh.rs
src/libpanic_unwind/seh64_gnu.rs
src/libpanic_unwind/windows.rs
src/librustc/Cargo.toml
src/librustc/cfg/construct.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.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/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/mod.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/middle/stability.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/cache.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/session/config.rs
src/librustc/session/filesearch.rs
src/librustc/session/mod.rs
src/librustc/traits/fulfill.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/job.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/steal.rs
src/librustc/ty/structural_impls.rs
src/librustc/util/common.rs
src/librustc/util/profiling.rs
src/librustc/util/time_graph.rs
src/librustc_codegen_llvm/Cargo.toml
src/librustc_codegen_llvm/back/linker.rs
src/librustc_codegen_llvm/back/lto.rs
src/librustc_codegen_llvm/back/rpath.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_cratesio_shim/Cargo.toml
src/librustc_cratesio_shim/src/lib.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/flock.rs
src/librustc_data_structures/graph/test.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_data_structures/sync.rs
src/librustc_driver/driver.rs
src/librustc_driver/profile/trace.rs
src/librustc_errors/Cargo.toml
src/librustc_errors/emitter.rs
src/librustc_errors/lock.rs
src/librustc_errors/registry.rs
src/librustc_incremental/Cargo.toml
src/librustc_incremental/assert_module_sources.rs
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/fs.rs
src/librustc_incremental/persist/mod.rs
src/librustc_lint/bad_style.rs [deleted file]
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/nonstandard_style.rs [new file with mode: 0644]
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/locator.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/flows.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/snapshot.rs [new file with mode: 0644]
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs [new file with mode: 0644]
src/librustc_passes/rvalue_promotion.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_plugin/registry.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_save_analysis/span_utils.rs
src/librustc_target/lib.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
src/librustc_target/spec/riscv32imc_unknown_none_elf.rs [new file with mode: 0644]
src/librustc_target/spec/riscv_base.rs [new file with mode: 0644]
src/librustc_target/spec/wasm32_unknown_unknown.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/structured_errors.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/lib.rs
src/librustdoc/theme.rs
src/libstd/Cargo.toml
src/libstd/error.rs
src/libstd/fs.rs
src/libstd/io/lazy.rs
src/libstd/io/stdio.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/os/mod.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/cloudabi/condvar.rs
src/libstd/sys/cloudabi/rwlock.rs
src/libstd/sys/mod.rs
src/libstd/sys/redox/mod.rs
src/libstd/sys/unix/fd.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/rand.rs
src/libstd/sys/wasm/net.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/os.rs
src/libstd/sys_common/io.rs
src/libstd/tests/env.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/attr/mod.rs
src/libsyntax/config.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/derive.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/source_map.rs
src/libsyntax/test.rs
src/libsyntax/visit.rs
src/libsyntax_ext/Cargo.toml
src/libsyntax_ext/format.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/test.rs [new file with mode: 0644]
src/libsyntax_ext/test_case.rs [new file with mode: 0644]
src/libsyntax_pos/hygiene.rs
src/libtest/formatters/json.rs
src/libtest/lib.rs
src/libtest/stats.rs
src/libunwind/libunwind.rs
src/llvm
src/rustllvm/PassWrapper.cpp
src/rustllvm/llvm-rebuild-trigger
src/test/codegen-units/item-collection/unreferenced-const-fn.rs
src/test/codegen/link-dead-code.rs
src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs
src/test/compile-fail/issue-43733-2.rs
src/test/incremental/issue-49595/issue_49595.rs
src/test/mir-opt/lower_128bit_debug_test.rs
src/test/mir-opt/lower_128bit_test.rs
src/test/run-fail/issue-29798.rs
src/test/run-make-fulldeps/libtest-json/output.json
src/test/run-pass/auxiliary/const_fn_lib.rs
src/test/run-pass/auxiliary/issue-36954.rs
src/test/run-pass/const-fn-const-eval.rs
src/test/run-pass/const-fn-method.rs
src/test/run-pass/const-fn-nested.rs
src/test/run-pass/const-int-conversion.rs [new file with mode: 0644]
src/test/run-pass/const-int-overflowing.rs [new file with mode: 0644]
src/test/run-pass/const-int-rotate.rs [new file with mode: 0644]
src/test/run-pass/const-int-sign.rs [new file with mode: 0644]
src/test/run-pass/const-int-wrapping.rs [new file with mode: 0644]
src/test/run-pass/const-meth-pattern.rs
src/test/run-pass/const-pattern-variant.rs
src/test/run-pass/const-size_of-align_of.rs
src/test/run-pass/const-unsafe-fn.rs
src/test/run-pass/consts-in-patterns.rs
src/test/run-pass/ctfe/ice-48279.rs
src/test/run-pass/ctfe/match-const-fn-structs.rs
src/test/run-pass/ctfe/return-in-const-fn.rs
src/test/run-pass/invalid_const_promotion.rs
src/test/run-pass/issue-28822.rs
src/test/run-pass/issue-29927.rs
src/test/run-pass/issue-33537.rs
src/test/run-pass/issue-37991.rs
src/test/run-pass/issue-48006.rs [new file with mode: 0644]
src/test/run-pass/issue29927-1.rs
src/test/run-pass/redundant.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/enums.rs
src/test/run-pass/simd-target-feature-mixup.rs
src/test/run-pass/try-from-int-error-partial-eq.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/issue-27362.rs
src/test/rustdoc/const-fn.rs
src/test/rustdoc/const.rs
src/test/rustdoc/extern-html-root-url.rs [new file with mode: 0644]
src/test/rustdoc/intra-links.rs
src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs
src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
src/test/ui-fulldeps/lint_tool_cmdline_allow.rs [new file with mode: 0644]
src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr [new file with mode: 0644]
src/test/ui-fulldeps/lint_tool_test.rs
src/test/ui-fulldeps/lint_tool_test.stderr
src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr
src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr
src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr
src/test/ui/borrowck/issue-45983.nll.stderr
src/test/ui/borrowck/issue-45983.rs
src/test/ui/borrowck/issue-7573.nll.stderr
src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs
src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr
src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr
src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr
src/test/ui/cfg-non-opt-expr.rs
src/test/ui/cfg-non-opt-expr.stderr
src/test/ui/chalkify/lower_trait_where_clause.rs
src/test/ui/chalkify/lower_trait_where_clause.stderr
src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr
src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr
src/test/ui/consts/auxiliary/const_fn_lib.rs
src/test/ui/consts/const-eval/auxiliary/stability.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/issue-43197.rs
src/test/ui/consts/const-eval/issue-47971.rs
src/test/ui/consts/const-eval/issue-52475.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/issue-52475.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ref_to_float_transmute.rs [deleted file]
src/test/ui/consts/const-eval/ub-ptr-in-usize.rs [deleted file]
src/test/ui/consts/const-int-conversion.rs [new file with mode: 0644]
src/test/ui/consts/const-int-conversion.stderr [new file with mode: 0644]
src/test/ui/consts/const-int-overflowing.rs [new file with mode: 0644]
src/test/ui/consts/const-int-overflowing.stderr [new file with mode: 0644]
src/test/ui/consts/const-int-rotate.rs [new file with mode: 0644]
src/test/ui/consts/const-int-rotate.stderr [new file with mode: 0644]
src/test/ui/consts/const-int-sign.rs [new file with mode: 0644]
src/test/ui/consts/const-int-sign.stderr [new file with mode: 0644]
src/test/ui/consts/const-int-wrapping.rs [new file with mode: 0644]
src/test/ui/consts/const-int-wrapping.stderr [new file with mode: 0644]
src/test/ui/consts/const-pattern-not-const-evaluable.rs
src/test/ui/consts/const-size_of-cycle.rs
src/test/ui/consts/const-size_of-cycle.stderr
src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr [new file with mode: 0644]
src/test/ui/custom-test-frameworks-simple.rs [new file with mode: 0644]
src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs [new file with mode: 0644]
src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs [new file with mode: 0644]
src/test/ui/custom_test_frameworks/dynamic.rs [new file with mode: 0644]
src/test/ui/custom_test_frameworks/full.rs [new file with mode: 0644]
src/test/ui/custom_test_frameworks/mismatch.rs [new file with mode: 0644]
src/test/ui/custom_test_frameworks/mismatch.stderr [new file with mode: 0644]
src/test/ui/deref-suggestion.rs
src/test/ui/deref-suggestion.stderr
src/test/ui/dst/dst-index.nll.stderr
src/test/ui/dst/dst-rvalue.nll.stderr
src/test/ui/enum/enum-discrim-autosizing.rs
src/test/ui/enum/enum-discrim-autosizing.stderr
src/test/ui/error-codes/E0161.ast.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.astul.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.edition.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.editionul.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.nll.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.nllul.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.rs
src/test/ui/error-codes/E0161.zflags.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0161.zflagsul.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0308.stderr
src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr
src/test/ui/existential_types/generic_type_does_not_live_long_enough.nll.stderr
src/test/ui/feature-gate-custom_test_frameworks.rs [new file with mode: 0644]
src/test/ui/feature-gate-custom_test_frameworks.stderr [new file with mode: 0644]
src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs [new file with mode: 0644]
src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-const_fn.rs
src/test/ui/feature-gates/feature-gate-const_fn.stderr
src/test/ui/feature-gates/feature-gate-min_const_fn.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-min_const_fn.stderr [new file with mode: 0644]
src/test/ui/gated-bad-feature.rs
src/test/ui/gated-bad-feature.stderr
src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr
src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr
src/test/ui/hygiene/fields-move.nll.stderr
src/test/ui/hygiene/generate-mod.rs
src/test/ui/hygiene/generate-mod.stderr
src/test/ui/hygiene/no_implicit_prelude.rs
src/test/ui/hygiene/no_implicit_prelude.stderr
src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
src/test/ui/impl-trait/type_parameters_captured.nll.stderr
src/test/ui/imports/import-glob-circular.rs
src/test/ui/imports/import-glob-circular.stderr
src/test/ui/imports/import-loop-2.rs
src/test/ui/imports/import-loop-2.stderr
src/test/ui/in-band-lifetimes/mismatched.nll.stderr
src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr [deleted file]
src/test/ui/inaccessible-test-modules.stderr
src/test/ui/infinite/infinite-recursion-const-fn.rs
src/test/ui/invalid_crate_type_syntax.rs
src/test/ui/invalid_crate_type_syntax.stderr
src/test/ui/issues/issue-10291.nll.stderr
src/test/ui/issues/issue-11692-2.rs
src/test/ui/issues/issue-12997-2.stderr
src/test/ui/issues/issue-13058.nll.stderr
src/test/ui/issues/issue-14285.nll.stderr [deleted file]
src/test/ui/issues/issue-15034.nll.stderr
src/test/ui/issues/issue-16683.nll.stderr
src/test/ui/issues/issue-16922.nll.stderr
src/test/ui/issues/issue-17728.nll.stderr
src/test/ui/issues/issue-17758.nll.stderr
src/test/ui/issues/issue-26217.nll.stderr
src/test/ui/issues/issue-3154.nll.stderr [deleted file]
src/test/ui/issues/issue-38715.rs
src/test/ui/issues/issue-38715.stderr
src/test/ui/issues/issue-40288-2.nll.stderr
src/test/ui/issues/issue-42755.rs
src/test/ui/issues/issue-42755.stderr
src/test/ui/issues/issue-43784-associated-type.rs
src/test/ui/issues/issue-43784-associated-type.stderr
src/test/ui/issues/issue-43784-supertrait.rs
src/test/ui/issues/issue-43784-supertrait.stderr
src/test/ui/issues/issue-44415.rs
src/test/ui/issues/issue-52060.rs [new file with mode: 0644]
src/test/ui/issues/issue-52060.stderr [new file with mode: 0644]
src/test/ui/issues/issue-52213.nll.stderr
src/test/ui/issues/issue-5239-1.stderr
src/test/ui/issues/issue-52533-1.nll.stderr
src/test/ui/issues/issue-52533.nll.stderr
src/test/ui/kindck/kindck-impl-type-params.nll.stderr
src/test/ui/kindck/kindck-send-object1.nll.stderr
src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr
src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr [deleted file]
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr
src/test/ui/lint/lint-group-style.rs
src/test/ui/lint/lint-group-style.stderr
src/test/ui/lint/lint-shorthand-field.rs
src/test/ui/lint/outer-forbid.rs
src/test/ui/lint/outer-forbid.stderr
src/test/ui/lint/test-inner-fn.rs
src/test/ui/lint/test-inner-fn.stderr
src/test/ui/lub-if.nll.stderr
src/test/ui/lub-match.nll.stderr
src/test/ui/macros/macro-use-bad-args-1.rs
src/test/ui/macros/macro-use-bad-args-1.stderr
src/test/ui/macros/macro-use-bad-args-2.rs
src/test/ui/macros/macro-use-bad-args-2.stderr
src/test/ui/match/match-ref-mut-invariance.nll.stderr
src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
src/test/ui/nested-ty-params.rs
src/test/ui/nested-ty-params.stderr
src/test/ui/nll/closure-requirements/escape-argument-callee.rs
src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
src/test/ui/nll/mir_check_cast_closure.rs
src/test/ui/nll/mir_check_cast_closure.stderr
src/test/ui/nll/mir_check_cast_reify.rs
src/test/ui/nll/mir_check_cast_reify.stderr
src/test/ui/nll/mir_check_cast_unsafe_fn.rs
src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
src/test/ui/nll/mir_check_cast_unsize.rs
src/test/ui/nll/mir_check_cast_unsize.stderr
src/test/ui/nll/ty-outlives/impl-trait-captures.rs
src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
src/test/ui/nll/ty-outlives/projection-implied-bounds.rs
src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
src/test/ui/nll/ty-outlives/ty-param-fn.rs
src/test/ui/nll/ty-outlives/ty-param-fn.stderr
src/test/ui/nll/where_clauses_in_functions.rs
src/test/ui/nll/where_clauses_in_functions.stderr
src/test/ui/nll/where_clauses_in_structs.rs
src/test/ui/nll/where_clauses_in_structs.stderr
src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr
src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr
src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr
src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr
src/test/ui/regions/region-object-lifetime-2.nll.stderr
src/test/ui/regions/region-object-lifetime-4.nll.stderr
src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
src/test/ui/regions/regions-addr-of-self.nll.stderr
src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr
src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr
src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr
src/test/ui/regions/regions-bounds.nll.stderr
src/test/ui/regions/regions-close-associated-type-into-object.nll.stderr
src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
src/test/ui/regions/regions-close-object-into-object-5.nll.stderr
src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr
src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr
src/test/ui/regions/regions-close-param-into-object.nll.stderr
src/test/ui/regions/regions-creating-enums3.nll.stderr
src/test/ui/regions/regions-creating-enums4.nll.stderr
src/test/ui/regions/regions-early-bound-error-method.nll.stderr
src/test/ui/regions/regions-early-bound-error.nll.stderr
src/test/ui/regions/regions-escape-method.nll.stderr
src/test/ui/regions/regions-escape-via-trait-or-not.nll.stderr
src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr
src/test/ui/regions/regions-glb-free-free.nll.stderr [deleted file]
src/test/ui/regions/regions-infer-at-fn-not-param.nll.stderr [deleted file]
src/test/ui/regions/regions-infer-bound-from-trait-self.nll.stderr
src/test/ui/regions/regions-infer-bound-from-trait.nll.stderr
src/test/ui/regions/regions-infer-call-3.nll.stderr
src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr
src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr
src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr
src/test/ui/regions/regions-infer-not-param.nll.stderr
src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr
src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr
src/test/ui/regions/regions-nested-fns.nll.stderr
src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr
src/test/ui/regions/regions-proc-bound-capture.nll.stderr [deleted file]
src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr
src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr
src/test/ui/regions/regions-ret-borrowed-1.nll.stderr
src/test/ui/regions/regions-ret-borrowed.nll.stderr
src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.nll.stderr
src/test/ui/regions/regions-static-bound.ll.nll.stderr
src/test/ui/regions/regions-static-bound.ll.stderr
src/test/ui/regions/regions-static-bound.nll.stderr
src/test/ui/regions/regions-static-bound.rs
src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
src/test/ui/repr/repr-transparent-other-items.rs
src/test/ui/repr/repr-transparent-other-items.stderr
src/test/ui/repr/repr-transparent-other-reprs.rs
src/test/ui/repr/repr-transparent-other-reprs.stderr
src/test/ui/repr/repr-transparent.rs
src/test/ui/repr/repr-transparent.stderr
src/test/ui/resolve/resolve-unknown-trait.rs
src/test/ui/resolve/resolve-unknown-trait.stderr
src/test/ui/resolve_self_super_hint.rs
src/test/ui/resolve_self_super_hint.stderr
src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
src/test/ui/rust-2018/uniform-paths/redundant.rs [deleted file]
src/test/ui/rust-2018/uniform-paths/redundant.stderr [deleted file]
src/test/ui/specialization/defaultimpl/validation.rs
src/test/ui/specialization/defaultimpl/validation.stderr
src/test/ui/test-on-macro.rs [new file with mode: 0644]
src/test/ui/test-on-macro.stderr [new file with mode: 0644]
src/test/ui/test-shadowing/auxiliary/test_macro.rs [new file with mode: 0644]
src/test/ui/test-shadowing/test-cant-be-shadowed.rs [new file with mode: 0644]
src/test/ui/tuple/tuple-struct-fields/test.rs
src/test/ui/tuple/tuple-struct-fields/test.stderr
src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.nll.stderr
src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr
src/test/ui/unresolved/unresolved-import.rs
src/test/ui/unresolved/unresolved-import.stderr
src/test/ui/unsafe/unsafe-const-fn.rs
src/test/ui/user-defined-macro-rules.rs
src/test/ui/user-defined-macro-rules.stderr
src/test/ui/variance/variance-btree-invariant-types.nll.stderr
src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
src/test/ui/variance/variance-covariant-arg-object.nll.stderr
src/test/ui/variance/variance-invariant-arg-object.nll.stderr
src/test/ui/variance/variance-trait-matching.nll.stderr
src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr
src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr
src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr
src/test/ui/wasm-custom-section-relocations.rs
src/test/ui/wasm-custom-section-relocations.stderr
src/test/ui/wf/wf-fn-where-clause.rs
src/test/ui/wf/wf-fn-where-clause.stderr
src/test/ui/wf/wf-static-method.nll.stderr
src/tools/build-manifest/README.md [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/clang
src/tools/clippy
src/tools/compiletest/Cargo.toml
src/tools/lld
src/tools/lldb
src/tools/rls
src/tools/rustfmt
src/tools/tidy/src/deps.rs

index 9ffaa82e1c8b5dace88ca77f19aa55047dc4f7cc..e18acfd98e241b14cf69e554406705d83f7e569d 100644 (file)
@@ -1,49 +1,3 @@
-*.a
-*.aux
-*.bc
-*.boot
-*.bz2
-*.cmi
-*.cmo
-*.cmx
-*.cp
-*.cps
-*.d
-*.dSYM
-*.def
-*.diff
-*.dll
-*.dylib
-*.elc
-*.epub
-*.exe
-*.fn
-*.html
-*.kdev4
-*.ky
-*.ll
-*.llvm
-*.log
-*.o
-*.orig
-*.out
-*.patch
-*.pdb
-*.pdf
-*.pg
-*.pot
-*.pyc
-*.rej
-*.rlib
-*.rustc
-*.so
-*.swo
-*.swp
-*.tmp
-*.toc
-*.tp
-*.vr
-*.x86
 *~
 .#*
 .DS_Store
index 1631daac76c2ce07b0cc807666e4f2287a9bcfa8..5753e9ed45eda9532f5d1fbc2a78d96c0abe49c9 100644 (file)
@@ -59,8 +59,8 @@
 [submodule "src/tools/lldb"]
        path = src/tools/lldb
        url = https://github.com/rust-lang-nursery/lldb/
-       branch = rust-release-70
+       branch = rust-release-80-v1
 [submodule "src/tools/clang"]
        path = src/tools/clang
        url = https://github.com/rust-lang-nursery/clang/
-       branch = release_70
+       branch = rust-release-80-v1
index ea9f2c194300507798ef377ea2f821035d82a5d1..21b14d011f91182d815acb4f610dff1a5f0b5a1c 100644 (file)
@@ -405,7 +405,8 @@ before the PR is merged.
 [breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler
 
 Rust's build system builds a number of tools that make use of the
-internals of the compiler. This includes clippy,
+internals of the compiler. This includes 
+[Clippy](https://github.com/rust-lang-nursery/rust-clippy),
 [RLS](https://github.com/rust-lang-nursery/rls) and
 [rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools
 break because of your changes, you may run into a sort of "chicken and egg"
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644 (file)
index 0000000..f1b36f5
--- /dev/null
@@ -0,0 +1,46 @@
+*.a
+*.aux
+*.bc
+*.boot
+*.bz2
+*.cmi
+*.cmo
+*.cmx
+*.cp
+*.cps
+*.d
+*.dSYM
+*.def
+*.diff
+*.dll
+*.dylib
+*.elc
+*.epub
+*.exe
+*.fn
+*.html
+*.kdev4
+*.ky
+*.ll
+*.llvm
+*.log
+*.o
+*.orig
+*.out
+*.patch
+*.pdb
+*.pdf
+*.pg
+*.pot
+*.pyc
+*.rej
+*.rlib
+*.rustc
+*.so
+*.swo
+*.swp
+*.tmp
+*.toc
+*.tp
+*.vr
+*.x86
index e4d9f6e23945e535d4df79dbb8461417c0ae9a49..a4f9082c284cd226770dfcf74e5e924f216d9b1b 100644 (file)
@@ -12,7 +12,7 @@ version = "0.0.0"
 dependencies = [
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -391,7 +391,7 @@ dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -421,7 +421,7 @@ dependencies = [
 name = "core"
 version = "0.0.0"
 dependencies = [
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1092,6 +1092,15 @@ dependencies = [
 name = "linkchecker"
 version = "0.1.0"
 
+[[package]]
+name = "lock_api"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "log"
 version = "0.3.9"
@@ -1198,6 +1207,15 @@ dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "memmap"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "memoffset"
 version = "0.2.1"
@@ -1388,6 +1406,15 @@ dependencies = [
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "parking_lot"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "parking_lot_core"
 version = "0.2.14"
@@ -1399,6 +1426,17 @@ dependencies = [
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "parking_lot_core"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "percent-encoding"
 version = "1.0.1"
@@ -1568,7 +1606,7 @@ dependencies = [
 
 [[package]]
 name = "racer"
-version = "2.1.4"
+version = "2.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1579,7 +1617,7 @@ dependencies = [
  "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1716,7 +1754,7 @@ dependencies = [
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1725,8 +1763,9 @@ dependencies = [
  "rls-rustc 0.5.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
- "rustfmt-nightly 0.99.2",
+ "rustfmt-nightly 0.99.4",
  "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1811,7 +1850,7 @@ dependencies = [
  "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1831,15 +1870,15 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-arena"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1848,7 +1887,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1856,67 +1895,72 @@ dependencies = [
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "218.0.0"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-arena 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2029,6 +2073,7 @@ name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
  "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_llvm 0.0.0",
@@ -2056,6 +2101,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2065,7 +2111,7 @@ dependencies = [
  "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2115,10 +2161,11 @@ name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_cratesio_shim 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
  "syntax_pos 0.0.0",
- "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2132,7 +2179,7 @@ version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_fs_util 0.0.0",
@@ -2399,7 +2446,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.99.2"
+version = "0.99.4"
 dependencies = [
  "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2413,9 +2460,9 @@ dependencies = [
  "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2564,7 +2611,7 @@ dependencies = [
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -2692,6 +2739,7 @@ name = "syntax_ext"
 version = "0.0.0"
 dependencies = [
  "fmt_macros 0.0.0",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -3140,6 +3188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab62b46003ba97701554631fa570d9f7e7947e2480ae3d941e555a54a2c0f05"
 "checksum libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "10dbc0957a27626444f5a3f523e6b97a70c3d702999bf1c7161cfbe7a25a9368"
 "checksum libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "f5f9aba969b3c45fe9c94bec65895868a9ceca9a600699f4054b75747a19c7c6"
+"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2"
 "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
@@ -3151,6 +3200,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
 "checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d"
+"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
@@ -3171,7 +3221,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
+"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
 "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
+"checksum parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06a2b6aae052309c2fd2161ef58f5067bc17bb758377a0de9d4b279d603fdd8a"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
 "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf"
@@ -3192,7 +3244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
 "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
-"checksum racer 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dcbc5ababaffee8d8f34910f925287c8f716b1ead48561c4278a152d08264f7c"
+"checksum racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4bc3847329b20ff5ba56c298938c179ae9911af15c9c10553f683b65164533"
 "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
 "checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea"
 "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
@@ -3211,14 +3263,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f"
-"checksum rustc-ap-arena 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e905467184ce31ccdbd33ac33b9ba377f8cc7aefb340a733ab7e5efe34cddda"
-"checksum rustc-ap-rustc_cratesio_shim 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a1a45817e78d0c1e2800fb933c526747ef2c5ee4b2dc0946e0c2d901329b88"
-"checksum rustc-ap-rustc_data_structures 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4e9e5588883318e0e58bb7ea7cde2a66eaca55b25e32908f0982365988657"
-"checksum rustc-ap-rustc_errors 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d233c0d9beda42a52d329a5df865c8f20c64773d2ab7aa6b4ae4248bacf3188"
-"checksum rustc-ap-rustc_target 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eec0bc13feecf9e88e39439b24b4b3ca54db8caf12fb7172d0c430451c8b377c"
-"checksum rustc-ap-serialize 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffcfb1102cd7cbf5f25c008a00f7253427af9dfac8989ede48c19bd47f556893"
-"checksum rustc-ap-syntax 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a2ca0ef078a735c81a0d33589e04148dcf41f80ee7ebe30e72904a631b7c669"
-"checksum rustc-ap-syntax_pos 218.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1bbd31d1bbc7210983c3bbbcb9ee35bac443c6c899f979b8114e58bb7101c28"
+"checksum rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d24c8b3c1437fad023cb9472381216a1d41d82dbb2d2e6c7858bd6f50317719"
+"checksum rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c5b02c76cd1ee4e9c97c8228701796d6b7431e8f100dea2d8af1d6c2c2bad56"
+"checksum rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076388154497fb9a007e3badd78e415402a5594111cd6bc7ce1420dd1b1818b"
+"checksum rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c11e4789cbc276ceaa87d326c234b1a2d1e0fe6017b88a8a25903200060acb"
+"checksum rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25f711bb152b9d7cdd69410cfe6d99aeb1409c959e0fdf3c8ca4d220e568aa52"
+"checksum rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57638db658d4942d3f30a12566836f9a67a636ed8002c8cae1c9231214e39929"
+"checksum rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6dbcf07abf7a9957dce8d34353d55dfb4cd882153181f24349f4690facb58f0"
+"checksum rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0915cb5e166cabe588a129dec2d47357077e96fb1f9b57318fbe217eac4ce508"
 "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
index a54e58665cceb8177b936b6744c0bfe50537e683..bb5a21e3e405fd034f35d33373006369333bfc21 100644 (file)
@@ -37,6 +37,8 @@ fn main() {
     let mut dylib_path = bootstrap::util::dylib_path();
     dylib_path.insert(0, PathBuf::from(libdir.clone()));
 
+    //FIXME(misdreavus): once stdsimd uses cfg(rustdoc) instead of cfg(dox), remove the `--cfg dox`
+    //arguments here
     let mut cmd = Command::new(rustdoc);
     cmd.args(&args)
         .arg("--cfg")
index c6ff63ad71b80b217ae902aaea4a6100e4a32c0d..167e4a78edaf8e9a251d21eb7e9273c306e9c3dd 100644 (file)
@@ -501,6 +501,13 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
             t!(fs::create_dir_all(&backends_dst));
             builder.cp_r(&backends_src, &backends_dst);
 
+            // Copy libLLVM.so to the lib dir as well, if needed. While not
+            // technically needed by rustc itself it's needed by lots of other
+            // components like the llvm tools and LLD. LLD is included below and
+            // tools/LLDB come later, so let's just throw it in the rustc
+            // component for now.
+            maybe_install_llvm_dylib(builder, host, image);
+
             // Copy over lld if it's there
             if builder.config.lld_enabled {
                 let exe = exe("rust-lld", &compiler.host);
@@ -1895,6 +1902,16 @@ fn maybe_install_llvm_dylib(builder: &Builder,
     let src_libdir = builder
         .llvm_out(target)
         .join("lib");
+    let dst_libdir = image.join("lib/rustlib").join(&*target).join("lib");
+    t!(fs::create_dir_all(&dst_libdir));
+
+    if target.contains("apple-darwin") {
+        let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
+        if llvm_dylib_path.exists() {
+            builder.install(&llvm_dylib_path, &dst_libdir, 0o644);
+        }
+        return
+    }
 
     // Usually libLLVM.so is a symlink to something like libLLVM-6.0.so.
     // Since tools link to the latter rather than the former, we have to
@@ -1906,8 +1923,6 @@ fn maybe_install_llvm_dylib(builder: &Builder,
                    llvm_dylib_path.display(), e);
         });
 
-        let dst_libdir = image.join("lib");
-        t!(fs::create_dir_all(&dst_libdir));
 
         builder.install(&llvm_dylib_path, &dst_libdir, 0o644);
     }
@@ -1960,15 +1975,15 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         let src_bindir = builder
             .llvm_out(target)
             .join("bin");
-        let dst_bindir = image.join("bin");
+        let dst_bindir = image.join("lib/rustlib")
+            .join(&*target)
+            .join("bin");
         t!(fs::create_dir_all(&dst_bindir));
         for tool in LLVM_TOOLS {
             let exe = src_bindir.join(exe(tool, &target));
             builder.install(&exe, &dst_bindir, 0o755);
         }
 
-        maybe_install_llvm_dylib(builder, target, &image);
-
         // Prepare the overlay
         let overlay = tmp.join("llvm-tools-overlay");
         drop(fs::remove_dir_all(&overlay));
@@ -2087,9 +2102,6 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
             }
         }
 
-        // Copy libLLVM.so to the lib dir as well, if needed.
-        maybe_install_llvm_dylib(builder, target, &image);
-
         // Prepare the overlay
         let overlay = tmp.join("lldb-overlay");
         drop(fs::remove_dir_all(&overlay));
index 60b4d65f444014133bd81262a7cbdcabea84bdfe..2084b8bdb65ffb859bb74195c6ec764ad4069afc 100644 (file)
@@ -125,7 +125,8 @@ pub fn parse(args: &[String]) -> Flags {
             "stage to build (indicates compiler to use/test, e.g. stage 0 uses the \
              bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
             "N");
-        opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N");
+        opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling \
+            (pass multiple times to keep e.g. both stages 0 and 1)", "N");
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
         opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
         opts.optflag("h", "help", "print this help message");
index 6445ce8da332ea95904fb6b8a7ebbfd16f09d029..e6ee525ca2e0304bf4a8f615b3a6288361f2bc17 100644 (file)
@@ -37,7 +37,7 @@
 //! Note that this module has a #[cfg(windows)] above it as none of this logic
 //! is required on Unix.
 
-#![allow(bad_style, dead_code)]
+#![allow(nonstandard_style, dead_code)]
 
 use std::env;
 use std::io;
index b6a89e1c18fab7763ee7ee00d81c9d7deba68240..2725abdc3d95f4774ee4cfe31040aa68634a9155 100644 (file)
@@ -211,6 +211,7 @@ pub unsafe fn setup(_build: &mut ::Build) {
     "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume
     "llvm-objdump", // used to disassemble programs
     "llvm-profdata", // used to inspect and merge files generated by profiles
+    "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide
     "llvm-size", // used to prints the size of the linker sections of a program
     "llvm-strip", // used to discard symbols from binary files to reduce their size
 ];
index c28b467df5093138f547c3f52f668424332da755..347c2472c6b9b6d75197795090bf4ed85fda3771 100644 (file)
@@ -145,6 +145,7 @@ fn run(self, builder: &Builder) -> PathBuf {
            .define("LLVM_INCLUDE_EXAMPLES", "OFF")
            .define("LLVM_INCLUDE_TESTS", "OFF")
            .define("LLVM_INCLUDE_DOCS", "OFF")
+           .define("LLVM_INCLUDE_BENCHMARKS", "OFF")
            .define("LLVM_ENABLE_ZLIB", "OFF")
            .define("WITH_POLLY", "OFF")
            .define("LLVM_ENABLE_TERMINFO", "OFF")
index be03796921af865b7c2c3d0a16b75d6d6272c888..8ce8f20add3ad20fa2d5e61ae629cf7364cd0888 100644 (file)
@@ -137,7 +137,7 @@ fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
     //
     // Copied from std
     #[cfg(windows)]
-    #[allow(bad_style)]
+    #[allow(nonstandard_style)]
     fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
         use std::ptr;
         use std::ffi::OsStr;
index e072959baa9c2bce08663d01606677f626d22921..e2484b7224b26fb96decc794a86464ee6fb3a495 100644 (file)
@@ -102,6 +102,7 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
+ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 ENV TARGETS=$TARGETS,armebv7r-none-eabi
 ENV TARGETS=$TARGETS,armebv7r-none-eabihf
index a91c2cd71cde34ce85c46f1960e9c6d3b6c39e10..32fb8c2f7d58e4f9330946fef58512f133d37076 100644 (file)
@@ -106,27 +106,25 @@ The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders docume
 item, it will be accompanied by a banner explaining that the item is only available on certain
 platforms.
 
-As mentioned earlier, getting the items to Rustdoc requires some extra preparation. The standard
-library adds a `--cfg dox` flag to every Rustdoc command, but the same thing can be accomplished by
-adding a feature to your Cargo.toml and adding `--feature dox` (or whatever you choose to name the
-feature) to your `cargo doc` calls.
+For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently
+running on. To aid this, Rustdoc sets the flag `#[cfg(rustdoc)]` when running on your crate.
+Combining this with the target platform of a given item allows it to appear when building your crate
+normally on that platform, as well as when building documentation anywhere.
 
-Either way, once you create an environment for the documentation, you can start to augment your
-`#[cfg]` attributes to allow both the target platform *and* the documentation configuration to leave
-the item in. For example, `#[cfg(any(windows, feature = "dox"))]` will preserve the item either on
-Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]`
-will tell Rustdoc that the item is supposed to be used on Windows. For example:
+For example, `#[cfg(any(windows, rustdoc))]` will preserve the item either on Windows or during the
+documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that
+the item is supposed to be used on Windows. For example:
 
 ```rust
 #![feature(doc_cfg)]
 
 /// Token struct that can only be used on Windows.
-#[cfg(any(windows, feature = "dox"))]
+#[cfg(any(windows, rustdoc))]
 #[doc(cfg(windows))]
 pub struct WindowsToken;
 
 /// Token struct that can only be used on Unix.
-#[cfg(any(unix, feature = "dox"))]
+#[cfg(any(unix, rustdoc))]
 #[doc(cfg(unix))]
 pub struct UnixToken;
 ```
@@ -361,6 +359,21 @@ This flag allows rustdoc to treat your rust code as the given edition. It will c
 the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015`
 (the first edition).
 
+### `--extern-html-root-url`: control how rustdoc links to non-local crates
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --extern-html-root-url some-crate=https://example.com/some-crate/1.0.1
+```
+
+Ordinarily, when rustdoc wants to link to a type from a different crate, it looks in two places:
+docs that already exist in the output directory, or the `#![doc(doc_html_root)]` set in the other
+crate. However, if you want to link to docs that exist in neither of those places, you can use these
+flags to control that behavior. When the `--extern-html-root-url` flag is given with a name matching
+one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist
+in the output directory, those local docs will still override this flag.
+
 ### `-Z force-unstable-if-unmarked`
 
 Using this flag looks like this:
diff --git a/src/doc/unstable-book/src/language-features/custom-test-frameworks.md b/src/doc/unstable-book/src/language-features/custom-test-frameworks.md
new file mode 100644 (file)
index 0000000..3990b6a
--- /dev/null
@@ -0,0 +1,33 @@
+# `custom_test_frameworks`
+
+The tracking issue for this feature is: [#50297]
+
+[#50297]: https://github.com/rust-lang/rust/issues/50297
+
+------------------------
+
+The `custom_test_frameworks` feature allows the use of `#[test_case]` and `#![test_runner]`.
+Any function, const, or static can be annotated with `#[test_case]` causing it to be aggregated (like `#[test]`)
+and be passed to the test runner determined by the `#![test_runner]` crate attribute.
+
+```rust
+#![feature(custom_test_frameworks)]
+#![test_runner(my_runner)]
+
+fn my_runner(tests: &[&i32]) {
+    for t in tests {
+        if **t == 0 {
+            println!("PASSED");
+        } else {
+            println!("FAILED");
+        }
+    }
+}
+
+#[test_case]
+const WILL_PASS: i32 = 0;
+
+#[test_case]
+const WILL_FAIL: i32 = 4;
+```
+
index ddc538e12144ac5ff5a2d692d5aba400c4ca3843..96c66a1515ed5495b2da721e641ce191fe5167f7 100644 (file)
@@ -12,13 +12,17 @@ This attribute has two effects:
 
 2. The item's doc-tests will only run on the specific platform.
 
+In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a
+special conditional compilation flag, `#[cfg(rustdoc)]`, set whenever building documentation on your
+crate.
+
 This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the
 standard library be documented.
 
 ```rust
 #![feature(doc_cfg)]
 
-#[cfg(any(windows, feature = "documentation"))]
+#[cfg(any(windows, rustdoc))]
 #[doc(cfg(windows))]
 /// The application's icon in the notification area (a.k.a. system tray).
 ///
@@ -39,4 +43,4 @@ pub struct Icon {
 ```
 
 [#43781]: https://github.com/rust-lang/rust/issues/43781
-[#43348]: https://github.com/rust-lang/rust/issues/43348
\ No newline at end of file
+[#43348]: https://github.com/rust-lang/rust/issues/43348
diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui
new file mode 100755 (executable)
index 0000000..7e179ba
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh
+# 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.
+
+# Exit if anything fails
+set -e
+
+if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ]; then
+    echo "
+rust-gdbgui
+===========
+gdbgui - https://gdbgui.com - is a graphical front-end to GDB
+that runs in a browser. This script invokes gdbgui with the Rust
+pretty printers loaded.
+
+Simple usage  : rust-gdbgui target/debug/myprog
+With arguments: rust-gdbgui 'target/debug/myprog arg1 arg2...'
+  (note the quotes)
+
+
+Hints
+=====
+gdbgui won't be able to find the rust 'main' method automatically, so
+in its options make sure to disable the 'Add breakpoint to main after
+loading executable' setting to avoid a 'File not found: main' warning
+on startup.
+
+Instead, type 'main' into gdbgui's file browser and you should get
+auto-completion on the filename. Just pick 'main.rs', add a breakpoint
+by clicking in the line number gutter, and type 'r' or hit the Restart
+icon to start your program running.
+"
+    exit 0
+fi
+
+# Find out where the pretty printer Python module is
+RUSTC_SYSROOT=`rustc --print=sysroot`
+GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
+
+# Set the environment variable `RUST_GDB` to overwrite the call to a
+# different/specific command (defaults to `gdb`).
+RUST_GDB="${RUST_GDB:-gdb}"
+
+# Set the environment variable `RUST_GDBGUI` to overwrite the call to a
+# different/specific command (defaults to `gdbgui`).
+RUST_GDBGUI="${RUST_GDBGUI:-gdbgui}"
+
+# These arguments get passed through to GDB and make it load the
+# Rust pretty printers.
+GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\" -iex \"add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY\""
+
+# Finally we execute gdbgui.
+PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" \
+  exec ${RUST_GDBGUI} \
+  --gdb ${RUST_GDB} \
+  --gdb-args "${GDB_ARGS}" \
+  "${@}"
+
index 1dad323769a07b95f0ae315544cc68dd26df1b4f..642a43d4d9c2bc1a8d53a2db094183da8ffc8066 100644 (file)
@@ -14,7 +14,7 @@ core = { path = "../libcore" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 
 [dev-dependencies]
-rand = "0.4"
+rand = "0.5"
 
 [[test]]
 name = "collectionstests"
index c6741ddb822d5bb9114889bc71fdd2203f72e559..5ae5339138fbed3ef3bbc1049ca1d686f094f924 100644 (file)
@@ -141,6 +141,41 @@ fn clone_into(&self, target: &mut T) {
 /// let mut input = Cow::from(vec![-1, 0, 1]);
 /// abs_all(&mut input);
 /// ```
+///
+/// Another example showing how to keep `Cow` in a struct:
+///
+/// ```
+/// use std::borrow::{Cow, ToOwned};
+///
+/// struct Items<'a, X: 'a> where [X]: ToOwned<Owned=Vec<X>> {
+///     values: Cow<'a, [X]>,
+/// }
+///
+/// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned<Owned=Vec<X>> {
+///     fn new(v: Cow<'a, [X]>) -> Self {
+///         Items { values: v }
+///     }
+/// }
+///
+/// // Creates a container from borrowed values of a slice
+/// let readonly = [1, 2];
+/// let borrowed = Items::new((&readonly[..]).into());
+/// match borrowed {
+///     Items { values: Cow::Borrowed(b) } => println!("borrowed {:?}", b),
+///     _ => panic!("expect borrowed value"),
+/// }
+///
+/// let mut clone_on_write = borrowed;
+/// // Mutates the data from slice into owned vec and pushes a new value on top
+/// clone_on_write.values.to_mut().push(3);
+/// println!("clone_on_write = {:?}", clone_on_write.values);
+///
+/// // The data was mutated. Let check it out.
+/// match clone_on_write {
+///     Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"),
+///     _ => panic!("expect owned data"),
+/// }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Cow<'a, B: ?Sized + 'a>
     where B: ToOwned
index 9844de9a57d70274c4bf91cc93d79da0e381acf4..2ef84dbade0fbc480f96529db85988407f45e241 100644 (file)
@@ -1222,7 +1222,7 @@ mod tests {
     use std::thread;
     use std::vec::Vec;
 
-    use rand::{thread_rng, Rng};
+    use rand::{thread_rng, RngCore};
 
     use super::{LinkedList, Node};
 
index 676c977514f320299f06087a34521b7f5312f9d8..452d2b1472ff4a2fb8d9b29e7097ae6da75700fb 100644 (file)
@@ -88,7 +88,8 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
index 2cd7898f4c78134678cfee3e4750ecc3f10a6d89..db7a4044b267f7eedc0cecf47473790d73e4adbf 100644 (file)
 ///
 /// The type `Arc<T>` provides shared ownership of a value of type `T`,
 /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
-/// a new pointer to the same value in the heap. When the last `Arc`
-/// pointer to a given value is destroyed, the pointed-to value is
-/// also destroyed.
+/// a new `Arc` instance, which points to the same value on the heap as the
+/// source `Arc`, while increasing a reference count. When the last `Arc`
+/// pointer to a given value is destroyed, the pointed-to value is also
+/// destroyed.
 ///
 /// Shared references in Rust disallow mutation by default, and `Arc` is no
 /// exception: you cannot generally obtain a mutable reference to something
 /// // The two syntaxes below are equivalent.
 /// let a = foo.clone();
 /// let b = Arc::clone(&foo);
-/// // a and b both point to the same memory location as foo.
+/// // a, b, and foo are all Arcs that point to the same memory location
 /// ```
 ///
 /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly
index 3a84f9e7e47ba03675da89abf666196db22bcc52..710c659ac53962b18c1b6bb4bf75900171ac9fca 100644 (file)
@@ -11,7 +11,8 @@
 #![feature(allocator_api)]
 #![feature(alloc_system)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
 #![feature(pattern)]
index df5e18a9a184ecc60a9afa90c19cf4a508109d28..f33bf64d40bdef79e987a809039b44891e0aad13 100644 (file)
@@ -18,7 +18,8 @@
 use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize};
 use std::thread;
 
-use rand::{Rng, thread_rng};
+use rand::{Rng, RngCore, thread_rng};
+use rand::distributions::Standard;
 
 fn square(n: usize) -> usize {
     n * n
@@ -405,7 +406,7 @@ fn test_sort() {
     for len in (2..25).chain(500..510) {
         for &modulus in &[5, 10, 100, 1000] {
             for _ in 0..10 {
-                let orig: Vec<_> = rng.gen_iter::<i32>()
+                let orig: Vec<_> = rng.sample_iter::<i32, _>(&Standard)
                     .map(|x| x % modulus)
                     .take(len)
                     .collect();
index 6275c7bb112063dc2205fc75698a7d6f7b8d3ba1..a5fa7f0c4d938a96332bc64bf6ee64ad528698a8 100644 (file)
@@ -727,33 +727,33 @@ fn test_is_char_boundary() {
 }
 
 #[test]
-fn test_trim_left_matches() {
+fn test_trim_start_matches() {
     let v: &[char] = &[];
-    assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
+    assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
     let chars: &[char] = &['*', ' '];
-    assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
-    assert_eq!(" ***  *** ".trim_left_matches(chars), "");
-    assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
+    assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
+    assert_eq!(" ***  *** ".trim_start_matches(chars), "");
+    assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
 
-    assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
     let chars: &[char] = &['1', '2'];
-    assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
-    assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
+    assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
+    assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
 }
 
 #[test]
-fn test_trim_right_matches() {
+fn test_trim_end_matches() {
     let v: &[char] = &[];
-    assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
+    assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
     let chars: &[char] = &['*', ' '];
-    assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
-    assert_eq!(" ***  *** ".trim_right_matches(chars), "");
-    assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
+    assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
+    assert_eq!(" ***  *** ".trim_end_matches(chars), "");
+    assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
 
-    assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+    assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
     let chars: &[char] = &['1', '2'];
-    assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
-    assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
+    assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
+    assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
 }
 
 #[test]
@@ -772,23 +772,23 @@ fn test_trim_matches() {
 }
 
 #[test]
-fn test_trim_left() {
-    assert_eq!("".trim_left(), "");
-    assert_eq!("a".trim_left(), "a");
-    assert_eq!("    ".trim_left(), "");
-    assert_eq!("     blah".trim_left(), "blah");
-    assert_eq!("   \u{3000}  wut".trim_left(), "wut");
-    assert_eq!("hey ".trim_left(), "hey ");
+fn test_trim_start() {
+    assert_eq!("".trim_start(), "");
+    assert_eq!("a".trim_start(), "a");
+    assert_eq!("    ".trim_start(), "");
+    assert_eq!("     blah".trim_start(), "blah");
+    assert_eq!("   \u{3000}  wut".trim_start(), "wut");
+    assert_eq!("hey ".trim_start(), "hey ");
 }
 
 #[test]
-fn test_trim_right() {
-    assert_eq!("".trim_right(), "");
-    assert_eq!("a".trim_right(), "a");
-    assert_eq!("    ".trim_right(), "");
-    assert_eq!("blah     ".trim_right(), "blah");
-    assert_eq!("wut   \u{3000}  ".trim_right(), "wut");
-    assert_eq!(" hey".trim_right(), " hey");
+fn test_trim_end() {
+    assert_eq!("".trim_end(), "");
+    assert_eq!("a".trim_end(), "a");
+    assert_eq!("    ".trim_end(), "");
+    assert_eq!("blah     ".trim_end(), "blah");
+    assert_eq!("wut   \u{3000}  ".trim_end(), "wut");
+    assert_eq!(" hey".trim_end(), " hey");
 }
 
 #[test]
@@ -1518,12 +1518,20 @@ fn trim_ws() {
                     "a \t  ");
     assert_eq!(" \t  a \t  ".trim_right_matches(|c: char| c.is_whitespace()),
                " \t  a");
+    assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
+                    "a \t  ");
+    assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
+               " \t  a");
     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
                     "a");
     assert_eq!(" \t   \t  ".trim_left_matches(|c: char| c.is_whitespace()),
                          "");
     assert_eq!(" \t   \t  ".trim_right_matches(|c: char| c.is_whitespace()),
                "");
+    assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
+                         "");
+    assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
+               "");
     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
                "");
 }
index ffab9e8e4af3c561032c23613f62f88400d92172..8848be5903810ef96bdbc44dda078a543e1c4fe0 100644 (file)
@@ -220,7 +220,7 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
 }
 
 #[cfg(windows)]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod platform {
     use MIN_ALIGN;
     use System;
index d549d85b1735dc5066b2973f8549557a813bb9c8..0703bfa72524e01e414477657ca9b64794c5c1c3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d549d85b1735dc5066b2973f8549557a813bb9c8
+Subproject commit 0703bfa72524e01e414477657ca9b64794c5c1c3
index 321ed892ea9a986337baa7ea902215e27202f816..0b01cfc488bbaf83fd80b02ce4361957f4967456 100644 (file)
@@ -20,4 +20,4 @@ name = "corebenches"
 path = "../libcore/benches/lib.rs"
 
 [dev-dependencies]
-rand = "0.4"
+rand = "0.5"
index 67e02cf9509b6cd8ba71db2be4dd19cea9946ce0..f4f01eb1cf5d29d84d8c4466a209e103bc24d99f 100644 (file)
@@ -15,7 +15,7 @@
 fn bench_downcast_ref(b: &mut Bencher) {
     b.iter(|| {
         let mut x = 0;
-        let mut y = &mut x as &mut Any;
+        let mut y = &mut x as &mut dyn Any;
         black_box(&mut y);
         black_box(y.downcast_ref::<isize>() == Some(&0));
     });
index 58d6c4f5e09236640c8be496f352e6797c84c5ef..ef7d83a0993da134e3d670408c7b0008e59ee7b1 100644 (file)
 /// the same book if their ISBN matches, even if the formats differ:
 ///
 /// ```
-/// enum BookFormat { Paperback, Hardback, Ebook }
+/// enum BookFormat {
+///     Paperback,
+///     Hardback,
+///     Ebook,
+/// }
+///
 /// struct Book {
 ///     isbn: i32,
 ///     format: BookFormat,
 /// assert!(b1 != b3);
 /// ```
 ///
+/// ## How can I compare two different types?
+///
+/// The type you can compare with is controlled by `PartialEq`'s type parameter.
+/// For example, let's tweak our previous code a bit:
+///
+/// ```
+/// enum BookFormat {
+///     Paperback,
+///     Hardback,
+///     Ebook,
+/// }
+///
+/// struct Book {
+///     isbn: i32,
+///     format: BookFormat,
+/// }
+///
+/// impl PartialEq<BookFormat> for Book {
+///     fn eq(&self, other: &BookFormat) -> bool {
+///         match (&self.format, other) {
+///            (BookFormat::Paperback, BookFormat::Paperback) => true,
+///            (BookFormat::Hardback,  BookFormat::Hardback)  => true,
+///            (BookFormat::Ebook,     BookFormat::Ebook)     => true,
+///            (_, _) => false,
+///         }
+///     }
+/// }
+///
+/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
+///
+/// assert!(b1 == BookFormat::Paperback);
+/// assert!(b1 != BookFormat::Ebook);
+/// ```
+///
+/// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
+/// we've changed what type we can use on the right side of the `==` operator.
+/// This lets us use it in the `assert!` statements at the bottom.
+///
+/// You can also combine these implementations to let the `==` operator work with
+/// two different types:
+///
+/// ```
+/// enum BookFormat {
+///     Paperback,
+///     Hardback,
+///     Ebook,
+/// }
+///
+/// struct Book {
+///     isbn: i32,
+///     format: BookFormat,
+/// }
+///
+/// impl PartialEq<BookFormat> for Book {
+///     fn eq(&self, other: &BookFormat) -> bool {
+///         match (&self.format, other) {
+///            (&BookFormat::Paperback, &BookFormat::Paperback) => true,
+///            (&BookFormat::Hardback,  &BookFormat::Hardback)  => true,
+///            (&BookFormat::Ebook,     &BookFormat::Ebook)     => true,
+///            (_, _) => false,
+///         }
+///     }
+/// }
+///
+/// impl PartialEq for Book {
+///     fn eq(&self, other: &Book) -> bool {
+///         self.isbn == other.isbn
+///     }
+/// }
+///
+/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
+/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
+///
+/// assert!(b1 == BookFormat::Paperback);
+/// assert!(b1 != BookFormat::Ebook);
+/// assert!(b1 == b2);
+/// ```
+///
 /// # Examples
 ///
 /// ```
index 651c7a35d413c6478b6e661b23dbd586208be6a6..55addd86bc1cef81810c8830952fc5a4e2a11c55 100644 (file)
@@ -165,8 +165,16 @@ fn add_usize(&self, n: usize) -> Option<Self> {
     )*)
 }
 
-step_impl_unsigned!(usize u8 u16 u32);
-step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]);
+step_impl_unsigned!(usize u8 u16);
+#[cfg(not(target_pointer_witdth = "16"))]
+step_impl_unsigned!(u32);
+#[cfg(target_pointer_witdth = "16")]
+step_impl_no_between!(u32);
+step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
+#[cfg(not(target_pointer_witdth = "16"))]
+step_impl_signed!([i32: u32]);
+#[cfg(target_pointer_witdth = "16")]
+step_impl_no_between!(i32);
 #[cfg(target_pointer_width = "64")]
 step_impl_unsigned!(u64);
 #[cfg(target_pointer_width = "64")]
index 2aa3226af8960b553dcd05ed3a7568021ce5af7d..b0c93316301c44dbf822d01c28809a48ef1ad4f9 100644 (file)
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
+#![feature(const_let)]
+#![feature(const_int_rotate)]
+#![feature(const_int_wrapping)]
+#![feature(const_int_sign)]
+#![feature(const_int_conversion)]
+#![feature(const_transmute)]
+#![feature(reverse_bits)]
 #![feature(non_exhaustive)]
 
 #[prelude_import]
index 5b3b2d1635688e8c04d5d9ee93e97321e2825a50..0032bedc7ed1de518390c363f30171a5900cc274 100644 (file)
@@ -541,7 +541,7 @@ macro_rules! unimplemented {
 /// into libsyntax itself.
 ///
 /// For more information, see documentation for `std`'s macros.
-#[cfg(dox)]
+#[cfg(rustdoc)]
 mod builtin {
 
     /// Unconditionally causes compilation to fail with the given error message when encountered.
index f2852d98282b7be7df5cecdc89b52bbaa4523398..e00a22bf8b6c360674bcd3ec5da5573e49cb0cf6 100644 (file)
@@ -285,6 +285,15 @@ pub fn forget<T>(t: T) {
 /// [alignment]: ./fn.align_of.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+pub const fn size_of<T>() -> usize {
+    intrinsics::size_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
 pub const fn size_of<T>() -> usize {
     unsafe { intrinsics::size_of::<T>() }
 }
@@ -334,6 +343,16 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+#[cfg(not(stage0))]
+pub fn min_align_of<T>() -> usize {
+    intrinsics::min_align_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
 pub fn min_align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
@@ -376,6 +395,15 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+pub const fn align_of<T>() -> usize {
+    intrinsics::min_align_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
 pub const fn align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
index b93428c6321f61e27f8d4279b1c1e02cdd206379..19d3ad20247130fa6c33ec920eec8f1a78aab6a8 100644 (file)
@@ -338,6 +338,14 @@ pub const fn trailing_zeros(self) -> u32 {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn rotate_left(self, n: u32) -> Self {
+            (self as $UnsignedT).rotate_left(n) as Self
+        }
+
         doc_comment! {
             concat!("Shifts the bits to the left by a specified amount, `n`,
 wrapping the truncated bits to the end of the resulting integer.
@@ -355,12 +363,22 @@ pub const fn trailing_zeros(self) -> u32 {
 assert_eq!(n.rotate_left(", $rot, "), m);
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_rotate")]
             #[inline]
-            pub fn rotate_left(self, n: u32) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn rotate_left(self, n: u32) -> Self {
                 (self as $UnsignedT).rotate_left(n) as Self
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn rotate_right(self, n: u32) -> Self {
+            (self as $UnsignedT).rotate_right(n) as Self
+        }
+
         doc_comment! {
             concat!("Shifts the bits to the right by a specified amount, `n`,
 wrapping the truncated bits to the beginning of the resulting
@@ -379,11 +397,14 @@ pub fn rotate_left(self, n: u32) -> Self {
 assert_eq!(n.rotate_right(", $rot, "), m);
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_rotate")]
             #[inline]
-            pub fn rotate_right(self, n: u32) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn rotate_right(self, n: u32) -> Self {
                 (self as $UnsignedT).rotate_right(n) as Self
             }
         }
+
         doc_comment! {
             concat!("Reverses the byte order of the integer.
 
@@ -406,6 +427,14 @@ pub const fn swap_bytes(self) -> Self {
             }
         }
 
+        /// no docs here
+        #[unstable(feature = "reverse_bits", issue = "48763")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn reverse_bits(self) -> Self {
+            (self as $UnsignedT).reverse_bits() as Self
+        }
+
         doc_comment! {
             concat!("Reverses the bit pattern of the integer.
 
@@ -422,8 +451,10 @@ pub const fn swap_bytes(self) -> Self {
 assert_eq!(m, ", $reversed, ");
 ```"),
             #[unstable(feature = "reverse_bits", issue = "48763")]
+            #[rustc_const_unstable(feature = "const_int_conversion")]
             #[inline]
-            pub fn reverse_bits(self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn reverse_bits(self) -> Self {
                 (self as $UnsignedT).reverse_bits() as Self
             }
         }
@@ -973,6 +1004,16 @@ pub fn saturating_pow(self, exp: u32) -> Self {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_add(self, rhs: Self) -> Self {
+            unsafe {
+                intrinsics::overflowing_add(self, rhs)
+            }
+        }
+
         doc_comment! {
             concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the
 boundary of the type.
@@ -988,14 +1029,26 @@ pub fn saturating_pow(self, exp: u32) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_add(self, rhs: Self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_add(self, rhs: Self) -> Self {
                 unsafe {
                     intrinsics::overflowing_add(self, rhs)
                 }
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_sub(self, rhs: Self) -> Self {
+            unsafe {
+                intrinsics::overflowing_sub(self, rhs)
+            }
+        }
+
         doc_comment! {
             concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
 boundary of the type.
@@ -1011,14 +1064,26 @@ pub fn wrapping_add(self, rhs: Self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_sub(self, rhs: Self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_sub(self, rhs: Self) -> Self {
                 unsafe {
                     intrinsics::overflowing_sub(self, rhs)
                 }
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_mul(self, rhs: Self) -> Self {
+            unsafe {
+                intrinsics::overflowing_mul(self, rhs)
+            }
+        }
+
         doc_comment! {
             concat!("Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
 the boundary of the type.
@@ -1033,8 +1098,10 @@ pub fn wrapping_sub(self, rhs: Self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_mul(self, rhs: Self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_mul(self, rhs: Self) -> Self {
                 unsafe {
                     intrinsics::overflowing_mul(self, rhs)
                 }
@@ -1177,6 +1244,16 @@ pub fn wrapping_neg(self) -> Self {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
         doc_comment! {
             concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes
 any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
@@ -1196,14 +1273,26 @@ pub fn wrapping_neg(self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_shl(self, rhs: u32) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_shl(self, rhs: u32) -> Self {
                 unsafe {
                     intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
                 }
             }
         }
 
+        /// no docs here
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
         doc_comment! {
             concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask`
 removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type.
@@ -1223,8 +1312,10 @@ pub fn wrapping_shl(self, rhs: u32) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_shr(self, rhs: u32) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_shr(self, rhs: u32) -> Self {
                 unsafe {
                     intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
                 }
@@ -1302,6 +1393,18 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = unsafe {
+                intrinsics::add_with_overflow(self as $ActualT,
+                                                rhs as $ActualT)
+            };
+            (a as Self, b)
+        }
+
         doc_comment! {
             concat!("Calculates `self` + `rhs`
 
@@ -1319,9 +1422,11 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self {
 assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT),
 "::MIN, true));", $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
                 let (a, b) = unsafe {
                     intrinsics::add_with_overflow(self as $ActualT,
                                                   rhs as $ActualT)
@@ -1330,6 +1435,18 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = unsafe {
+                intrinsics::sub_with_overflow(self as $ActualT,
+                                                rhs as $ActualT)
+            };
+            (a as Self, b)
+        }
+
         doc_comment! {
             concat!("Calculates `self` - `rhs`
 
@@ -1347,9 +1464,11 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT),
 "::MAX, true));", $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
                 let (a, b) = unsafe {
                     intrinsics::sub_with_overflow(self as $ActualT,
                                                   rhs as $ActualT)
@@ -1358,6 +1477,18 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = unsafe {
+                intrinsics::mul_with_overflow(self as $ActualT,
+                                                rhs as $ActualT)
+            };
+            (a as Self, b)
+        }
+
         doc_comment! {
             concat!("Calculates the multiplication of `self` and `rhs`.
 
@@ -1373,9 +1504,11 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
 assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));",
 $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
                 let (a, b) = unsafe {
                     intrinsics::mul_with_overflow(self as $ActualT,
                                                   rhs as $ActualT)
@@ -1545,6 +1678,14 @@ pub fn overflowing_neg(self) -> (Self, bool) {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+        }
+
         doc_comment! {
             concat!("Shifts self left by `rhs` bits.
 
@@ -1561,13 +1702,23 @@ pub fn overflowing_neg(self) -> (Self, bool) {
 assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));",
 $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+        }
+
         doc_comment! {
             concat!("Shifts self right by `rhs` bits.
 
@@ -1584,9 +1735,11 @@ pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
 assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));",
 $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
             }
         }
@@ -1850,6 +2003,12 @@ pub fn signum(self) -> Self {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn is_positive(self) -> bool { self > 0 }
+
         doc_comment! {
             concat!("Returns `true` if `self` is positive and `false` if the number is zero or
 negative.
@@ -1864,10 +2023,18 @@ pub fn signum(self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_sign")]
             #[inline]
-            pub fn is_positive(self) -> bool { self > 0 }
+            #[cfg(not(stage0))]
+            pub const fn is_positive(self) -> bool { self > 0 }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn is_negative(self) -> bool { self < 0 }
+
         doc_comment! {
             concat!("Returns `true` if `self` is negative and `false` if the number is zero or
 positive.
@@ -1882,8 +2049,18 @@ pub fn is_positive(self) -> bool { self > 0 }
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_sign")]
             #[inline]
-            pub fn is_negative(self) -> bool { self < 0 }
+            #[cfg(not(stage0))]
+            pub const fn is_negative(self) -> bool { self < 0 }
+        }
+
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_be().to_ne_bytes()
         }
 
         /// Return the memory representation of this integer as a byte array in
@@ -1898,11 +2075,21 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        #[cfg(not(stage0))]
+        pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
             self.to_be().to_ne_bytes()
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_le().to_ne_bytes()
+        }
+
         /// Return the memory representation of this integer as a byte array in
         /// little-endian byte order.
         ///
@@ -1915,11 +2102,21 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        #[cfg(not(stage0))]
+        pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
             self.to_le().to_ne_bytes()
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            unsafe { mem::transmute(self) }
+        }
+
         /// Return the memory representation of this integer as a byte array in
         /// native byte order.
         ///
@@ -1939,11 +2136,21 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// assert_eq!(bytes, [0x80, 0, 0, 0]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        #[cfg(not(stage0))]
+        pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
             unsafe { mem::transmute(self) }
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_be(Self::from_ne_bytes(bytes))
+        }
+
         /// Create an integer value from its representation as a byte array in
         /// big endian.
         ///
@@ -1956,11 +2163,21 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// assert_eq!(int, 0x12_34_56_78);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             Self::from_be(Self::from_ne_bytes(bytes))
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_le(Self::from_ne_bytes(bytes))
+        }
+
         /// Create an integer value from its representation as a byte array in
         /// little endian.
         ///
@@ -1973,11 +2190,21 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// assert_eq!(int, 0x78_56_34_12);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             Self::from_le(Self::from_ne_bytes(bytes))
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            unsafe { mem::transmute(bytes) }
+        }
+
         /// Create an integer value from its memory representation as a byte
         /// array in native endianness.
         ///
@@ -1997,8 +2224,10 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// assert_eq!(int, i32::min_value());
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             unsafe { mem::transmute(bytes) }
         }
     }
@@ -2217,6 +2446,16 @@ pub const fn trailing_zeros(self) -> u32 {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn rotate_left(self, n: u32) -> Self {
+            // Protect against undefined behaviour for over-long bit shifts
+            let n = n % $BITS;
+            (self << n) | (self >> (($BITS - n) % $BITS))
+        }
+
         doc_comment! {
             concat!("Shifts the bits to the left by a specified amount, `n`,
 wrapping the truncated bits to the end of the resulting integer.
@@ -2234,14 +2473,24 @@ pub const fn trailing_zeros(self) -> u32 {
 assert_eq!(n.rotate_left(", $rot, "), m);
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_rotate")]
             #[inline]
-            pub fn rotate_left(self, n: u32) -> Self {
-                // Protect against undefined behaviour for over-long bit shifts
-                let n = n % $BITS;
-                (self << n) | (self >> (($BITS - n) % $BITS))
+            #[cfg(not(stage0))]
+            pub const fn rotate_left(self, n: u32) -> Self {
+                (self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS))
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn rotate_right(self, n: u32) -> Self {
+            // Protect against undefined behaviour for over-long bit shifts
+            let n = n % $BITS;
+            (self >> n) | (self << (($BITS - n) % $BITS))
+        }
+
         doc_comment! {
             concat!("Shifts the bits to the right by a specified amount, `n`,
 wrapping the truncated bits to the beginning of the resulting
@@ -2260,11 +2509,11 @@ pub fn rotate_left(self, n: u32) -> Self {
 assert_eq!(n.rotate_right(", $rot, "), m);
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_rotate")]
             #[inline]
-            pub fn rotate_right(self, n: u32) -> Self {
-                // Protect against undefined behaviour for over-long bit shifts
-                let n = n % $BITS;
-                (self >> n) | (self << (($BITS - n) % $BITS))
+            #[cfg(not(stage0))]
+            pub const fn rotate_right(self, n: u32) -> Self {
+                (self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS))
             }
         }
 
@@ -2290,6 +2539,14 @@ pub const fn swap_bytes(self) -> Self {
             }
         }
 
+        /// no docs here
+        #[unstable(feature = "reverse_bits", issue = "48763")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn reverse_bits(self) -> Self {
+            unsafe { intrinsics::bitreverse(self as $ActualT) as Self }
+        }
+
         doc_comment! {
             concat!("Reverses the bit pattern of the integer.
 
@@ -2306,8 +2563,10 @@ pub const fn swap_bytes(self) -> Self {
 assert_eq!(m, ", $reversed, ");
 ```"),
             #[unstable(feature = "reverse_bits", issue = "48763")]
+            #[rustc_const_unstable(feature = "const_int_conversion")]
             #[inline]
-            pub fn reverse_bits(self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn reverse_bits(self) -> Self {
                 unsafe { intrinsics::bitreverse(self as $ActualT) as Self }
             }
         }
@@ -2795,6 +3054,16 @@ pub fn saturating_pow(self, exp: u32) -> Self {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_add(self, rhs: Self) -> Self {
+            unsafe {
+                intrinsics::overflowing_add(self, rhs)
+            }
+        }
+
         doc_comment! {
             concat!("Wrapping (modular) addition. Computes `self + rhs`,
 wrapping around at the boundary of the type.
@@ -2809,14 +3078,26 @@ pub fn saturating_pow(self, exp: u32) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_add(self, rhs: Self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_add(self, rhs: Self) -> Self {
                 unsafe {
                     intrinsics::overflowing_add(self, rhs)
                 }
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_sub(self, rhs: Self) -> Self {
+            unsafe {
+                intrinsics::overflowing_sub(self, rhs)
+            }
+        }
+
         doc_comment! {
             concat!("Wrapping (modular) subtraction. Computes `self - rhs`,
 wrapping around at the boundary of the type.
@@ -2831,14 +3112,26 @@ pub fn wrapping_add(self, rhs: Self) -> Self {
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_sub(self, rhs: Self) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_sub(self, rhs: Self) -> Self {
                 unsafe {
                     intrinsics::overflowing_sub(self, rhs)
                 }
             }
         }
 
+        /// no docs here
+        #[stable(feature = "rust1", since = "1.0.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_mul(self, rhs: Self) -> Self {
+            unsafe {
+                intrinsics::overflowing_mul(self, rhs)
+            }
+        }
+
         /// Wrapping (modular) multiplication. Computes `self *
         /// rhs`, wrapping around at the boundary of the type.
         ///
@@ -2854,8 +3147,10 @@ pub fn wrapping_sub(self, rhs: Self) -> Self {
         /// assert_eq!(25u8.wrapping_mul(12), 44);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_unstable(feature = "const_int_wrapping")]
         #[inline]
-        pub fn wrapping_mul(self, rhs: Self) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn wrapping_mul(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_mul(self, rhs)
             }
@@ -2976,6 +3271,16 @@ pub fn wrapping_neg(self) -> Self {
             self.overflowing_neg().0
         }
 
+        /// no docs here
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
         doc_comment! {
             concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`,
 where `mask` removes any high-order bits of `rhs` that
@@ -2997,14 +3302,26 @@ pub fn wrapping_neg(self) -> Self {
 assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_shl(self, rhs: u32) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_shl(self, rhs: u32) -> Self {
                 unsafe {
                     intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
                 }
             }
         }
 
+        /// no docs here
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
         doc_comment! {
             concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
 where `mask` removes any high-order bits of `rhs` that
@@ -3026,8 +3343,10 @@ pub fn wrapping_shl(self, rhs: u32) -> Self {
 assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_int_wrapping")]
             #[inline]
-            pub fn wrapping_shr(self, rhs: u32) -> Self {
+            #[cfg(not(stage0))]
+            pub const fn wrapping_shr(self, rhs: u32) -> Self {
                 unsafe {
                     intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
                 }
@@ -3072,6 +3391,18 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = unsafe {
+                intrinsics::add_with_overflow(self as $ActualT,
+                                                rhs as $ActualT)
+            };
+            (a as Self, b)
+        }
+
         doc_comment! {
             concat!("Calculates `self` + `rhs`
 
@@ -3089,9 +3420,11 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self {
 assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
 assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
                 let (a, b) = unsafe {
                     intrinsics::add_with_overflow(self as $ActualT,
                                                   rhs as $ActualT)
@@ -3100,6 +3433,18 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = unsafe {
+                intrinsics::sub_with_overflow(self as $ActualT,
+                                                rhs as $ActualT)
+            };
+            (a as Self, b)
+        }
+
         doc_comment! {
             concat!("Calculates `self` - `rhs`
 
@@ -3118,9 +3463,11 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
 assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));",
 $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
                 let (a, b) = unsafe {
                     intrinsics::sub_with_overflow(self as $ActualT,
                                                   rhs as $ActualT)
@@ -3129,6 +3476,18 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            let (a, b) = unsafe {
+                intrinsics::mul_with_overflow(self as $ActualT,
+                                              rhs as $ActualT)
+            };
+            (a as Self, b)
+        }
+
         /// Calculates the multiplication of `self` and `rhs`.
         ///
         /// Returns a tuple of the multiplication along with a boolean
@@ -3146,9 +3505,11 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
         /// assert_eq!(5u32.overflowing_mul(2), (10, false));
         /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true));
         /// ```
-        #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
-        pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+        #[rustc_const_unstable(feature = "const_int_overflowing")]
+        #[inline]
+        #[cfg(not(stage0))]
+        pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
             let (a, b) = unsafe {
                 intrinsics::mul_with_overflow(self as $ActualT,
                                               rhs as $ActualT)
@@ -3286,6 +3647,14 @@ pub fn overflowing_neg(self) -> (Self, bool) {
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+        }
+
         doc_comment! {
             concat!("Shifts self left by `rhs` bits.
 
@@ -3303,13 +3672,23 @@ pub fn overflowing_neg(self) -> (Self, bool) {
 ", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false));
 assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
             }
         }
 
+        /// no docs here
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+        }
+
         doc_comment! {
             concat!("Shifts self right by `rhs` bits.
 
@@ -3327,9 +3706,11 @@ pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
 ", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));
 assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, "
 ```"),
-            #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
-            pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
             }
         }
@@ -3571,6 +3952,14 @@ pub fn wrapping_next_power_of_two(self) -> Self {
             }
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_be().to_ne_bytes()
+        }
+
         /// Return the memory representation of this integer as a byte array in
         /// big-endian (network) byte order.
         ///
@@ -3583,11 +3972,21 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        #[cfg(not(stage0))]
+        pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
             self.to_be().to_ne_bytes()
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_le().to_ne_bytes()
+        }
+
         /// Return the memory representation of this integer as a byte array in
         /// little-endian byte order.
         ///
@@ -3600,11 +3999,21 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        #[cfg(not(stage0))]
+        pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
             self.to_le().to_ne_bytes()
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            unsafe { mem::transmute(self) }
+        }
+
         /// Return the memory representation of this integer as a byte array in
         /// native byte order.
         ///
@@ -3624,11 +4033,21 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// assert_eq!(bytes, [0x80, 0, 0, 0]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        #[cfg(not(stage0))]
+        pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
             unsafe { mem::transmute(self) }
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_be(Self::from_ne_bytes(bytes))
+        }
+
         /// Create an integer value from its representation as a byte array in
         /// big endian.
         ///
@@ -3641,11 +4060,21 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// assert_eq!(int, 0x12_34_56_78);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             Self::from_be(Self::from_ne_bytes(bytes))
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_le(Self::from_ne_bytes(bytes))
+        }
+
         /// Create an integer value from its representation as a byte array in
         /// little endian.
         ///
@@ -3658,11 +4087,21 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// assert_eq!(int, 0x78_56_34_12);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             Self::from_le(Self::from_ne_bytes(bytes))
         }
 
+        /// no docs here
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        #[cfg(stage0)]
+        pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            unsafe { mem::transmute(bytes) }
+        }
+
         /// Create an integer value from its memory representation as a byte
         /// array in native endianness.
         ///
@@ -3682,8 +4121,10 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// assert_eq!(int, i32::min_value());
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[rustc_const_unstable(feature = "const_int_conversion")]
         #[inline]
-        pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        #[cfg(not(stage0))]
+        pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             unsafe { mem::transmute(bytes) }
         }
     }
@@ -4323,7 +4764,7 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
 
 /// The error type returned when a checked integral type conversion fails.
 #[unstable(feature = "try_from", issue = "33417")]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub struct TryFromIntError(());
 
 impl TryFromIntError {
index 3366c4a3e661c4a825bb0af9b03969ba907ab58c..62adaea168a3f97854f935c704331dad8c80701f 100644 (file)
 // The library infrastructure for slices is fairly messy. There's
 // a lot of stuff defined here. Let's keep it clean.
 //
-// Since slices don't support inherent methods; all operations
-// on them are defined on traits, which are then re-exported from
-// the prelude for convenience. So there are a lot of traits here.
-//
 // The layout of this file is thus:
 //
-// * Slice-specific 'extension' traits and their implementations. This
-//   is where most of the slice API resides.
+// * Inherent methods. This is where most of the slice API resides.
 // * Implementations of a few common traits with important slice ops.
 // * Definitions of a bunch of iterators.
 // * Free functions.
@@ -3884,13 +3879,16 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
     Repr { raw: FatPtr { data, len } }.rust
 }
 
-/// Performs the same functionality as `from_raw_parts`, except that a mutable
-/// slice is returned.
+/// Performs the same functionality as [`from_raw_parts`], except that a
+/// mutable slice is returned.
 ///
-/// This function is unsafe for the same reasons as `from_raw_parts`, as well
+/// This function is unsafe for the same reasons as [`from_raw_parts`], as well
 /// as not being able to provide a non-aliasing guarantee of the returned
 /// mutable slice. `data` must be non-null and aligned even for zero-length
-/// slices as with `from_raw_parts`.
+/// slices as with [`from_raw_parts`]. See the documentation of
+/// [`from_raw_parts`] for more details.
+///
+/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
index 64bdf4d9f486ad84d1d6d6dbdd72ad1ddaa3fe9f..2c941c28d4b80e938583864558c399e7a10f7ab2 100644 (file)
@@ -59,7 +59,7 @@
 ///
 ///     fn from_str(s: &str) -> Result<Self, Self::Err> {
 ///         let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' )
-///                                  .split(",")
+///                                  .split(',')
 ///                                  .collect();
 ///
 ///         let x_fromstr = coords[0].parse::<i32>()?;
@@ -3563,6 +3563,76 @@ pub fn trim(&self) -> &str {
         self.trim_matches(|c: char| c.is_whitespace())
     }
 
+    /// Returns a string slice with leading whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. `start` in this context means the first
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be left side; and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the right side.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!("Hello\tworld\t", s.trim_start());
+    /// ```
+    ///
+    /// Directionality:
+    ///
+    /// ```
+    /// let s = "  English  ";
+    /// assert!(Some('E') == s.trim_start().chars().next());
+    ///
+    /// let s = "  ×¢×‘רית  ";
+    /// assert!(Some('×¢') == s.trim_start().chars().next());
+    /// ```
+    #[stable(feature = "trim_direction", since = "1.30.0")]
+    pub fn trim_start(&self) -> &str {
+        self.trim_start_matches(|c: char| c.is_whitespace())
+    }
+
+    /// Returns a string slice with trailing whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. `end` in this context means the last
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be right side; and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the left side.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(" Hello\tworld", s.trim_end());
+    /// ```
+    ///
+    /// Directionality:
+    ///
+    /// ```
+    /// let s = "  English  ";
+    /// assert!(Some('h') == s.trim_end().chars().rev().next());
+    ///
+    /// let s = "  ×¢×‘רית  ";
+    /// assert!(Some('ת') == s.trim_end().chars().rev().next());
+    /// ```
+    #[stable(feature = "trim_direction", since = "1.30.0")]
+    pub fn trim_end(&self) -> &str {
+        self.trim_end_matches(|c: char| c.is_whitespace())
+    }
+
     /// Returns a string slice with leading whitespace removed.
     ///
     /// 'Whitespace' is defined according to the terms of the Unicode Derived
@@ -3595,8 +3665,9 @@ pub fn trim(&self) -> &str {
     /// assert!(Some('×¢') == s.trim_left().chars().next());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(reason = "superseded by `trim_start`", since = "1.33.0")]
     pub fn trim_left(&self) -> &str {
-        self.trim_left_matches(|c: char| c.is_whitespace())
+        self.trim_start()
     }
 
     /// Returns a string slice with trailing whitespace removed.
@@ -3631,8 +3702,9 @@ pub fn trim_left(&self) -> &str {
     /// assert!(Some('ת') == s.trim_right().chars().rev().next());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(reason = "superseded by `trim_end`", since = "1.33.0")]
     pub fn trim_right(&self) -> &str {
-        self.trim_right_matches(|c: char| c.is_whitespace())
+        self.trim_end()
     }
 
     /// Returns a string slice with all prefixes and suffixes that match a
@@ -3697,14 +3769,14 @@ pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
     /// Basic usage:
     ///
     /// ```
-    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
-    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
+    /// assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
+    /// assert_eq!("123foo1bar123".trim_start_matches(char::is_numeric), "foo1bar123");
     ///
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+    /// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12");
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
+    #[stable(feature = "trim_direction", since = "1.30.0")]
+    pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
         let mut i = self.len();
         let mut matcher = pat.into_searcher(self);
         if let Some((a, _)) = matcher.next_reject() {
@@ -3734,20 +3806,20 @@ pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
     /// Simple patterns:
     ///
     /// ```
-    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
-    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
+    /// assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
+    /// assert_eq!("123foo1bar123".trim_end_matches(char::is_numeric), "123foo1bar");
     ///
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// assert_eq!("12foo1bar12".trim_end_matches(x), "12foo1bar");
     /// ```
     ///
     /// A more complex pattern, using a closure:
     ///
     /// ```
-    /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
+    /// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo");
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+    #[stable(feature = "trim_direction", since = "1.30.0")]
+    pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
         where P::Searcher: ReverseSearcher<'a>
     {
         let mut j = 0;
@@ -3761,6 +3833,78 @@ pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
         }
     }
 
+    /// Returns a string slice with all prefixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(reason = "superseded by `trim_start_matches`", since = "1.33.0")]
+    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
+        self.trim_start_matches(pat)
+    }
+
+    /// Returns a string slice with all suffixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(reason = "superseded by `trim_end_matches`", since = "1.33.0")]
+    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        self.trim_end_matches(pat)
+    }
+
     /// Parses this string slice into another type.
     ///
     /// Because `parse` is so general, it can cause problems with type
index a1928657dabc480413d361950f8234d60ab8474b..ab619093d9d85b77969fc2ee9b0999cb8e5e56e5 100644 (file)
@@ -18,8 +18,8 @@
 use core::num::flt2dec::strategy::grisu::format_shortest_opt;
 use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
 
-use rand::{self, Rand, XorShiftRng};
-use rand::distributions::{IndependentSample, Range};
+use rand::{FromEntropy, XorShiftRng};
+use rand::distributions::{Distribution, Uniform};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -71,10 +71,10 @@ fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V
 pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
         where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
               G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
-    let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
-    let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000);
+    let mut rng = XorShiftRng::from_entropy();
+    let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000);
     iterate("f32_random_equivalence_test", k, n, f, g, |_| {
-        let x = f32::from_bits(f32_range.ind_sample(&mut rng));
+        let x = f32::from_bits(f32_range.sample(&mut rng));
         decode_finite(x)
     });
 }
@@ -82,10 +82,10 @@ pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
 pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
         where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
               G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
-    let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
-    let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
+    let mut rng = XorShiftRng::from_entropy();
+    let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
     iterate("f64_random_equivalence_test", k, n, f, g, |_| {
-        let x = f64::from_bits(f64_range.ind_sample(&mut rng));
+        let x = f64::from_bits(f64_range.sample(&mut rng));
         decode_finite(x)
     });
 }
index b087ec81f59c67004ef049027eb2aafad792368a..012dc9bf5e0b93751c40ea628adf19adcce71459 100644 (file)
@@ -802,11 +802,11 @@ fn test_rotate_right() {
 fn sort_unstable() {
     use core::cmp::Ordering::{Equal, Greater, Less};
     use core::slice::heapsort;
-    use rand::{Rng, XorShiftRng};
+    use rand::{FromEntropy, Rng, XorShiftRng};
 
     let mut v = [0; 600];
     let mut tmp = [0; 600];
-    let mut rng = XorShiftRng::new_unseeded();
+    let mut rng = XorShiftRng::from_entropy();
 
     for len in (2..25).chain(500..510) {
         let v = &mut v[0..len];
index 015be2dea2157205d6fd6b1eb3426bd42eace040..d6298a38a2601fbd3cee9699c40ec983e7f0af84 100644 (file)
@@ -54,7 +54,7 @@
 //! [win64]: http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx
 //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
index 0b08e54c6739a0684c41cf9478e87b35027f8e82..c2074db00385b8367c823eb44d3ba4365d65b1c0 100644 (file)
@@ -11,7 +11,7 @@
 //! Unwinding implementation of top of native Win64 SEH,
 //! however the unwind handler data (aka LSDA) uses GCC-compatible encoding.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
index 5f1dda36a889ea0aff118b969d5da63d37f9d3ef..0a1c9b3adf183b67143f02a7f335dc16446d5591 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![allow(dead_code)]
 #![cfg(windows)]
 
index fc5d4a9c92331bb606e535b23a9f5b55eca2168c..6c3b52196a3a2bb03c459e4f96b8a821fda5864d 100644 (file)
@@ -29,7 +29,7 @@ serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 backtrace = "0.3.3"
-parking_lot = "0.5.5"
+parking_lot = "0.6"
 byteorder = { version = "1.1", features = ["i128"]}
 chalk-engine = { version = "0.7.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
index 98cfa094c169a2c250311df96f35919246c1096b..1b97480920321d6fafad010285a19ff258e95394 100644 (file)
@@ -488,8 +488,9 @@ fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr,
                     // expression to target
                     let guard_start = self.add_dummy_node(&[pat_exit]);
                     // Visit the guard expression
-                    let guard_exit = self.expr(&guard, guard_start);
-
+                    let guard_exit = match guard {
+                        hir::Guard::If(ref e) => self.expr(e, guard_start),
+                    };
                     // #47295: We used to have very special case code
                     // here for when a pair of arms are both formed
                     // solely from constants, and if so, not add these
index 90081d5b85ef9ec7186ee1931cb16f398a482140..dfe0a395ca140678fac359aa24fc6236e0ca3d1e 100644 (file)
@@ -75,7 +75,7 @@
     CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
 };
 use ty::{TyCtxt, FnSig, Instance, InstanceDef,
-         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty, self};
+         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
 use ty::subst::Substs;
 
 // erase!() just makes tokens go away. It's used to specify which macro argument
@@ -632,7 +632,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // queries). Making them anonymous avoids hashing the result, which
     // may save a bit of time.
     [anon] EraseRegionsTy { ty: Ty<'tcx> },
-    [anon] ConstToAllocation { val: &'tcx ty::Const<'tcx> },
 
     [input] Freevars(DefId),
     [input] MaybeUnusedTraitImport(DefId),
index a285399657177a3ade729dc2421f45363c82b390..4df0fc443a27c6ed2fcc246cc607fad247f12adb 100644 (file)
@@ -878,7 +878,7 @@ pub struct WorkProduct {
     pub saved_files: Vec<(WorkProductFileKind, String)>,
 }
 
-#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, PartialEq)]
 pub enum WorkProductFileKind {
     Object,
     Bytecode,
index d853d3d9a7fb4975601bc311b1c538455d131c4d..8129cc18d46c2e08952b0753b8fcd691a90526b1 100644 (file)
@@ -1102,7 +1102,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
     walk_list!(visitor, visit_pat, &arm.pats);
-    walk_list!(visitor, visit_expr, &arm.guard);
+    if let Some(ref g) = arm.guard {
+        match g {
+            Guard::If(ref e) => visitor.visit_expr(e),
+        }
+    }
     visitor.visit_expr(&arm.body);
     walk_list!(visitor, visit_attribute, &arm.attrs);
 }
index cb05f7b44c3b96b783b3ed13fc2495324f421c08..34b3eb0a8c8bf64d1fd595377f2f028d89dcaf3f 100644 (file)
@@ -50,6 +50,7 @@
 use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
                     ELIDED_LIFETIMES_IN_PATHS};
 use middle::cstore::CrateStore;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::small_vec::OneVector;
 use rustc_data_structures::thin_vec::ThinVec;
@@ -57,7 +58,7 @@
 use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, NodeMap};
 
-use std::collections::{BTreeMap, HashSet};
+use std::collections::BTreeMap;
 use std::fmt::Debug;
 use std::iter;
 use std::mem;
@@ -1053,7 +1054,10 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
         hir::Arm {
             attrs: self.lower_attrs(&arm.attrs),
             pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
-            guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
+            guard: match arm.guard {
+                Some(Guard::If(ref x)) => Some(hir::Guard::If(P(self.lower_expr(x)))),
+                _ => None,
+            },
             body: P(self.lower_expr(&arm.body)),
         }
     }
@@ -1342,7 +1346,7 @@ struct ImplTraitLifetimeCollector<'r, 'a: 'r> {
             exist_ty_id: NodeId,
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
-            already_defined_lifetimes: HashSet<hir::LifetimeName>,
+            already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
             output_lifetimes: Vec<hir::GenericArg>,
             output_lifetime_params: Vec<hir::GenericParam>,
         }
@@ -1476,7 +1480,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
             exist_ty_id,
             collect_elided_lifetimes: true,
             currently_bound_lifetimes: Vec::new(),
-            already_defined_lifetimes: HashSet::new(),
+            already_defined_lifetimes: FxHashSet::default(),
             output_lifetimes: Vec::new(),
             output_lifetime_params: Vec::new(),
         };
index 7ac334d84a9bfdd2401f6f5734a044f4d4f7aad0..1b3103578737190b2c32a3886806940a6022af92 100644 (file)
@@ -1204,10 +1204,15 @@ pub fn is_local(&self) -> bool {
 pub struct Arm {
     pub attrs: HirVec<Attribute>,
     pub pats: HirVec<P<Pat>>,
-    pub guard: Option<P<Expr>>,
+    pub guard: Option<Guard>,
     pub body: P<Expr>,
 }
 
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum Guard {
+    If(P<Expr>),
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Field {
     pub id: NodeId,
index 8b221f3463ed334d27a2cc39fa7e1b714dc10b18..55357095fb7596f10b6281af5f268493dab500bd 100644 (file)
@@ -1949,10 +1949,14 @@ fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
             self.print_pat(&p)?;
         }
         self.s.space()?;
-        if let Some(ref e) = arm.guard {
-            self.word_space("if")?;
-            self.print_expr(&e)?;
-            self.s.space()?;
+        if let Some(ref g) = arm.guard {
+            match g {
+                hir::Guard::If(e) => {
+                    self.word_space("if")?;
+                    self.print_expr(&e)?;
+                    self.s.space()?;
+                }
+            }
         }
         self.word_space("=>")?;
 
index 371f631737c9871001536c5f4e964f2f0a012736..1acc58948f413b71ecf72bf47a71884bb8b3a48e 100644 (file)
@@ -15,7 +15,6 @@
 use ich::{self, CachingSourceMapView, Fingerprint};
 use middle::cstore::CrateStore;
 use ty::{TyCtxt, fast_reject};
-use mir::interpret::AllocId;
 use session::Session;
 
 use std::cmp::Ord;
@@ -60,8 +59,6 @@ pub struct StableHashingContext<'a> {
     // CachingSourceMapView, so we initialize it lazily.
     raw_source_map: &'a SourceMap,
     caching_source_map: Option<CachingSourceMapView<'a>>,
-
-    pub(super) alloc_id_recursion_tracker: FxHashSet<AllocId>,
 }
 
 #[derive(PartialEq, Eq, Clone, Copy)]
@@ -105,7 +102,6 @@ pub fn new(sess: &'a Session,
             hash_spans: hash_spans_initial,
             hash_bodies: true,
             node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
-            alloc_id_recursion_tracker: Default::default(),
         }
     }
 
index 2ac195dca82c42278dc7b40a31e3de8196a9dbbe..3f1899bc54fb4c2e1e34b1c548cb51fcc3726e6b 100644 (file)
@@ -493,6 +493,10 @@ fn hash_stable<W: StableHasherResult>(&self,
     body
 });
 
+impl_stable_hash_for!(enum hir::Guard {
+    If(expr),
+});
+
 impl_stable_hash_for!(struct hir::Field {
     id -> _,
     ident,
index 1c9387d02d5a34ffbc3de811e20e9e365b7c8cca..f11e4487964624d74ce17abd7aa57a3d0b0846e9 100644 (file)
@@ -65,6 +65,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
         match *self {
             mir::UnsafetyViolationKind::General => {}
+            mir::UnsafetyViolationKind::MinConstFn => {}
             mir::UnsafetyViolationKind::ExternStatic(lint_node_id) |
             mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
                 lint_node_id.hash_stable(hcx, hasher);
index ac5fdb2fe27971f980261a54b5d3cc11b8205379..a15411c7d83698c115b8bb5dc8f8a5531e22a0ae 100644 (file)
@@ -130,7 +130,7 @@ fn to_stable_hash_key(&self,
     level,
     feature,
     rustc_depr,
-    rustc_const_unstable
+    const_stability
 });
 
 impl<'a> HashStable<StableHashingContext<'a>>
@@ -161,7 +161,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
-impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
 
 
 impl_stable_hash_for!(enum ::syntax::attr::IntType {
index c598f99a2b54dfed9785ef4b1b741373c9dc0c56..68320dfddefbc04934d7a24581d4eb2e4b419f80 100644 (file)
@@ -344,13 +344,13 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl_stable_hash_for!(struct ty::VariantDef {
-    did,
-    name,
-    discr,
-    fields,
-    ctor_kind
-});
+impl<'a> HashStable<StableHashingContext<'a>> for ty::VariantFlags {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        std_hash::Hash::hash(self, hasher);
+    }
+}
 
 impl_stable_hash_for!(enum ty::VariantDiscr {
     Explicit(def_id),
@@ -412,7 +412,7 @@ fn hash_stable<W: StableHasherResult>(
         ty::tls::with_opt(|tcx| {
             trace!("hashing {:?}", *self);
             let tcx = tcx.expect("can't hash AllocIds during hir lowering");
-            let alloc_kind = tcx.alloc_map.lock().get(*self).expect("no value for AllocId");
+            let alloc_kind = tcx.alloc_map.lock().get(*self);
             alloc_kind.hash_stable(hcx, hasher);
         });
     }
@@ -512,6 +512,7 @@ fn hash_stable<W: StableHasherResult>(&self,
         mem::discriminant(&self).hash_stable(hcx, hasher);
 
         match *self {
+            FunctionArgCountMismatch |
             DanglingPointerDeref |
             DoubleFree |
             InvalidMemoryAccess |
@@ -558,7 +559,11 @@ fn hash_stable<W: StableHasherResult>(&self,
             },
             ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
             MachineError(ref err) => err.hash_stable(hcx, hasher),
-            FunctionPointerTyMismatch(a, b) => {
+            FunctionAbiMismatch(a, b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher)
+            },
+            FunctionArgMismatch(a, b) => {
                 a.hash_stable(hcx, hasher);
                 b.hash_stable(hcx, hasher)
             },
index cf0d0ceadca910b68e2c029698f1ed86af7b819c..ac6a7f0c2baa8ff7d2ae1e968b35295670004f1e 100644 (file)
@@ -68,6 +68,7 @@
 use traits::{ObligationCause, ObligationCauseCode};
 use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TyKind};
 use ty::error::TypeError;
+use session::config::BorrowckMode;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
@@ -303,40 +304,16 @@ pub fn report_region_errors(
     ) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
-        if will_later_be_reported_by_nll &&
-            // FIXME: `use_mir_borrowck` seems wrong here...
-            self.tcx.use_mir_borrowck() &&
-            // ... this is a band-aid; may be better to explicitly
-            // match on every borrowck_mode variant to guide decision
-            // here.
-            !self.tcx.migrate_borrowck() {
-
-            // With `#![feature(nll)]`, we want to present a nice user
-            // experience, so don't even mention the errors from the
-            // AST checker.
-            if self.tcx.features().nll {
-                return;
+        // If the errors will later be reported by NLL, choose wether to display them or not based
+        // on the borrowck mode
+        if will_later_be_reported_by_nll {
+            match self.tcx.borrowck_mode() {
+                // If we're on AST or Migrate mode, report AST region errors
+                BorrowckMode::Ast | BorrowckMode::Migrate => {},
+                // If we're on MIR or Compare mode, don't report AST region errors as they should
+                // be reported by NLL
+                BorrowckMode::Compare | BorrowckMode::Mir => return,
             }
-
-            // But with nll, it's nice to have some note for later.
-            for error in errors {
-                match *error {
-                    RegionResolutionError::ConcreteFailure(ref origin, ..)
-                    | RegionResolutionError::GenericBoundFailure(ref origin, ..) => {
-                        self.tcx
-                            .sess
-                            .span_warn(origin.span(), "not reporting region error due to nll");
-                    }
-
-                    RegionResolutionError::SubSupConflict(ref rvo, ..) => {
-                        self.tcx
-                            .sess
-                            .span_warn(rvo.span(), "not reporting region error due to nll");
-                    }
-                }
-            }
-
-            return;
         }
 
         // try to pre-process the errors, which will group some of them
index a3c9d14eef2954f1530ed8f1cf997fe63f668417..a379438275d897f5b2e7079ed3ca31027be9c220 100644 (file)
@@ -1116,7 +1116,11 @@ pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
         self.resolve_type_vars_if_possible(t).to_string()
     }
 
-    pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
+    // We have this force-inlined variant of shallow_resolve() for the one
+    // callsite that is extremely hot. All other callsites use the normal
+    // variant.
+    #[inline(always)]
+    pub fn inlined_shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         match typ.sty {
             ty::Infer(ty::TyVar(v)) => {
                 // Not entirely obvious: if `typ` is a type variable,
@@ -1157,6 +1161,10 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
+    pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
+        self.inlined_shallow_resolve(typ)
+    }
+
     pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
         where T: TypeFoldable<'tcx>
     {
index d014f319564fef11c344060164f8eb8dd0665a5c..d79281666d63914e7f137927c04100b96ec02368 100644 (file)
@@ -42,7 +42,8 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![cfg_attr(windows, feature(libc))]
index 5cc862a58d35a3496875452086b834902c33409b..b823545aa9114e75243849931dbb670c6f224797 100644 (file)
@@ -67,9 +67,10 @@ pub struct LintStore {
     /// Lints indexed by name.
     by_name: FxHashMap<String, TargetLint>,
 
-    /// Map of registered lint groups to what lints they expand to. The bool
-    /// is true if the lint group was added by a plugin.
-    lint_groups: FxHashMap<&'static str, (Vec<LintId>, bool)>,
+    /// Map of registered lint groups to what lints they expand to. The first
+    /// bool is true if the lint group was added by a plugin. The optional string
+    /// is used to store the new names of deprecated lint group names.
+    lint_groups: FxHashMap<&'static str, (Vec<LintId>, bool, Option<&'static str>)>,
 
     /// Extra info for future incompatibility lints, describing the
     /// issue or RFC that caused the incompatibility.
@@ -138,7 +139,7 @@ pub enum CheckLintNameResult<'a> {
     /// compiled with the tool and therefore the lint was never
     /// added to the `LintStore`. Otherwise the `LintId` will be
     /// returned as if it where a rustc lint.
-    Tool(Option<&'a [LintId]>),
+    Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>),
 }
 
 impl LintStore {
@@ -221,7 +222,7 @@ pub fn register_future_incompatible(&mut self,
             let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id)
                              .collect::<Vec<_>>();
             if !lints.is_empty() {
-                self.register_group(sess, false, edition.lint_name(), lints)
+                self.register_group(sess, false, edition.lint_name(), None, lints)
             }
         }
 
@@ -231,19 +232,35 @@ pub fn register_future_incompatible(&mut self,
             self.future_incompatible.insert(lint.id, lint);
         }
 
-        self.register_group(sess, false, "future_incompatible", future_incompatible);
-
-
+        self.register_group(
+            sess,
+            false,
+            "future_incompatible",
+            None,
+            future_incompatible,
+        );
     }
 
     pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
         self.future_incompatible.get(&id)
     }
 
-    pub fn register_group(&mut self, sess: Option<&Session>,
-                          from_plugin: bool, name: &'static str,
-                          to: Vec<LintId>) {
-        let new = self.lint_groups.insert(name, (to, from_plugin)).is_none();
+    pub fn register_group(
+        &mut self,
+        sess: Option<&Session>,
+        from_plugin: bool,
+        name: &'static str,
+        deprecated_name: Option<&'static str>,
+        to: Vec<LintId>,
+    ) {
+        let new = self
+            .lint_groups
+            .insert(name, (to, from_plugin, None))
+            .is_none();
+        if let Some(deprecated) = deprecated_name {
+            self.lint_groups
+                .insert(deprecated, (vec![], from_plugin, Some(name)));
+        }
 
         if !new {
             let msg = format!("duplicate specification of lint group {}", name);
@@ -302,7 +319,15 @@ pub fn check_lint_name_cmdline(&self,
             CheckLintNameResult::NoLint => {
                 Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
             }
-            CheckLintNameResult::Tool(_) => unreachable!(),
+            CheckLintNameResult::Tool(result) => match result {
+                Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
+                    "lint name `{}` is deprecated \
+                     and does not have an effect anymore. \
+                     Use: {}",
+                    lint_name, new_name
+                ))),
+                _ => None,
+            },
         };
 
         if let Some(mut db) = db {
@@ -336,13 +361,14 @@ pub fn check_lint_name(
         } else {
             lint_name.to_string()
         };
+        // If the lint was scoped with `tool::` check if the tool lint exists
         if let Some(_) = tool_name {
             match self.by_name.get(&complete_name) {
                 None => match self.lint_groups.get(&*complete_name) {
-                    None => return CheckLintNameResult::Tool(None),
-                    Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)),
+                    None => return CheckLintNameResult::Tool(Err((None, String::new()))),
+                    Some(ids) => return CheckLintNameResult::Tool(Ok(&ids.0)),
                 },
-                Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))),
+                Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
                 // If the lint was registered as removed or renamed by the lint tool, we don't need
                 // to treat tool_lints and rustc lints different and can use the code below.
                 _ => {}
@@ -350,20 +376,64 @@ pub fn check_lint_name(
         }
         match self.by_name.get(&complete_name) {
             Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
-                format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
+                format!(
+                    "lint `{}` has been renamed to `{}`",
+                    complete_name, new_name
+                ),
                 Some(new_name.to_owned()),
             ),
             Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
-                format!("lint `{}` has been removed: `{}`", lint_name, reason),
+                format!("lint `{}` has been removed: `{}`", complete_name, reason),
                 None,
             ),
             None => match self.lint_groups.get(&*complete_name) {
-                None => CheckLintNameResult::NoLint,
-                Some(ids) => CheckLintNameResult::Ok(&ids.0),
+                // If neither the lint, nor the lint group exists check if there is a `clippy::`
+                // variant of this lint
+                None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"),
+                Some(ids) => {
+                    // Check if the lint group name is deprecated
+                    if let Some(new_name) = ids.2 {
+                        let lint_ids = self.lint_groups.get(new_name).unwrap();
+                        return CheckLintNameResult::Tool(Err((
+                            Some(&lint_ids.0),
+                            new_name.to_string(),
+                        )));
+                    }
+                    CheckLintNameResult::Ok(&ids.0)
+                }
             },
             Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
         }
     }
+
+    fn check_tool_name_for_backwards_compat(
+        &self,
+        lint_name: &str,
+        tool_name: &str,
+    ) -> CheckLintNameResult {
+        let complete_name = format!("{}::{}", tool_name, lint_name);
+        match self.by_name.get(&complete_name) {
+            None => match self.lint_groups.get(&*complete_name) {
+                // Now we are sure, that this lint exists nowhere
+                None => CheckLintNameResult::NoLint,
+                Some(ids) => {
+                    // Reaching this would be weird, but lets cover this case anyway
+                    if let Some(new_name) = ids.2 {
+                        let lint_ids = self.lint_groups.get(new_name).unwrap();
+                        return CheckLintNameResult::Tool(Err((
+                            Some(&lint_ids.0),
+                            new_name.to_string(),
+                        )));
+                    }
+                    CheckLintNameResult::Tool(Err((Some(&ids.0), complete_name)))
+                }
+            },
+            Some(&Id(ref id)) => {
+                CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
+            }
+            _ => CheckLintNameResult::NoLint,
+        }
+    }
 }
 
 /// Context for lint checking after type checking.
index 5b9ddabf21c1b36fa16681c5ba1eb72c73046338..336ebe79d33abd7276eb6d20f6f427be9f82b04b 100644 (file)
@@ -231,12 +231,13 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     let gate_feature = !self.sess.features_untracked().tool_lints;
                     let known_tool = attr::is_known_lint_tool(lint_tool);
                     if gate_feature {
-                        feature_gate::emit_feature_err(&sess.parse_sess,
-                                                       "tool_lints",
-                                                       word.span,
-                                                       feature_gate::GateIssue::Language,
-                                                       &format!("scoped lint `{}` is experimental",
-                                                                word.ident));
+                        feature_gate::emit_feature_err(
+                            &sess.parse_sess,
+                            "tool_lints",
+                            word.span,
+                            feature_gate::GateIssue::Language,
+                            &format!("scoped lint `{}` is experimental", word.ident),
+                        );
                     }
                     if !known_tool {
                         span_err!(
@@ -249,7 +250,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     }
 
                     if gate_feature || !known_tool {
-                        continue
+                        continue;
                     }
 
                     Some(lint_tool.as_str())
@@ -266,17 +267,52 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     }
 
                     CheckLintNameResult::Tool(result) => {
-                        if let Some(ids) = result {
-                            let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
-                            let src = LintSource::Node(Symbol::intern(complete_name), li.span);
-                            for id in ids {
-                                specs.insert(*id, (level, src));
+                        match result {
+                            Ok(ids) => {
+                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+                                let src = LintSource::Node(Symbol::intern(complete_name), li.span);
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((Some(ids), new_lint_name)) => {
+                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                                let (lvl, src) =
+                                    self.sets
+                                        .get_lint_level(lint, self.cur, Some(&specs), &sess);
+                                let msg = format!(
+                                    "lint name `{}` is deprecated \
+                                     and may not have an effect in the future. \
+                                     Also `cfg_attr(cargo-clippy)` won't be necessary anymore",
+                                    name
+                                );
+                                let mut err = lint::struct_lint_level(
+                                    self.sess,
+                                    lint,
+                                    lvl,
+                                    src,
+                                    Some(li.span.into()),
+                                    &msg,
+                                );
+                                err.span_suggestion_with_applicability(
+                                    li.span,
+                                    "change it to",
+                                    new_lint_name.to_string(),
+                                    Applicability::MachineApplicable,
+                                ).emit();
+
+                                let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span);
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((None, _)) => {
+                                // If Tool(Err(None, _)) is returned, then either the lint does not
+                                // exist in the tool or the code was not compiled with the tool and
+                                // therefore the lint was never added to the `LintStore`. To detect
+                                // this is the responsibility of the lint tool.
                             }
                         }
-                        // If Tool(None) is returned, then either the lint does not exist in the
-                        // tool or the code was not compiled with the tool and therefore the lint
-                        // was never added to the `LintStore`. To detect this is the responsibility
-                        // of the lint tool.
                     }
 
                     _ if !self.warn_about_weird_lints => {}
index 90692bcd30103303fa1df4cecade47c976500d7d..356992b22146d67b02d63c409b07787c93b46774 100644 (file)
@@ -792,7 +792,9 @@ fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode
         }
 
         if let Some(ref guard) = arm.guard {
-            self.consume_expr(&guard);
+            match guard {
+                hir::Guard::If(ref e) => self.consume_expr(e),
+            }
         }
 
         self.consume_expr(&arm.body);
index 2697d62cf467aa0d4cf857cc018db30fb5e0c6db..c34a0a654e6a9f7c1964b39b3fa0c4e411391010 100644 (file)
@@ -1030,7 +1030,12 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
                 let body_succ =
                     self.propagate_through_expr(&arm.body, succ);
                 let guard_succ =
-                    self.propagate_through_opt_expr(arm.guard.as_ref().map(|e| &**e), body_succ);
+                    self.propagate_through_opt_expr(
+                        arm.guard.as_ref().map(|g|
+                            match g {
+                                hir::Guard::If(e) => &**e,
+                            }),
+                        body_succ);
                 // only consider the first pattern; any later patterns must have
                 // the same bindings, and we also consider the first pattern to be
                 // the "authoritative" set of ids
index 20ee5f0b04635fbc8dae8d5ca02c75da6f584da6..e281cbf94889394198e3e8e5d982b70b43bfab81 100644 (file)
@@ -885,8 +885,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
 fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) {
     visitor.terminating_scopes.insert(arm.body.hir_id.local_id);
 
-    if let Some(ref expr) = arm.guard {
-        visitor.terminating_scopes.insert(expr.hir_id.local_id);
+    if let Some(ref g) = arm.guard {
+        match g {
+            hir::Guard::If(ref expr) => visitor.terminating_scopes.insert(expr.hir_id.local_id),
+        };
     }
 
     intravisit::walk_arm(visitor, arm);
index 85195b0f62e7cf58aeaaaaf3e8b55e4880c7f38f..f237c5b397bd5263722c7ab089f0760ac12a605f 100644 (file)
@@ -440,7 +440,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
                     },
                     feature: Symbol::intern("rustc_private"),
                     rustc_depr: None,
-                    rustc_const_unstable: None,
+                    const_stability: None,
                 });
                 annotator.parent_stab = Some(stability);
             }
index bfc27e3b5806c95f31d34e28033065f724cedd5f..cbf6722c0fd375dbcbfbac29a7dd1862098ef168 100644 (file)
@@ -13,6 +13,7 @@
 use session::config;
 use middle::lang_items;
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_target::spec::PanicStrategy;
 use syntax::ast;
 use syntax::symbol::Symbol;
@@ -23,8 +24,6 @@
 use hir;
 use ty::TyCtxt;
 
-use std::collections::HashSet;
-
 macro_rules! weak_lang_items {
     ($($name:ident, $item:ident, $sym:ident;)*) => (
 
@@ -101,7 +100,7 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return
     }
 
-    let mut missing = HashSet::new();
+    let mut missing = FxHashSet::default();
     for &cnum in tcx.crates().iter() {
         for &item in tcx.missing_lang_items(cnum).iter() {
             missing.insert(item);
index 41ba526b73fefdafd3d707eac79698e10da0ddd9..d1f050fcd424d23201142bd3453440a245c4b931 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::sync::{RwLock, ReadGuard};
+use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use ich::StableHashingContext;
@@ -55,7 +55,10 @@ pub fn invalidate(&self) {
         *self.predecessors.borrow_mut() = None;
     }
 
-    pub fn predecessors(&self, mir: &Mir) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(
+        &self,
+        mir: &Mir
+    ) -> MappedReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         if self.predecessors.borrow().is_none() {
             *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
         }
index ab38f8fa72135dbb12054024c23a65fee2e8ae5b..84d55c84ce154b8e23dd643c5f571ca3e53c55d3 100644 (file)
 use std::{fmt, env};
 
 use mir;
-use ty::{FnSig, Ty, layout};
+use ty::{Ty, layout};
 use ty::layout::{Size, Align};
 use rustc_data_structures::sync::Lrc;
+use rustc_target::spec::abi::Abi;
 
 use super::{
     Pointer, Lock, AccessKind
@@ -182,7 +183,10 @@ pub enum EvalErrorKind<'tcx, O> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant
     MachineError(String),
-    FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>),
+
+    FunctionAbiMismatch(Abi, Abi),
+    FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
+    FunctionArgCountMismatch,
     NoMirFor(String),
     UnterminatedCString(Pointer),
     DanglingPointerDeref,
@@ -290,8 +294,8 @@ pub fn description(&self) -> &str {
         use self::EvalErrorKind::*;
         match *self {
             MachineError(ref inner) => inner,
-            FunctionPointerTyMismatch(..) =>
-                "tried to call a function through a function pointer of a different type",
+            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionArgCountMismatch =>
+                "tried to call a function through a function pointer of incompatible type",
             InvalidMemoryAccess =>
                 "tried to access memory through an invalid pointer",
             DanglingPointerDeref =>
@@ -459,9 +463,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "type validation failed: {}", err)
             }
             NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
-            FunctionPointerTyMismatch(sig, got) =>
-                write!(f, "tried to call a function with sig {} through a \
-                       function pointer of type {}", sig, got),
+            FunctionAbiMismatch(caller_abi, callee_abi) =>
+                write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}",
+                    callee_abi, caller_abi),
+            FunctionArgMismatch(caller_ty, callee_ty) =>
+                write!(f, "tried to call a function with argument of type {:?} \
+                           passing data of type {:?}",
+                    callee_ty, caller_ty),
+            FunctionArgCountMismatch =>
+                write!(f, "tried to call a function with incorrect number of arguments"),
             BoundsCheck { ref len, ref index } =>
                 write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             ReallocatedWrongMemoryKind(ref old, ref new) =>
index 147f9ccad7c38fbd87544ac1f2aab37512b148e2..ccc5bba1ad61170e592665f3857073852191861e 100644 (file)
@@ -85,9 +85,14 @@ pub struct GlobalId<'tcx> {
 pub trait PointerArithmetic: layout::HasDataLayout {
     // These are not supposed to be overridden.
 
+    #[inline(always)]
+    fn pointer_size(self) -> Size {
+        self.data_layout().pointer_size
+    }
+
     //// Trunace the given value to the pointer size; also return whether there was an overflow
     fn truncate_to_ptr(self, val: u128) -> (u64, bool) {
-        let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits();
+        let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
         ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
     }
 
@@ -128,9 +133,14 @@ fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 {
 impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 
 
+/// Pointer is generic over the type that represents a reference to Allocations,
+/// thus making it possible for the most convenient representation to be used in
+/// each context.
+///
+/// Defaults to the index based and loosely coupled AllocId.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub struct Pointer {
-    pub alloc_id: AllocId,
+pub struct Pointer<Id=AllocId> {
+    pub alloc_id: Id,
     pub offset: Size,
 }
 
@@ -491,7 +501,9 @@ pub struct Allocation {
     /// Note that the bytes of a pointer represent the offset of the pointer
     pub bytes: Vec<u8>,
     /// Maps from byte addresses to allocations.
-    /// Only the first byte of a pointer is inserted into the map.
+    /// Only the first byte of a pointer is inserted into the map; i.e.,
+    /// every entry in this map applies to `pointer_size` consecutive bytes starting
+    /// at the given offset.
     pub relocations: Relocations,
     /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
     pub undef_mask: UndefMask,
@@ -536,16 +548,16 @@ pub fn undef(size: Size, align: Align) -> Self {
 impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct Relocations(SortedMap<Size, AllocId>);
+pub struct Relocations<Id=AllocId>(SortedMap<Size, Id>);
 
-impl Relocations {
-    pub fn new() -> Relocations {
+impl<Id> Relocations<Id> {
+    pub fn new() -> Self {
         Relocations(SortedMap::new())
     }
 
     // The caller must guarantee that the given relocations are already sorted
     // by address and contain no duplicates.
-    pub fn from_presorted(r: Vec<(Size, AllocId)>) -> Relocations {
+    pub fn from_presorted(r: Vec<(Size, Id)>) -> Self {
         Relocations(SortedMap::from_presorted_elements(r))
     }
 }
index d793bb1cc63ca7a9702d009b319afac180015a18..9982da483ce09968cd18a3b601312946d93125ec 100644 (file)
@@ -14,7 +14,7 @@
 use ty::subst::Substs;
 use hir::def_id::DefId;
 
-use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend};
+use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
 
 /// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
 /// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
@@ -58,6 +58,7 @@ pub fn try_to_ptr(&self) -> Option<Pointer> {
         self.try_to_scalar()?.to_ptr().ok()
     }
 
+    #[inline]
     pub fn new_slice(
         val: Scalar,
         len: u64,
@@ -69,12 +70,14 @@ pub fn new_slice(
         }.into())
     }
 
+    #[inline]
     pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
         ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into())
     }
 }
 
 impl<'tcx> Scalar {
+    #[inline]
     pub fn ptr_null(cx: impl HasDataLayout) -> Self {
         Scalar::Bits {
             bits: 0,
@@ -82,10 +85,12 @@ pub fn ptr_null(cx: impl HasDataLayout) -> Self {
         }
     }
 
+    #[inline]
     pub fn zst() -> Self {
         Scalar::Bits { bits: 0, size: 0 }
     }
 
+    #[inline]
     pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self {
@@ -100,6 +105,7 @@ pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tc
         }
     }
 
+    #[inline]
     pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self {
@@ -114,6 +120,7 @@ pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Sel
         }
     }
 
+    #[inline]
     pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
         let layout = cx.data_layout();
         match self {
@@ -128,6 +135,7 @@ pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self
         }
     }
 
+    #[inline]
     pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
         match self {
             Scalar::Bits { bits, size } =>  {
@@ -138,14 +146,53 @@ pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
         }
     }
 
+    #[inline]
+    pub fn is_null(self) -> bool {
+        match self {
+            Scalar::Bits { bits, .. } => bits == 0,
+            Scalar::Ptr(_) => false
+        }
+    }
+
+    #[inline]
     pub fn from_bool(b: bool) -> Self {
         Scalar::Bits { bits: b as u128, size: 1 }
     }
 
+    #[inline]
     pub fn from_char(c: char) -> Self {
         Scalar::Bits { bits: c as u128, size: 4 }
     }
 
+    #[inline]
+    pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
+        let i = i.into();
+        debug_assert_eq!(truncate(i, size), i,
+                    "Unsigned value {} does not fit in {} bits", i, size.bits());
+        Scalar::Bits { bits: i, size: size.bytes() as u8 }
+    }
+
+    #[inline]
+    pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
+        let i = i.into();
+        // `into` performed sign extension, we have to truncate
+        let truncated = truncate(i as u128, size);
+        debug_assert_eq!(sign_extend(truncated, size) as i128, i,
+                    "Signed value {} does not fit in {} bits", i, size.bits());
+        Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
+    }
+
+    #[inline]
+    pub fn from_f32(f: f32) -> Self {
+        Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
+    }
+
+    #[inline]
+    pub fn from_f64(f: f64) -> Self {
+        Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
+    }
+
+    #[inline]
     pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
         match self {
             Scalar::Bits { bits, size } => {
@@ -157,6 +204,7 @@ pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
         }
     }
 
+    #[inline]
     pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
         match self {
             Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
@@ -165,6 +213,7 @@ pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
         }
     }
 
+    #[inline]
     pub fn is_bits(self) -> bool {
         match self {
             Scalar::Bits { .. } => true,
@@ -172,6 +221,7 @@ pub fn is_bits(self) -> bool {
         }
     }
 
+    #[inline]
     pub fn is_ptr(self) -> bool {
         match self {
             Scalar::Ptr(_) => true,
@@ -209,6 +259,13 @@ pub fn to_u32(self) -> EvalResult<'static, u32> {
         Ok(b as u32)
     }
 
+    pub fn to_u64(self) -> EvalResult<'static, u64> {
+        let sz = Size::from_bits(64);
+        let b = self.to_bits(sz)?;
+        assert_eq!(b as u64 as u128, b);
+        Ok(b as u64)
+    }
+
     pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
         let b = self.to_bits(cx.data_layout().pointer_size)?;
         assert_eq!(b as u64 as u128, b);
@@ -231,12 +288,30 @@ pub fn to_i32(self) -> EvalResult<'static, i32> {
         Ok(b as i32)
     }
 
+    pub fn to_i64(self) -> EvalResult<'static, i64> {
+        let sz = Size::from_bits(64);
+        let b = self.to_bits(sz)?;
+        let b = sign_extend(b, sz) as i128;
+        assert_eq!(b as i64 as i128, b);
+        Ok(b as i64)
+    }
+
     pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
         let b = self.to_bits(cx.data_layout().pointer_size)?;
         let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
         assert_eq!(b as i64 as i128, b);
         Ok(b as i64)
     }
+
+    #[inline]
+    pub fn to_f32(self) -> EvalResult<'static, f32> {
+        Ok(f32::from_bits(self.to_u32()?))
+    }
+
+    #[inline]
+    pub fn to_f64(self) -> EvalResult<'static, f64> {
+        Ok(f64::from_bits(self.to_u64()?))
+    }
 }
 
 impl From<Pointer> for Scalar {
@@ -251,7 +326,7 @@ fn from(ptr: Pointer) -> Self {
 /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
 /// of a simple value or a pointer into another `Allocation`
 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum Scalar {
+pub enum Scalar<Id=AllocId> {
     /// The raw bytes of a simple value.
     Bits {
         /// The first `size` bytes are the value.
@@ -263,12 +338,12 @@ pub enum Scalar {
     /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
     /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
     /// relocation and its associated offset together as a `Pointer` here.
-    Ptr(Pointer),
+    Ptr(Pointer<Id>),
 }
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum ScalarMaybeUndef {
-    Scalar(Scalar),
+pub enum ScalarMaybeUndef<Id=AllocId> {
+    Scalar(Scalar<Id>),
     Undef,
 }
 
@@ -308,6 +383,16 @@ pub fn to_char(self) -> EvalResult<'tcx, char> {
         self.not_undef()?.to_char()
     }
 
+    #[inline(always)]
+    pub fn to_f32(self) -> EvalResult<'tcx, f32> {
+        self.not_undef()?.to_f32()
+    }
+
+    #[inline(always)]
+    pub fn to_f64(self) -> EvalResult<'tcx, f64> {
+        self.not_undef()?.to_f64()
+    }
+
     #[inline(always)]
     pub fn to_u8(self) -> EvalResult<'tcx, u8> {
         self.not_undef()?.to_u8()
@@ -318,6 +403,11 @@ pub fn to_u32(self) -> EvalResult<'tcx, u32> {
         self.not_undef()?.to_u32()
     }
 
+    #[inline(always)]
+    pub fn to_u64(self) -> EvalResult<'tcx, u64> {
+        self.not_undef()?.to_u64()
+    }
+
     #[inline(always)]
     pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
         self.not_undef()?.to_usize(cx)
@@ -333,6 +423,11 @@ pub fn to_i32(self) -> EvalResult<'tcx, i32> {
         self.not_undef()?.to_i32()
     }
 
+    #[inline(always)]
+    pub fn to_i64(self) -> EvalResult<'tcx, i64> {
+        self.not_undef()?.to_i64()
+    }
+
     #[inline(always)]
     pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
         self.not_undef()?.to_isize(cx)
index 0840f333c876b1ec6e95af8074a5bc8bf1e7889a..f66be6dc54d37e3c883d062c5cfd44a0aeb6e12f 100644 (file)
 use hir::def_id::DefId;
 use hir::{self, HirId, InlineAsm};
 use middle::region;
-use mir::interpret::{EvalErrorKind, Scalar, ScalarMaybeUndef, ConstValue};
+use mir::interpret::{ConstValue, EvalErrorKind, Scalar, ScalarMaybeUndef};
 use mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_data_structures::graph::dominators::{dominators, Dominators};
 use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use smallvec::SmallVec;
 use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::sync::ReadGuard;
+use rustc_data_structures::sync::MappedReadGuard;
 use rustc_serialize as serialize;
+use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Formatter, Write};
 use std::ops::{Index, IndexMut};
@@ -194,13 +194,42 @@ pub fn basic_blocks_and_local_decls_mut(
     }
 
     #[inline]
-    pub fn predecessors(&self) -> ReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
         self.cache.predecessors(self)
     }
 
     #[inline]
-    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<'_, Vec<BasicBlock>> {
-        ReadGuard::map(self.predecessors(), |p| &p[bb])
+    pub fn predecessors_for(&self, bb: BasicBlock) -> MappedReadGuard<'_, Vec<BasicBlock>> {
+        MappedReadGuard::map(self.predecessors(), |p| &p[bb])
+    }
+
+    #[inline]
+    pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
+        let if_zero_locations = if loc.statement_index == 0 {
+            let predecessor_blocks = self.predecessors_for(loc.block);
+            let num_predecessor_blocks = predecessor_blocks.len();
+            Some(
+                (0..num_predecessor_blocks)
+                    .map(move |i| predecessor_blocks[i])
+                    .map(move |bb| self.terminator_loc(bb)),
+            )
+        } else {
+            None
+        };
+
+        let if_not_zero_locations = if loc.statement_index == 0 {
+            None
+        } else {
+            Some(Location {
+                block: loc.block,
+                statement_index: loc.statement_index - 1,
+            })
+        };
+
+        if_zero_locations
+            .into_iter()
+            .flatten()
+            .chain(if_not_zero_locations)
     }
 
     #[inline]
@@ -555,13 +584,15 @@ pub enum BindingForm<'tcx> {
 });
 
 mod binding_form_impl {
-    use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
     use ich::StableHashingContext;
+    use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 
     impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
-        fn hash_stable<W: StableHasherResult>(&self,
-                                            hcx: &mut StableHashingContext<'a>,
-                                            hasher: &mut StableHasher<W>) {
+        fn hash_stable<W: StableHasherResult>(
+            &self,
+            hcx: &mut StableHashingContext<'a>,
+            hasher: &mut StableHasher<W>,
+        ) {
             use super::BindingForm::*;
             ::std::mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -1478,16 +1509,17 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
                     .map(|&u| {
                         let mut s = String::new();
                         let c = ty::Const {
-                            val: ConstValue::Scalar(Scalar::Bits {
+                            val: ConstValue::Scalar(
+                                Scalar::Bits {
                                     bits: u,
                                     size: size.bytes() as u8,
-                                }.into()),
+                                }.into(),
+                            ),
                             ty: switch_ty,
                         };
                         fmt_const_val(&mut s, &c).unwrap();
                         s.into()
-                    })
-                    .chain(iter::once(String::from("otherwise").into()))
+                    }).chain(iter::once(String::from("otherwise").into()))
                     .collect()
             }
             Call {
@@ -2017,7 +2049,13 @@ pub enum AggregateKind<'tcx> {
     /// active field number and is present only for union expressions
     /// -- e.g. for a union expression `SomeUnion { c: .. }`, the
     /// active field index would identity the field `c`
-    Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<CanonicalTy<'tcx>>, Option<usize>),
+    Adt(
+        &'tcx AdtDef,
+        usize,
+        &'tcx Substs<'tcx>,
+        Option<CanonicalTy<'tcx>>,
+        Option<usize>,
+    ),
 
     Closure(DefId, ClosureSubsts<'tcx>),
     Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
@@ -2267,7 +2305,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result {
                 return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i);
             }
             Char => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
-            _ => {},
+            _ => {}
         }
     }
     // print function definitons
@@ -2283,14 +2321,12 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result {
                         let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
                         if let Some(interpret::AllocType::Memory(alloc)) = alloc {
                             assert_eq!(len as usize as u128, len);
-                            let slice = &alloc
-                                .bytes
-                                    [(ptr.offset.bytes() as usize)..]
-                                    [..(len as usize)];
+                            let slice =
+                                &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
                             let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
                             write!(f, "{:?}", s)
                         } else {
-                             write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
+                            write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
                         }
                     });
                 }
@@ -2394,6 +2430,8 @@ pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) ->
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum UnsafetyViolationKind {
     General,
+    /// unsafety is not allowed at all in min const fn
+    MinConstFn,
     ExternStatic(ast::NodeId),
     BorrowPacked(ast::NodeId),
 }
@@ -2821,15 +2859,13 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 let kind = box match **kind {
                     AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                     AggregateKind::Tuple => AggregateKind::Tuple,
-                    AggregateKind::Adt(def, v, substs, user_ty, n) => {
-                        AggregateKind::Adt(
-                            def,
-                            v,
-                            substs.fold_with(folder),
-                            user_ty.fold_with(folder),
-                            n,
-                        )
-                    }
+                    AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
+                        def,
+                        v,
+                        substs.fold_with(folder),
+                        user_ty.fold_with(folder),
+                        n,
+                    ),
                     AggregateKind::Closure(id, substs) => {
                         AggregateKind::Closure(id, substs.fold_with(folder))
                     }
@@ -2860,8 +2896,9 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
                 (match **kind {
                     AggregateKind::Array(ty) => ty.visit_with(visitor),
                     AggregateKind::Tuple => false,
-                    AggregateKind::Adt(_, _, substs, user_ty, _) =>
-                        substs.visit_with(visitor) || user_ty.visit_with(visitor),
+                    AggregateKind::Adt(_, _, substs, user_ty, _) => {
+                        substs.visit_with(visitor) || user_ty.visit_with(visitor)
+                    }
                     AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
                     AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
                 }) || fields.visit_with(visitor)
index a58bb4724d2e27fd85bfb4a1362bfdff70fa2f95..ee3fabc58d53f6edc6e6b150a1b652727991587b 100644 (file)
 use std::collections::btree_map::Keys as BTreeMapKeysIter;
 use std::collections::btree_map::Values as BTreeMapValuesIter;
 
+use rustc_data_structures::fx::FxHashSet;
 use std::{fmt, str};
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
-use std::collections::HashSet;
 use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
@@ -68,7 +68,7 @@ pub enum OptLevel {
     SizeMin,    // -Oz
 }
 
-#[derive(Clone, Copy, PartialEq, Hash)]
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum Lto {
     /// Don't do any LTO whatsoever
     No,
@@ -1373,7 +1373,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let max_atomic_width = sess.target.target.max_atomic_width();
     let atomic_cas = sess.target.target.options.atomic_cas;
 
-    let mut ret = HashSet::new();
+    let mut ret = FxHashSet::default();
     // Target bindings.
     ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os))));
     if let Some(ref fam) = sess.target.target.options.target_family {
index 32044fdf2a8cb2fa9df336d949ca3b9fc24d5dce..0de5d3d03d5c37cbb725264079ddc62b10bb42d3 100644 (file)
@@ -12,8 +12,8 @@
 
 pub use self::FileMatch::*;
 
+use rustc_data_structures::fx::FxHashSet;
 use std::borrow::Cow;
-use std::collections::HashSet;
 use std::env;
 use std::fs;
 use std::path::{Path, PathBuf};
@@ -40,7 +40,7 @@ impl<'a> FileSearch<'a> {
     pub fn for_each_lib_search_path<F>(&self, mut f: F) where
         F: FnMut(&Path, PathKind)
     {
-        let mut visited_dirs = HashSet::new();
+        let mut visited_dirs = FxHashSet::default();
 
         for (path, kind) in self.search_paths.iter(self.kind) {
             f(path, kind);
index c8c0d4c38a22126fb405cbd9f65acd7228dbd380..778c388c7dec71181c88bdb7da7b009c6f8a1c46 100644 (file)
@@ -47,7 +47,6 @@
 
 use std;
 use std::cell::{self, Cell, RefCell};
-use std::collections::HashMap;
 use std::env;
 use std::fmt;
 use std::io::Write;
@@ -122,7 +121,7 @@ pub struct Session {
     /// Map from imported macro spans (which consist of
     /// the localized span for the macro body) to the
     /// macro name and definition span in the source crate.
-    pub imported_macro_spans: OneThread<RefCell<HashMap<Span, (String, Span)>>>,
+    pub imported_macro_spans: OneThread<RefCell<FxHashMap<Span, (String, Span)>>>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
 
@@ -581,11 +580,6 @@ pub fn lto(&self) -> config::Lto {
             return config::Lto::No;
         }
 
-        // Right now ThinLTO isn't compatible with incremental compilation.
-        if self.opts.incremental.is_some() {
-            return config::Lto::No;
-        }
-
         // Now we're in "defaults" territory. By default we enable ThinLTO for
         // optimized compiles (anything greater than O0).
         match self.opts.optimize {
@@ -1122,7 +1116,7 @@ pub fn build_session_(
         injected_allocator: Once::new(),
         allocator_kind: Once::new(),
         injected_panic_runtime: Once::new(),
-        imported_macro_spans: OneThread::new(RefCell::new(HashMap::new())),
+        imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         self_profiling: Lock::new(SelfProfiler::new()),
         profile_channel: Lock::new(None),
@@ -1178,8 +1172,18 @@ pub fn build_session_(
 // commandline argument, you can do so here.
 fn validate_commandline_args_with_session_available(sess: &Session) {
 
-    if sess.lto() != Lto::No && sess.opts.incremental.is_some() {
-        sess.err("can't perform LTO when compiling incrementally");
+    if sess.opts.incremental.is_some() {
+        match sess.lto() {
+            Lto::Yes |
+            Lto::Thin |
+            Lto::Fat => {
+                sess.err("can't perform LTO when compiling incrementally");
+            }
+            Lto::ThinLocal |
+            Lto::No => {
+                // This is fine
+            }
+        }
     }
 
     // Since we don't know if code in an rlib will be linked to statically or
index 5c977e1bf624be9a0c6a804d7aa4ae3aaec88eb8..9998db4ad1d48569f8ce45bd488d949a5f3b2467 100644 (file)
@@ -269,7 +269,8 @@ fn process_obligation(&mut self,
         // doing more work yet
         if !pending_obligation.stalled_on.is_empty() {
             if pending_obligation.stalled_on.iter().all(|&ty| {
-                let resolved_ty = self.selcx.infcx().shallow_resolve(&ty);
+                // Use the force-inlined variant of shallow_resolve() because this code is hot.
+                let resolved_ty = self.selcx.infcx().inlined_shallow_resolve(&ty);
                 resolved_ty == ty // nothing changed here
             }) {
                 debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
index de50598c42c9da5774b02538806ab483193cfe27..6981d92f05f00cf9ec4c96acf9e99d4adccf19e9 100644 (file)
@@ -1099,6 +1099,37 @@ fn is_global(self) -> bool {
         local as usize == global as usize
     }
 
+    /// Returns true if this function must conform to `min_const_fn`
+    pub fn is_min_const_fn(self, def_id: DefId) -> bool {
+        if self.features().staged_api {
+            // some intrinsics are waved through if called inside the
+            // standard library. Users never need to call them directly
+            if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
+                assert!(!self.is_const_fn(def_id));
+                match &self.item_name(def_id).as_str()[..] {
+                    | "size_of"
+                    | "min_align_of"
+                    => return true,
+                    _ => {},
+                }
+            }
+            // in order for a libstd function to be considered min_const_fn
+            // it needs to be stable and have no `rustc_const_unstable` attribute
+            match self.lookup_stability(def_id) {
+                // stable functions with unstable const fn aren't `min_const_fn`
+                Some(&attr::Stability { const_stability: Some(_), .. }) => false,
+                // unstable functions don't need to conform
+                Some(&attr::Stability { ref level, .. }) if level.is_unstable() => false,
+                // everything else needs to conform, because it would be callable from
+                // other `min_const_fn` functions
+                _ => true,
+            }
+        } else {
+            // users enabling the `const_fn` can do what they want
+            !self.sess.features_untracked().const_fn
+        }
+    }
+
     /// Create a type context and call the closure with a `TyCtxt` reference
     /// to the context. The closure enforces that the type context and any interned
     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
index 63308ac46d10f4b7b28eb3a9e77756f6f587a5a0..5e2093d03566af5a4900b191f1de312719195984 100644 (file)
@@ -1692,12 +1692,17 @@ pub struct AdtFlags: u32 {
         const IS_FUNDAMENTAL      = 1 << 2;
         const IS_UNION            = 1 << 3;
         const IS_BOX              = 1 << 4;
-        /// Indicates whether this abstract data type will be expanded on in future (new
-        /// fields/variants) and as such, whether downstream crates must match exhaustively on the
-        /// fields/variants of this data type.
-        ///
-        /// See RFC 2008 (<https://github.com/rust-lang/rfcs/pull/2008>).
-        const IS_NON_EXHAUSTIVE   = 1 << 5;
+        /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
+        /// (i.e., this flag is never set unless this ADT is an enum).
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 5;
+    }
+}
+
+bitflags! {
+    pub struct VariantFlags: u32 {
+        const NO_VARIANT_FLAGS        = 0;
+        /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
+        const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
     }
 }
 
@@ -1710,8 +1715,56 @@ pub struct VariantDef {
     pub discr: VariantDiscr,
     pub fields: Vec<FieldDef>,
     pub ctor_kind: CtorKind,
+    flags: VariantFlags,
 }
 
+impl<'a, 'gcx, 'tcx> VariantDef {
+    /// Create a new `VariantDef`.
+    ///
+    /// - `did` is the DefId used for the variant - for tuple-structs, it is the constructor DefId,
+    /// and for everything else, it is the variant DefId.
+    /// - `attribute_def_id` is the DefId that has the variant's attributes.
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+               did: DefId,
+               name: Name,
+               discr: VariantDiscr,
+               fields: Vec<FieldDef>,
+               adt_kind: AdtKind,
+               ctor_kind: CtorKind)
+               -> Self
+    {
+        debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, name, discr, fields,
+               adt_kind, ctor_kind);
+        let mut flags = VariantFlags::NO_VARIANT_FLAGS;
+        if adt_kind == AdtKind::Struct && tcx.has_attr(did, "non_exhaustive") {
+            debug!("found non-exhaustive field list for {:?}", did);
+            flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
+        }
+        VariantDef {
+            did,
+            name,
+            discr,
+            fields,
+            ctor_kind,
+            flags
+        }
+    }
+
+    #[inline]
+    pub fn is_field_list_non_exhaustive(&self) -> bool {
+        self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
+    }
+}
+
+impl_stable_hash_for!(struct VariantDef {
+    did,
+    name,
+    discr,
+    fields,
+    ctor_kind,
+    flags
+});
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum VariantDiscr {
     /// Explicit value for this variant, i.e. `X = 123`.
@@ -1850,7 +1903,7 @@ pub struct ReprFlags: u8 {
 
 
 /// Represents the repr options provided by the user,
-#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
 pub struct ReprOptions {
     pub int: Option<attr::IntType>,
     pub align: u32,
@@ -1939,6 +1992,7 @@ fn new(tcx: TyCtxt,
            kind: AdtKind,
            variants: Vec<VariantDef>,
            repr: ReprOptions) -> Self {
+        debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
         let attrs = tcx.get_attrs(did);
         if attr::contains_name(&attrs, "fundamental") {
@@ -1950,8 +2004,9 @@ fn new(tcx: TyCtxt,
         if Some(did) == tcx.lang_items().owned_box() {
             flags = flags | AdtFlags::IS_BOX;
         }
-        if tcx.has_attr(did, "non_exhaustive") {
-            flags = flags | AdtFlags::IS_NON_EXHAUSTIVE;
+        if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
+            debug!("found non-exhaustive variant list for {:?}", did);
+            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
         }
         match kind {
             AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
@@ -1982,8 +2037,8 @@ pub fn is_enum(&self) -> bool {
     }
 
     #[inline]
-    pub fn is_non_exhaustive(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE)
+    pub fn is_variant_list_non_exhaustive(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
     }
 
     /// Returns the kind of the ADT - Struct or Enum.
index b5093d0a1fc951f9cb059da4e5cb55ab1eeb915a..837354bfcaf360246acac0c7717df5a2bb3708e3 100644 (file)
@@ -198,12 +198,6 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::const_to_allocation<'tcx> {
-    fn describe(_tcx: TyCtxt, val: &'tcx ty::Const<'tcx>) -> String {
-        format!("converting constant `{:?}` to an allocation", val)
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
     fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
         format!("erasing regions from `{:?}`", ty)
@@ -722,12 +716,6 @@ fn describe(_tcx: TyCtxt, _: InternedString) -> String {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::compile_codegen_unit<'tcx> {
-    fn describe(_tcx: TyCtxt, _: InternedString) -> String {
-        "compile_codegen_unit".to_string()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> {
     fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
         "output_filenames".to_string()
index e3b0f8c4570df1fc30d0a2e201018c626d9f9f22..d07891fca12aea5144fbe378051805c345a2eb43 100644 (file)
@@ -11,6 +11,7 @@
 #![allow(warnings)]
 
 use std::mem;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
 use rustc_data_structures::OnDrop;
 use syntax_pos::Span;
@@ -21,7 +22,7 @@
 use errors::Diagnostic;
 use std::process;
 use std::{fmt, ptr};
-use std::collections::HashSet;
+
 #[cfg(parallel_queries)]
 use {
     rayon_core,
@@ -282,7 +283,7 @@ fn visit_waiters<'tcx, F>(query: Lrc<QueryJob<'tcx>>, mut visit: F) -> Option<Op
 fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
                      span: Span,
                      stack: &mut Vec<(Span, Lrc<QueryJob<'tcx>>)>,
-                     visited: &mut HashSet<*const QueryJob<'tcx>>
+                     visited: &mut FxHashSet<*const QueryJob<'tcx>>
 ) -> Option<Option<Waiter<'tcx>>> {
     if visited.contains(&query.as_ptr()) {
         return if let Some(p) = stack.iter().position(|q| q.1.as_ptr() == query.as_ptr()) {
@@ -321,7 +322,7 @@ fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
 #[cfg(parallel_queries)]
 fn connected_to_root<'tcx>(
     query: Lrc<QueryJob<'tcx>>,
-    visited: &mut HashSet<*const QueryJob<'tcx>>
+    visited: &mut FxHashSet<*const QueryJob<'tcx>>
 ) -> bool {
     // We already visited this or we're deliberately ignoring it
     if visited.contains(&query.as_ptr()) {
@@ -357,7 +358,7 @@ fn remove_cycle<'tcx>(
     wakelist: &mut Vec<Lrc<QueryWaiter<'tcx>>>,
     tcx: TyCtxt<'_, 'tcx, '_>
 ) -> bool {
-    let mut visited = HashSet::new();
+    let mut visited = FxHashSet::default();
     let mut stack = Vec::new();
     // Look for a cycle starting with the last query in `jobs`
     if let Some(waiter) = cycle_check(jobs.pop().unwrap(),
@@ -389,7 +390,7 @@ fn remove_cycle<'tcx>(
         // connected to queries outside the cycle
         let entry_points: Vec<Lrc<QueryJob<'tcx>>> = stack.iter().filter_map(|query| {
             // Mark all the other queries in the cycle as already visited
-            let mut visited = HashSet::from_iter(stack.iter().filter_map(|q| {
+            let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| {
                 if q.1.as_ptr() != query.1.as_ptr() {
                     Some(q.1.as_ptr())
                 } else {
index 6f61583e49b8e8f0d1e9250ed2b26fa8c729dce1..993ba2fd13d0d7d05bda5003b97fe950d9cc92ea 100644 (file)
@@ -28,9 +28,9 @@
 use middle::lang_items::{LanguageItems, LangItem};
 use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
 use mir::interpret::ConstEvalResult;
-use mir::mono::{CodegenUnit, Stats};
+use mir::mono::CodegenUnit;
 use mir;
-use mir::interpret::{GlobalId, Allocation};
+use mir::interpret::GlobalId;
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
 use traits::{self, Vtable};
         /// other items (such as enum variant explicit discriminants).
         [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
             -> ConstEvalResult<'tcx>,
-
-        /// Converts a constant value to a constant allocation
-        [] fn const_to_allocation: const_to_allocation(
-            &'tcx ty::Const<'tcx>
-        ) -> &'tcx Allocation,
     },
 
     TypeChecking {
             -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
         [] fn is_codegened_item: IsCodegenedItem(DefId) -> bool,
         [] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
-        [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
     },
 
     Other {
@@ -706,12 +700,6 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
     DepConstructor::EraseRegionsTy { ty }
 }
 
-fn const_to_allocation<'tcx>(
-    val: &'tcx ty::Const<'tcx>,
-) -> DepConstructor<'tcx> {
-    DepConstructor::ConstToAllocation { val }
-}
-
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::TypeParamPredicates {
         item_id,
index 8473e4af40e3b9944063eb63234bebcc93bdb8d4..215fba54499b7e0065f53c78066d565d55191e97 100644 (file)
@@ -718,7 +718,7 @@ pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
             }
         }
 
-        #[allow(bad_style)]
+        #[allow(nonstandard_style)]
         #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
@@ -775,7 +775,7 @@ fn hash_stable<W: StableHasherResult>(&self,
         pub mod queries {
             use std::marker::PhantomData;
 
-            $(#[allow(bad_style)]
+            $(#[allow(nonstandard_style)]
             pub struct $name<$tcx> {
                 data: PhantomData<&$tcx ()>
             })*
@@ -1062,7 +1062,6 @@ macro_rules! force {
         DepKind::FulfillObligation |
         DepKind::VtableMethods |
         DepKind::EraseRegionsTy |
-        DepKind::ConstToAllocation |
         DepKind::NormalizeProjectionTy |
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::ImpliedOutlivesBounds |
index 842c0d6573432fb962057b3432bb4707f75f3048..3ff3cb4cae1d499dddf592c8a9db4854d0f00fcd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::sync::{RwLock, ReadGuard};
+use rustc_data_structures::sync::{RwLock, ReadGuard, MappedReadGuard};
 use std::mem;
 
 /// The `Steal` struct is intended to used as the value for a query.
@@ -42,7 +42,7 @@ pub fn new(value: T) -> Self {
         }
     }
 
-    pub fn borrow(&self) -> ReadGuard<T> {
+    pub fn borrow(&self) -> MappedReadGuard<T> {
         ReadGuard::map(self.value.borrow(), |opt| match *opt {
             None => bug!("attempted to read from stolen value"),
             Some(ref v) => v
index e3ef74f44db7f6ecb1efc03d44c505fa34fdb1e0..60b85e8a8eb9aad5c4eed9938a5caeabb07009f6 100644 (file)
@@ -487,10 +487,12 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
         use ::mir::interpret::EvalErrorKind::*;
         Some(match *self {
             MachineError(ref err) => MachineError(err.clone()),
-            FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
+            FunctionAbiMismatch(a, b) => FunctionAbiMismatch(a, b),
+            FunctionArgMismatch(a, b) => FunctionArgMismatch(
                 tcx.lift(&a)?,
                 tcx.lift(&b)?,
             ),
+            FunctionArgCountMismatch => FunctionArgCountMismatch,
             NoMirFor(ref s) => NoMirFor(s.clone()),
             UnterminatedCString(ptr) => UnterminatedCString(ptr),
             DanglingPointerDeref => DanglingPointerDeref,
index bdfba7c3e3a37665c7132c22eb1c15b416191210..02bdc5f41b35428e04287114043e94ce6ad0b5f5 100644 (file)
@@ -84,7 +84,7 @@ pub struct ProfQDumpParams {
     pub dump_profq_msg_log:bool,
 }
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct QueryMsg {
     pub query: &'static str,
index 74ff1a5f4fd0d395ef5121a025c5589a7679370e..70760d35f7865c1f3e78d8b208f6990d37cb59d7 100644 (file)
@@ -21,7 +21,7 @@ pub enum ProfileCategory {
             $($name),*
         }
 
-        #[allow(bad_style)]
+        #[allow(nonstandard_style)]
         struct Categories<T> {
             $($name: T),*
         }
index a8502682a806b718f93c6e5b7c9943d86cba759a..3ba4e4ddbb13bb7e883f26b7096ba4324aac5be1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::fs::File;
 use std::io::prelude::*;
 use std::marker::PhantomData;
@@ -40,7 +40,7 @@ struct PerThread {
 
 #[derive(Clone)]
 pub struct TimeGraph {
-    data: Arc<Mutex<HashMap<TimelineId, PerThread>>>,
+    data: Arc<Mutex<FxHashMap<TimelineId, PerThread>>>,
 }
 
 #[derive(Clone, Copy)]
@@ -68,7 +68,7 @@ fn drop(&mut self) {
 impl TimeGraph {
     pub fn new() -> TimeGraph {
         TimeGraph {
-            data: Arc::new(Mutex::new(HashMap::new()))
+            data: Arc::new(Mutex::new(FxHashMap::default()))
         }
     }
 
index 28fa49846b7369de67024aacf0ac81e4121952b4..b711502b14b7fb1af4222d0859fbf82a03e75d06 100644 (file)
@@ -14,6 +14,7 @@ cc = "1.0.1"
 num_cpus = "1.0"
 rustc-demangle = "0.1.4"
 rustc_llvm = { path = "../librustc_llvm" }
+memmap = "0.6"
 
 [features]
 # This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm`
index eee60b262a1c7b44b9d90f4745d67db015015742..ebb229b7b6bfaca67f304b84c4f245e53fc5e3f1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::ffi::{OsStr, OsString};
 use std::fs::{self, File};
 use std::io::prelude::*;
@@ -31,7 +31,7 @@
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
 pub struct LinkerInfo {
-    exports: HashMap<CrateType, Vec<String>>,
+    exports: FxHashMap<CrateType, Vec<String>>,
 }
 
 impl LinkerInfo {
index 56858a31efd25fd5fe3584f10b979d3474ec950b..25bc662c408f65ca47e545e66b2de7ae029172bc 100644 (file)
 use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION};
 use back::symbol_export;
 use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
-use back::write::{self, DiagnosticHandlers};
+use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename};
 use errors::{FatalError, Handler};
 use llvm::archive_ro::ArchiveRO;
 use llvm::{True, False};
 use llvm;
+use memmap;
+use rustc::dep_graph::WorkProduct;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::session::config::{self, Lto};
 use rustc::util::common::time_ext;
+use rustc_data_structures::fx::FxHashMap;
 use time_graph::Timeline;
-use {ModuleCodegen, ModuleLlvm, ModuleKind, ModuleSource};
+use {ModuleCodegen, ModuleLlvm, ModuleKind};
 
 use libc;
 
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
+use std::fs;
 use std::ptr;
 use std::slice;
 use std::sync::Arc;
@@ -75,8 +79,8 @@ pub(crate) unsafe fn optimize(&mut self,
                 let module = module.take().unwrap();
                 {
                     let config = cgcx.config(module.kind);
-                    let llmod = module.llvm().unwrap().llmod();
-                    let tm = &*module.llvm().unwrap().tm;
+                    let llmod = module.module_llvm.llmod();
+                    let tm = &*module.module_llvm.tm;
                     run_pass_manager(cgcx, tm, llmod, config, false);
                     timeline.record("fat-done");
                 }
@@ -97,10 +101,16 @@ pub fn cost(&self) -> u64 {
     }
 }
 
+/// Performs LTO, which in the case of full LTO means merging all modules into
+/// a single one and returning it for further optimizing. For ThinLTO, it will
+/// do the global analysis necessary and return two lists, one of the modules
+/// the need optimization and another for modules that can simply be copied over
+/// from the incr. comp. cache.
 pub(crate) fn run(cgcx: &CodegenContext,
                   modules: Vec<ModuleCodegen>,
+                  cached_modules: Vec<(SerializedModule, WorkProduct)>,
                   timeline: &mut Timeline)
-    -> Result<Vec<LtoModuleCodegen>, FatalError>
+    -> Result<(Vec<LtoModuleCodegen>, Vec<WorkProduct>), FatalError>
 {
     let diag_handler = cgcx.create_diag_handler();
     let export_threshold = match cgcx.lto {
@@ -187,11 +197,20 @@ pub(crate) fn run(cgcx: &CodegenContext,
         }
     }
 
-    let arr = symbol_white_list.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
+    let symbol_white_list = symbol_white_list.iter()
+                                             .map(|c| c.as_ptr())
+                                             .collect::<Vec<_>>();
     match cgcx.lto {
         Lto::Yes | // `-C lto` == fat LTO by default
         Lto::Fat => {
-            fat_lto(cgcx, &diag_handler, modules, upstream_modules, &arr, timeline)
+            assert!(cached_modules.is_empty());
+            let opt_jobs = fat_lto(cgcx,
+                                  &diag_handler,
+                                  modules,
+                                  upstream_modules,
+                                  &symbol_white_list,
+                                  timeline);
+            opt_jobs.map(|opt_jobs| (opt_jobs, vec![]))
         }
         Lto::Thin |
         Lto::ThinLocal => {
@@ -199,7 +218,13 @@ pub(crate) fn run(cgcx: &CodegenContext,
                 unreachable!("We should never reach this case if the LTO step \
                               is deferred to the linker");
             }
-            thin_lto(&diag_handler, modules, upstream_modules, &arr, timeline)
+            thin_lto(cgcx,
+                     &diag_handler,
+                     modules,
+                     upstream_modules,
+                     cached_modules,
+                     &symbol_white_list,
+                     timeline)
         }
         Lto::No => unreachable!(),
     }
@@ -229,7 +254,7 @@ fn fat_lto(cgcx: &CodegenContext,
         .filter(|&(_, module)| module.kind == ModuleKind::Regular)
         .map(|(i, module)| {
             let cost = unsafe {
-                llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod())
+                llvm::LLVMRustModuleCost(module.module_llvm.llmod())
             };
             (cost, i)
         })
@@ -239,7 +264,7 @@ fn fat_lto(cgcx: &CodegenContext,
     let mut serialized_bitcode = Vec::new();
     {
         let (llcx, llmod) = {
-            let llvm = module.llvm().expect("can't lto pre-codegened modules");
+            let llvm = &module.module_llvm;
             (&llvm.llcx, llvm.llmod())
         };
         info!("using {:?} as a base module", module.name);
@@ -255,8 +280,7 @@ fn fat_lto(cgcx: &CodegenContext,
         // way we know of to do that is to serialize them to a string and them parse
         // them later. Not great but hey, that's why it's "fat" LTO, right?
         for module in modules {
-            let llvm = module.llvm().expect("can't lto pre-codegened modules");
-            let buffer = ModuleBuffer::new(llvm.llmod());
+            let buffer = ModuleBuffer::new(module.module_llvm.llmod());
             let llmod_id = CString::new(&module.name[..]).unwrap();
             serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
         }
@@ -362,16 +386,23 @@ fn drop(&mut self) {
 /// calculating the *index* for ThinLTO. This index will then be shared amongst
 /// all of the `LtoModuleCodegen` units returned below and destroyed once
 /// they all go out of scope.
-fn thin_lto(diag_handler: &Handler,
+fn thin_lto(cgcx: &CodegenContext,
+            diag_handler: &Handler,
             modules: Vec<ModuleCodegen>,
             serialized_modules: Vec<(SerializedModule, CString)>,
+            cached_modules: Vec<(SerializedModule, WorkProduct)>,
             symbol_white_list: &[*const libc::c_char],
             timeline: &mut Timeline)
-    -> Result<Vec<LtoModuleCodegen>, FatalError>
+    -> Result<(Vec<LtoModuleCodegen>, Vec<WorkProduct>), FatalError>
 {
     unsafe {
         info!("going for that thin, thin LTO");
 
+        let green_modules: FxHashMap<_, _> = cached_modules
+            .iter()
+            .map(|&(_, ref wp)| (wp.cgu_name.clone(), wp.clone()))
+            .collect();
+
         let mut thin_buffers = Vec::new();
         let mut module_names = Vec::new();
         let mut thin_modules = Vec::new();
@@ -385,9 +416,24 @@ fn thin_lto(diag_handler: &Handler,
         //        analysis!
         for (i, module) in modules.iter().enumerate() {
             info!("local module: {} - {}", i, module.name);
-            let llvm = module.llvm().expect("can't lto precodegened module");
             let name = CString::new(module.name.clone()).unwrap();
-            let buffer = ThinBuffer::new(llvm.llmod());
+            let buffer = ThinBuffer::new(module.module_llvm.llmod());
+
+            // We emit the module after having serialized it into a ThinBuffer
+            // because only then it will contain the ThinLTO module summary.
+            if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir {
+                if cgcx.config(module.kind).emit_pre_thin_lto_bc {
+                    let path = incr_comp_session_dir
+                        .join(pre_lto_bitcode_filename(&module.name));
+
+                    fs::write(&path, buffer.data()).unwrap_or_else(|e| {
+                        panic!("Error writing pre-lto-bitcode file `{}`: {}",
+                               path.display(),
+                               e);
+                    });
+                }
+            }
+
             thin_modules.push(llvm::ThinLTOModule {
                 identifier: name.as_ptr(),
                 data: buffer.data().as_ptr(),
@@ -415,8 +461,13 @@ fn thin_lto(diag_handler: &Handler,
         //        looking at upstream modules entirely sometimes (the contents,
         //        we must always unconditionally look at the index).
         let mut serialized = Vec::new();
-        for (module, name) in serialized_modules {
-            info!("foreign module {:?}", name);
+
+        let cached_modules = cached_modules.into_iter().map(|(sm, wp)| {
+            (sm, CString::new(wp.cgu_name).unwrap())
+        });
+
+        for (module, name) in serialized_modules.into_iter().chain(cached_modules) {
+            info!("upstream or cached module {:?}", name);
             thin_modules.push(llvm::ThinLTOModule {
                 identifier: name.as_ptr(),
                 data: module.data().as_ptr(),
@@ -426,6 +477,9 @@ fn thin_lto(diag_handler: &Handler,
             module_names.push(name);
         }
 
+        // Sanity check
+        assert_eq!(thin_modules.len(), module_names.len());
+
         // Delegate to the C++ bindings to create some data here. Once this is a
         // tried-and-true interface we may wish to try to upstream some of this
         // to LLVM itself, right now we reimplement a lot of what they do
@@ -439,10 +493,22 @@ fn thin_lto(diag_handler: &Handler,
             write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
         })?;
 
-        let data = ThinData(data);
         info!("thin LTO data created");
         timeline.record("data");
 
+        let import_map = if cgcx.incr_comp_session_dir.is_some() {
+            ThinLTOImports::from_thin_lto_data(data)
+        } else {
+            // If we don't compile incrementally, we don't need to load the
+            // import data from LLVM.
+            assert!(green_modules.is_empty());
+            ThinLTOImports::new()
+        };
+        info!("thin LTO import map loaded");
+        timeline.record("import-map-loaded");
+
+        let data = ThinData(data);
+
         // Throw our data in an `Arc` as we'll be sharing it across threads. We
         // also put all memory referenced by the C++ data (buffers, ids, etc)
         // into the arc as well. After this we'll create a thin module
@@ -453,12 +519,38 @@ fn thin_lto(diag_handler: &Handler,
             serialized_modules: serialized,
             module_names,
         });
-        Ok((0..shared.module_names.len()).map(|i| {
-            LtoModuleCodegen::Thin(ThinModule {
+
+        let mut copy_jobs = vec![];
+        let mut opt_jobs = vec![];
+
+        info!("checking which modules can be-reused and which have to be re-optimized.");
+        for (module_index, module_name) in shared.module_names.iter().enumerate() {
+            let module_name = module_name_to_str(module_name);
+
+            // If the module hasn't changed and none of the modules it imports
+            // from has changed, we can re-use the post-ThinLTO version of the
+            // module.
+            if green_modules.contains_key(module_name) {
+                let imports_all_green = import_map.modules_imported_by(module_name)
+                    .iter()
+                    .all(|imported_module| green_modules.contains_key(imported_module));
+
+                if imports_all_green {
+                    let work_product = green_modules[module_name].clone();
+                    copy_jobs.push(work_product);
+                    info!(" - {}: re-used", module_name);
+                    continue
+                }
+            }
+
+            info!(" - {}: re-compiled", module_name);
+            opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
                 shared: shared.clone(),
-                idx: i,
-            })
-        }).collect())
+                idx: module_index,
+            }));
+        }
+
+        Ok((opt_jobs, copy_jobs))
     }
 }
 
@@ -527,6 +619,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
 pub enum SerializedModule {
     Local(ModuleBuffer),
     FromRlib(Vec<u8>),
+    FromUncompressedFile(memmap::Mmap),
 }
 
 impl SerializedModule {
@@ -534,6 +627,7 @@ fn data(&self) -> &[u8] {
         match *self {
             SerializedModule::Local(ref m) => m.data(),
             SerializedModule::FromRlib(ref m) => m,
+            SerializedModule::FromUncompressedFile(ref m) => m,
         }
     }
 }
@@ -663,16 +757,16 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
             write::llvm_err(&diag_handler, msg)
         })? as *const _;
         let module = ModuleCodegen {
-            source: ModuleSource::Codegened(ModuleLlvm {
+            module_llvm: ModuleLlvm {
                 llmod_raw,
                 llcx,
                 tm,
-            }),
+            },
             name: self.name().to_string(),
             kind: ModuleKind::Regular,
         };
         {
-            let llmod = module.llvm().unwrap().llmod();
+            let llmod = module.module_llvm.llmod();
             cgcx.save_temp_bitcode(&module, "thin-lto-input");
 
             // Before we do much else find the "main" `DICompileUnit` that we'll be
@@ -768,7 +862,7 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
             // little differently.
             info!("running thin lto passes over {}", module.name);
             let config = cgcx.config(module.kind);
-            run_pass_manager(cgcx, module.llvm().unwrap().tm, llmod, config, true);
+            run_pass_manager(cgcx, module.module_llvm.tm, llmod, config, true);
             cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
             timeline.record("thin-done");
         }
@@ -776,3 +870,61 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
         Ok(module)
     }
 }
+
+#[derive(Debug)]
+pub struct ThinLTOImports {
+    // key = llvm name of importing module, value = list of modules it imports from
+    imports: FxHashMap<String, Vec<String>>,
+}
+
+impl ThinLTOImports {
+    fn new() -> ThinLTOImports {
+        ThinLTOImports {
+            imports: FxHashMap(),
+        }
+    }
+
+    fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] {
+        self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
+    }
+
+    /// Load the ThinLTO import map from ThinLTOData.
+    unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
+        unsafe extern "C" fn imported_module_callback(payload: *mut libc::c_void,
+                                                      importing_module_name: *const libc::c_char,
+                                                      imported_module_name: *const libc::c_char) {
+            let map = &mut* (payload as *mut ThinLTOImports);
+            let importing_module_name = CStr::from_ptr(importing_module_name);
+            let importing_module_name = module_name_to_str(&importing_module_name);
+            let imported_module_name = CStr::from_ptr(imported_module_name);
+            let imported_module_name = module_name_to_str(&imported_module_name);
+
+            if !map.imports.contains_key(importing_module_name) {
+                map.imports.insert(importing_module_name.to_owned(), vec![]);
+            }
+
+            map.imports
+               .get_mut(importing_module_name)
+               .unwrap()
+               .push(imported_module_name.to_owned());
+        }
+        let mut map = ThinLTOImports {
+            imports: FxHashMap(),
+        };
+        llvm::LLVMRustGetThinLTOModuleImports(data,
+                                              imported_module_callback,
+                                              &mut map as *mut _ as *mut libc::c_void);
+        map
+    }
+}
+
+fn module_name_to_str(c_str: &CStr) -> &str {
+    match c_str.to_str() {
+        Ok(s) => s,
+        Err(e) => {
+            bug!("Encountered non-utf8 LLVM module name `{}`: {}",
+                c_str.to_string_lossy(),
+                e)
+        }
+    }
+}
index 2c3a143646c24c57dabe9336f262bcee4aef8be4..aa4f7688b0f42fb7be454b93e8017609a3c88d93 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashSet;
+use rustc_data_structures::fx::FxHashSet;
 use std::env;
 use std::path::{Path, PathBuf};
 use std::fs;
@@ -172,7 +172,7 @@ fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
 }
 
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
-    let mut set = HashSet::new();
+    let mut set = FxHashSet::default();
     let mut minimized = Vec::new();
     for rpath in rpaths {
         if set.insert(rpath) {
index 2373428d68c0d64be518e5cccd91c154770c46f6..6b257ed4c3e94f8b23e386eab095afd3ad350e4c 100644 (file)
 
 use attributes;
 use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
-use back::lto::{self, ModuleBuffer, ThinBuffer};
+use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule};
 use back::link::{self, get_linker, remove};
 use back::command::Command;
 use back::linker::LinkerInfo;
 use back::symbol_export::ExportedSymbols;
 use base;
 use consts;
-use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir};
+use memmap;
+use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir,
+                        in_incr_comp_dir, in_incr_comp_dir_sess};
 use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
@@ -26,7 +28,8 @@
 use time_graph::{self, TimeGraph, Timeline};
 use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
 use llvm_util;
-use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
+use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm,
+     CachedModuleCodegen};
 use CrateInfo;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::ty::TyCtxt;
@@ -84,6 +87,8 @@
     ("local-exec", llvm::ThreadLocalMode::LocalExec),
 ];
 
+const PRE_THIN_LTO_BC_EXT: &str = "pre-thin-lto.bc";
+
 pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
     match llvm::last_error() {
         Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
@@ -171,13 +176,22 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
         None => llvm::CodeModel::None,
     };
 
-    let singlethread = sess.target.target.options.singlethread;
+    let features = attributes::llvm_target_features(sess).collect::<Vec<_>>();
+    let mut singlethread = sess.target.target.options.singlethread;
+
+    // On the wasm target once the `atomics` feature is enabled that means that
+    // we're no longer single-threaded, or otherwise we don't want LLVM to
+    // lower atomic operations to single-threaded operations.
+    if singlethread &&
+        sess.target.target.llvm_target.contains("wasm32") &&
+        features.iter().any(|s| *s == "+atomics")
+    {
+        singlethread = false;
+    }
 
     let triple = SmallCStr::new(&sess.target.target.llvm_target);
     let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
-    let features = attributes::llvm_target_features(sess)
-        .collect::<Vec<_>>()
-        .join(",");
+    let features = features.join(",");
     let features = CString::new(features).unwrap();
     let is_pie_binary = !find_features && is_pie_binary(sess);
     let trap_unreachable = sess.target.target.options.trap_unreachable;
@@ -223,6 +237,7 @@ pub struct ModuleConfig {
     pgo_use: String,
 
     // Flags indicating which outputs to produce.
+    pub emit_pre_thin_lto_bc: bool,
     emit_no_opt_bc: bool,
     emit_bc: bool,
     emit_bc_compressed: bool,
@@ -260,6 +275,7 @@ fn new(passes: Vec<String>) -> ModuleConfig {
             pgo_use: String::new(),
 
             emit_no_opt_bc: false,
+            emit_pre_thin_lto_bc: false,
             emit_bc: false,
             emit_bc_compressed: false,
             emit_lto_bc: false,
@@ -392,7 +408,7 @@ pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) {
             let cgu = Some(&module.name[..]);
             let path = self.output_filenames.temp_path_ext(&ext, cgu);
             let cstr = path2cstr(&path);
-            let llmod = module.llvm().unwrap().llmod();
+            let llmod = module.module_llvm.llmod();
             llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
         }
     }
@@ -495,13 +511,9 @@ unsafe fn optimize(cgcx: &CodegenContext,
                    timeline: &mut Timeline)
     -> Result<(), FatalError>
 {
-    let (llmod, llcx, tm) = match module.source {
-        ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
-        ModuleSource::Preexisting(_) => {
-            bug!("optimize_and_codegen: called with ModuleSource::Preexisting")
-        }
-    };
-
+    let llmod = module.module_llvm.llmod();
+    let llcx = &*module.module_llvm.llcx;
+    let tm = &*module.module_llvm.tm;
     let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
 
     let module_name = module.name.clone();
@@ -627,7 +639,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
 }
 
 fn generate_lto_work(cgcx: &CodegenContext,
-                     modules: Vec<ModuleCodegen>)
+                     modules: Vec<ModuleCodegen>,
+                     import_only_modules: Vec<(SerializedModule, WorkProduct)>)
     -> Vec<(WorkItem, u64)>
 {
     let mut timeline = cgcx.time_graph.as_ref().map(|tg| {
@@ -635,13 +648,22 @@ fn generate_lto_work(cgcx: &CodegenContext,
                  CODEGEN_WORK_PACKAGE_KIND,
                  "generate lto")
     }).unwrap_or(Timeline::noop());
-    let lto_modules = lto::run(cgcx, modules, &mut timeline)
+    let (lto_modules, copy_jobs) = lto::run(cgcx, modules, import_only_modules, &mut timeline)
         .unwrap_or_else(|e| e.raise());
 
-    lto_modules.into_iter().map(|module| {
+    let lto_modules = lto_modules.into_iter().map(|module| {
         let cost = module.cost();
         (WorkItem::LTO(module), cost)
-    }).collect()
+    });
+
+    let copy_jobs = copy_jobs.into_iter().map(|wp| {
+        (WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
+            name: wp.cgu_name.clone(),
+            source: wp,
+        }), 0)
+    });
+
+    lto_modules.chain(copy_jobs).collect()
 }
 
 unsafe fn codegen(cgcx: &CodegenContext,
@@ -653,12 +675,9 @@ unsafe fn codegen(cgcx: &CodegenContext,
 {
     timeline.record("codegen");
     {
-        let (llmod, llcx, tm) = match module.source {
-            ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
-            ModuleSource::Preexisting(_) => {
-                bug!("codegen: called with ModuleSource::Preexisting")
-            }
-        };
+        let llmod = module.module_llvm.llmod();
+        let llcx = &*module.module_llvm.llcx;
+        let tm = &*module.module_llvm.tm;
         let module_name = module.name.clone();
         let module_name = Some(&module_name[..]);
         let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
@@ -912,6 +931,20 @@ fn need_crate_bitcode_for_rlib(sess: &Session) -> bool {
     sess.opts.output_types.contains_key(&OutputType::Exe)
 }
 
+fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
+    if sess.opts.incremental.is_none() {
+        return false
+    }
+
+    match sess.lto() {
+        Lto::Yes |
+        Lto::Fat |
+        Lto::No => false,
+        Lto::Thin |
+        Lto::ThinLocal => true,
+    }
+}
+
 pub fn start_async_codegen(tcx: TyCtxt,
                                time_graph: Option<TimeGraph>,
                                metadata: EncodedMetadata,
@@ -970,6 +1003,7 @@ pub fn start_async_codegen(tcx: TyCtxt,
     // Save all versions of the bytecode if we're saving our temporaries.
     if sess.opts.cg.save_temps {
         modules_config.emit_no_opt_bc = true;
+        modules_config.emit_pre_thin_lto_bc = true;
         modules_config.emit_bc = true;
         modules_config.emit_lto_bc = true;
         metadata_config.emit_bc = true;
@@ -984,6 +1018,9 @@ pub fn start_async_codegen(tcx: TyCtxt,
         allocator_config.emit_bc_compressed = true;
     }
 
+    modules_config.emit_pre_thin_lto_bc =
+        need_pre_thin_lto_bitcode_for_incr_comp(sess);
+
     modules_config.no_integrated_as = tcx.sess.opts.cg.no_integrated_as ||
         tcx.sess.target.target.options.no_integrated_as;
 
@@ -1056,7 +1093,7 @@ pub fn start_async_codegen(tcx: TyCtxt,
 
 fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
     sess: &Session,
-    compiled_modules: &CompiledModules
+    compiled_modules: &CompiledModules,
 ) -> FxHashMap<WorkProductId, WorkProduct> {
     let mut work_products = FxHashMap::default();
 
@@ -1064,7 +1101,7 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
         return work_products;
     }
 
-    for module in compiled_modules.modules.iter() {
+    for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
         let mut files = vec![];
 
         if let Some(ref path) = module.object {
@@ -1236,21 +1273,30 @@ fn produce_final_output_artifacts(sess: &Session,
     // These are used in linking steps and will be cleaned up afterward.
 }
 
-pub(crate) fn dump_incremental_data(codegen_results: &CodegenResults) {
-    println!("[incremental] Re-using {} out of {} modules",
-              codegen_results.modules.iter().filter(|m| m.pre_existing).count(),
-              codegen_results.modules.len());
+pub(crate) fn dump_incremental_data(_codegen_results: &CodegenResults) {
+    // FIXME(mw): This does not work at the moment because the situation has
+    //            become more complicated due to incremental LTO. Now a CGU
+    //            can have more than two caching states.
+    // println!("[incremental] Re-using {} out of {} modules",
+    //           codegen_results.modules.iter().filter(|m| m.pre_existing).count(),
+    //           codegen_results.modules.len());
 }
 
 enum WorkItem {
+    /// Optimize a newly codegened, totally unoptimized module.
     Optimize(ModuleCodegen),
+    /// Copy the post-LTO artifacts from the incremental cache to the output
+    /// directory.
+    CopyPostLtoArtifacts(CachedModuleCodegen),
+    /// Perform (Thin)LTO on the given module.
     LTO(lto::LtoModuleCodegen),
 }
 
 impl WorkItem {
-    fn kind(&self) -> ModuleKind {
+    fn module_kind(&self) -> ModuleKind {
         match *self {
             WorkItem::Optimize(ref m) => m.kind,
+            WorkItem::CopyPostLtoArtifacts(_) |
             WorkItem::LTO(_) => ModuleKind::Regular,
         }
     }
@@ -1258,6 +1304,7 @@ fn kind(&self) -> ModuleKind {
     fn name(&self) -> String {
         match *self {
             WorkItem::Optimize(ref m) => format!("optimize: {}", m.name),
+            WorkItem::CopyPostLtoArtifacts(ref m) => format!("copy post LTO artifacts: {}", m.name),
             WorkItem::LTO(ref m) => format!("lto: {}", m.name()),
         }
     }
@@ -1273,141 +1320,168 @@ fn execute_work_item(cgcx: &CodegenContext,
                      timeline: &mut Timeline)
     -> Result<WorkItemResult, FatalError>
 {
-    let diag_handler = cgcx.create_diag_handler();
-    let config = cgcx.config(work_item.kind());
-    let module = match work_item {
-        WorkItem::Optimize(module) => module,
-        WorkItem::LTO(mut lto) => {
-            unsafe {
-                let module = lto.optimize(cgcx, timeline)?;
-                let module = codegen(cgcx, &diag_handler, module, config, timeline)?;
-                return Ok(WorkItemResult::Compiled(module))
-            }
+    let module_config = cgcx.config(work_item.module_kind());
+
+    match work_item {
+        WorkItem::Optimize(module) => {
+            execute_optimize_work_item(cgcx, module, module_config, timeline)
         }
-    };
-    let module_name = module.name.clone();
+        WorkItem::CopyPostLtoArtifacts(module) => {
+            execute_copy_from_cache_work_item(cgcx, module, module_config, timeline)
+        }
+        WorkItem::LTO(module) => {
+            execute_lto_work_item(cgcx, module, module_config, timeline)
+        }
+    }
+}
 
-    let pre_existing = match module.source {
-        ModuleSource::Codegened(_) => None,
-        ModuleSource::Preexisting(ref wp) => Some(wp.clone()),
-    };
+fn execute_optimize_work_item(cgcx: &CodegenContext,
+                              module: ModuleCodegen,
+                              module_config: &ModuleConfig,
+                              timeline: &mut Timeline)
+    -> Result<WorkItemResult, FatalError>
+{
+    let diag_handler = cgcx.create_diag_handler();
 
-    if let Some(wp) = pre_existing {
-        let incr_comp_session_dir = cgcx.incr_comp_session_dir
-                                        .as_ref()
-                                        .unwrap();
-        let name = &module.name;
-        let mut object = None;
-        let mut bytecode = None;
-        let mut bytecode_compressed = None;
-        for (kind, saved_file) in wp.saved_files {
-            let obj_out = match kind {
-                WorkProductFileKind::Object => {
-                    let path = cgcx.output_filenames.temp_path(OutputType::Object, Some(name));
-                    object = Some(path.clone());
-                    path
-                }
-                WorkProductFileKind::Bytecode => {
-                    let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name));
-                    bytecode = Some(path.clone());
-                    path
-                }
-                WorkProductFileKind::BytecodeCompressed => {
-                    let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name))
-                        .with_extension(RLIB_BYTECODE_EXTENSION);
-                    bytecode_compressed = Some(path.clone());
-                    path
-                }
-            };
-            let source_file = in_incr_comp_dir(&incr_comp_session_dir,
-                                               &saved_file);
-            debug!("copying pre-existing module `{}` from {:?} to {}",
-                   module.name,
-                   source_file,
-                   obj_out.display());
-            match link_or_copy(&source_file, &obj_out) {
-                Ok(_) => { }
-                Err(err) => {
-                    diag_handler.err(&format!("unable to copy {} to {}: {}",
-                                              source_file.display(),
-                                              obj_out.display(),
-                                              err));
-                }
-            }
+    unsafe {
+        optimize(cgcx, &diag_handler, &module, module_config, timeline)?;
+    }
+
+    let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled();
+
+    // After we've done the initial round of optimizations we need to
+    // decide whether to synchronously codegen this module or ship it
+    // back to the coordinator thread for further LTO processing (which
+    // has to wait for all the initial modules to be optimized).
+    //
+    // Here we dispatch based on the `cgcx.lto` and kind of module we're
+    // codegenning...
+    let needs_lto = match cgcx.lto {
+        Lto::No => false,
+
+        // If the linker does LTO, we don't have to do it. Note that we
+        // keep doing full LTO, if it is requested, as not to break the
+        // assumption that the output will be a single module.
+        Lto::Thin | Lto::ThinLocal if linker_does_lto => false,
+
+        // Here we've got a full crate graph LTO requested. We ignore
+        // this, however, if the crate type is only an rlib as there's
+        // no full crate graph to process, that'll happen later.
+        //
+        // This use case currently comes up primarily for targets that
+        // require LTO so the request for LTO is always unconditionally
+        // passed down to the backend, but we don't actually want to do
+        // anything about it yet until we've got a final product.
+        Lto::Yes | Lto::Fat | Lto::Thin => {
+            cgcx.crate_types.len() != 1 ||
+                cgcx.crate_types[0] != config::CrateType::Rlib
         }
-        assert_eq!(object.is_some(), config.emit_obj);
-        assert_eq!(bytecode.is_some(), config.emit_bc);
-        assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
-
-        Ok(WorkItemResult::Compiled(CompiledModule {
-            name: module_name,
-            kind: ModuleKind::Regular,
-            pre_existing: true,
-            object,
-            bytecode,
-            bytecode_compressed,
-        }))
-    } else {
-        debug!("llvm-optimizing {:?}", module_name);
 
-        unsafe {
-            optimize(cgcx, &diag_handler, &module, config, timeline)?;
-
-            let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled();
-
-            // After we've done the initial round of optimizations we need to
-            // decide whether to synchronously codegen this module or ship it
-            // back to the coordinator thread for further LTO processing (which
-            // has to wait for all the initial modules to be optimized).
-            //
-            // Here we dispatch based on the `cgcx.lto` and kind of module we're
-            // codegenning...
-            let needs_lto = match cgcx.lto {
-                Lto::No => false,
-
-                // If the linker does LTO, we don't have to do it. Note that we
-                // keep doing full LTO, if it is requested, as not to break the
-                // assumption that the output will be a single module.
-                Lto::Thin | Lto::ThinLocal if linker_does_lto => false,
-
-                // Here we've got a full crate graph LTO requested. We ignore
-                // this, however, if the crate type is only an rlib as there's
-                // no full crate graph to process, that'll happen later.
-                //
-                // This use case currently comes up primarily for targets that
-                // require LTO so the request for LTO is always unconditionally
-                // passed down to the backend, but we don't actually want to do
-                // anything about it yet until we've got a final product.
-                Lto::Yes | Lto::Fat | Lto::Thin => {
-                    cgcx.crate_types.len() != 1 ||
-                        cgcx.crate_types[0] != config::CrateType::Rlib
-                }
+        // When we're automatically doing ThinLTO for multi-codegen-unit
+        // builds we don't actually want to LTO the allocator modules if
+        // it shows up. This is due to various linker shenanigans that
+        // we'll encounter later.
+        //
+        // Additionally here's where we also factor in the current LLVM
+        // version. If it doesn't support ThinLTO we skip this.
+        Lto::ThinLocal => {
+            module.kind != ModuleKind::Allocator &&
+                unsafe { llvm::LLVMRustThinLTOAvailable() }
+        }
+    };
 
-                // When we're automatically doing ThinLTO for multi-codegen-unit
-                // builds we don't actually want to LTO the allocator modules if
-                // it shows up. This is due to various linker shenanigans that
-                // we'll encounter later.
-                //
-                // Additionally here's where we also factor in the current LLVM
-                // version. If it doesn't support ThinLTO we skip this.
-                Lto::ThinLocal => {
-                    module.kind != ModuleKind::Allocator &&
-                        llvm::LLVMRustThinLTOAvailable()
-                }
-            };
+    // Metadata modules never participate in LTO regardless of the lto
+    // settings.
+    let needs_lto = needs_lto && module.kind != ModuleKind::Metadata;
 
-            // Metadata modules never participate in LTO regardless of the lto
-            // settings.
-            let needs_lto = needs_lto && module.kind != ModuleKind::Metadata;
+    if needs_lto {
+        Ok(WorkItemResult::NeedsLTO(module))
+    } else {
+        let module = unsafe {
+            codegen(cgcx, &diag_handler, module, module_config, timeline)?
+        };
+        Ok(WorkItemResult::Compiled(module))
+    }
+}
 
-            if needs_lto {
-                Ok(WorkItemResult::NeedsLTO(module))
-            } else {
-                let module = codegen(cgcx, &diag_handler, module, config, timeline)?;
-                Ok(WorkItemResult::Compiled(module))
+fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
+                                     module: CachedModuleCodegen,
+                                     module_config: &ModuleConfig,
+                                     _: &mut Timeline)
+    -> Result<WorkItemResult, FatalError>
+{
+    let incr_comp_session_dir = cgcx.incr_comp_session_dir
+                                    .as_ref()
+                                    .unwrap();
+    let mut object = None;
+    let mut bytecode = None;
+    let mut bytecode_compressed = None;
+    for (kind, saved_file) in &module.source.saved_files {
+        let obj_out = match kind {
+            WorkProductFileKind::Object => {
+                let path = cgcx.output_filenames.temp_path(OutputType::Object,
+                                                           Some(&module.name));
+                object = Some(path.clone());
+                path
+            }
+            WorkProductFileKind::Bytecode => {
+                let path = cgcx.output_filenames.temp_path(OutputType::Bitcode,
+                                                           Some(&module.name));
+                bytecode = Some(path.clone());
+                path
+            }
+            WorkProductFileKind::BytecodeCompressed => {
+                let path = cgcx.output_filenames.temp_path(OutputType::Bitcode,
+                                                           Some(&module.name))
+                    .with_extension(RLIB_BYTECODE_EXTENSION);
+                bytecode_compressed = Some(path.clone());
+                path
+            }
+        };
+        let source_file = in_incr_comp_dir(&incr_comp_session_dir,
+                                           &saved_file);
+        debug!("copying pre-existing module `{}` from {:?} to {}",
+               module.name,
+               source_file,
+               obj_out.display());
+        match link_or_copy(&source_file, &obj_out) {
+            Ok(_) => { }
+            Err(err) => {
+                let diag_handler = cgcx.create_diag_handler();
+                diag_handler.err(&format!("unable to copy {} to {}: {}",
+                                          source_file.display(),
+                                          obj_out.display(),
+                                          err));
             }
         }
     }
+
+    assert_eq!(object.is_some(), module_config.emit_obj);
+    assert_eq!(bytecode.is_some(), module_config.emit_bc);
+    assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);
+
+    Ok(WorkItemResult::Compiled(CompiledModule {
+        name: module.name,
+        kind: ModuleKind::Regular,
+        object,
+        bytecode,
+        bytecode_compressed,
+    }))
+}
+
+fn execute_lto_work_item(cgcx: &CodegenContext,
+                         mut module: lto::LtoModuleCodegen,
+                         module_config: &ModuleConfig,
+                         timeline: &mut Timeline)
+    -> Result<WorkItemResult, FatalError>
+{
+    let diag_handler = cgcx.create_diag_handler();
+
+    unsafe {
+        let module = module.optimize(cgcx, timeline)?;
+        let module = codegen(cgcx, &diag_handler, module, module_config, timeline)?;
+        Ok(WorkItemResult::Compiled(module))
+    }
 }
 
 enum Message {
@@ -1424,6 +1498,10 @@ enum Message {
         llvm_work_item: WorkItem,
         cost: u64,
     },
+    AddImportOnlyModule {
+        module_data: SerializedModule,
+        work_product: WorkProduct,
+    },
     CodegenComplete,
     CodegenItem,
 }
@@ -1703,6 +1781,7 @@ fn start_executing_work(tcx: TyCtxt,
         let mut compiled_metadata_module = None;
         let mut compiled_allocator_module = None;
         let mut needs_lto = Vec::new();
+        let mut lto_import_only_modules = Vec::new();
         let mut started_lto = false;
 
         // This flag tracks whether all items have gone through codegens
@@ -1726,6 +1805,7 @@ fn start_executing_work(tcx: TyCtxt,
               work_items.len() > 0 ||
               running > 0 ||
               needs_lto.len() > 0 ||
+              lto_import_only_modules.len() > 0 ||
               main_thread_worker_state != MainThreadWorkerState::Idle {
 
             // While there are still CGUs to be codegened, the coordinator has
@@ -1749,7 +1829,7 @@ fn start_executing_work(tcx: TyCtxt,
                             worker: get_worker_id(&mut free_worker_ids),
                             .. cgcx.clone()
                         };
-                        maybe_start_llvm_timer(cgcx.config(item.kind()),
+                        maybe_start_llvm_timer(cgcx.config(item.module_kind()),
                                                &mut llvm_start_time);
                         main_thread_worker_state = MainThreadWorkerState::LLVMing;
                         spawn_work(cgcx, item);
@@ -1765,10 +1845,12 @@ fn start_executing_work(tcx: TyCtxt,
                    running == 0 &&
                    main_thread_worker_state == MainThreadWorkerState::Idle {
                     assert!(!started_lto);
-                    assert!(needs_lto.len() > 0);
+                    assert!(needs_lto.len() + lto_import_only_modules.len() > 0);
                     started_lto = true;
                     let modules = mem::replace(&mut needs_lto, Vec::new());
-                    for (work, cost) in generate_lto_work(&cgcx, modules) {
+                    let import_only_modules =
+                        mem::replace(&mut lto_import_only_modules, Vec::new());
+                    for (work, cost) in generate_lto_work(&cgcx, modules, import_only_modules) {
                         let insertion_index = work_items
                             .binary_search_by_key(&cost, |&(_, cost)| cost)
                             .unwrap_or_else(|e| e);
@@ -1789,7 +1871,7 @@ fn start_executing_work(tcx: TyCtxt,
                                 worker: get_worker_id(&mut free_worker_ids),
                                 .. cgcx.clone()
                             };
-                            maybe_start_llvm_timer(cgcx.config(item.kind()),
+                            maybe_start_llvm_timer(cgcx.config(item.module_kind()),
                                                    &mut llvm_start_time);
                             main_thread_worker_state = MainThreadWorkerState::LLVMing;
                             spawn_work(cgcx, item);
@@ -1820,7 +1902,7 @@ fn start_executing_work(tcx: TyCtxt,
             while work_items.len() > 0 && running < tokens.len() {
                 let (item, _) = work_items.pop().unwrap();
 
-                maybe_start_llvm_timer(cgcx.config(item.kind()),
+                maybe_start_llvm_timer(cgcx.config(item.module_kind()),
                                        &mut llvm_start_time);
 
                 let cgcx = CodegenContext {
@@ -1932,10 +2014,17 @@ fn start_executing_work(tcx: TyCtxt,
                     } else {
                         running -= 1;
                     }
-
                     free_worker_ids.push(worker_id);
                     needs_lto.push(result);
                 }
+                Message::AddImportOnlyModule { module_data, work_product } => {
+                    assert!(!started_lto);
+                    assert!(!codegen_done);
+                    assert_eq!(main_thread_worker_state,
+                               MainThreadWorkerState::Codegenning);
+                    lto_import_only_modules.push((module_data, work_product));
+                    main_thread_worker_state = MainThreadWorkerState::Idle;
+                }
                 Message::Done { result: Err(()), worker_id: _ } => {
                     shared_emitter.fatal("aborting due to worker thread failure");
                     // Exit the coordinator thread
@@ -2308,9 +2397,9 @@ pub(crate) fn join(
             time_graph.dump(&format!("{}-timings", self.crate_name));
         }
 
-        let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess,
-                                                                             &compiled_modules);
-
+        let work_products =
+            copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess,
+                                                             &compiled_modules);
         produce_final_output_artifacts(sess,
                                        &compiled_modules,
                                        &self.output_filenames);
@@ -2371,8 +2460,8 @@ pub fn wait_for_signal_to_codegen_item(&self) {
 }
 
 pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
-                                               module: ModuleCodegen,
-                                               cost: u64) {
+                                              module: ModuleCodegen,
+                                              cost: u64) {
     let llvm_work_item = WorkItem::Optimize(module);
     drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone {
         llvm_work_item,
@@ -2380,6 +2469,40 @@ pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
     })));
 }
 
+pub(crate) fn submit_post_lto_module_to_llvm(tcx: TyCtxt,
+                                             module: CachedModuleCodegen) {
+    let llvm_work_item = WorkItem::CopyPostLtoArtifacts(module);
+    drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone {
+        llvm_work_item,
+        cost: 0,
+    })));
+}
+
+pub(crate) fn submit_pre_lto_module_to_llvm(tcx: TyCtxt,
+                                            module: CachedModuleCodegen) {
+    let filename = pre_lto_bitcode_filename(&module.name);
+    let bc_path = in_incr_comp_dir_sess(tcx.sess, &filename);
+    let file = fs::File::open(&bc_path).unwrap_or_else(|e| {
+        panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e)
+    });
+
+    let mmap = unsafe {
+        memmap::Mmap::map(&file).unwrap_or_else(|e| {
+            panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e)
+        })
+    };
+
+    // Schedule the module to be loaded
+    drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::AddImportOnlyModule {
+        module_data: SerializedModule::FromUncompressedFile(mmap),
+        work_product: module.source,
+    })));
+}
+
+pub(super) fn pre_lto_bitcode_filename(module_name: &str) -> String {
+    format!("{}.{}", module_name, PRE_THIN_LTO_BC_EXT)
+}
+
 fn msvc_imps_needed(tcx: TyCtxt) -> bool {
     // This should never be true (because it's not supported). If it is true,
     // something is wrong with commandline arg validation.
index 009c6da9d8d15a35f0bf60cbf96cb09834940e52..c1f6006e684be595bdcaabae0eb29f22c5209f40 100644 (file)
@@ -24,9 +24,9 @@
 //!     int) and rec(x=int, y=int, z=int) will have the same llvm::Type.
 
 use super::ModuleLlvm;
-use super::ModuleSource;
 use super::ModuleCodegen;
 use super::ModuleKind;
+use super::CachedModuleCodegen;
 
 use abi;
 use back::write::{self, OngoingCodegen};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
 use rustc::ty::query::Providers;
-use rustc::dep_graph::{DepNode, DepConstructor};
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::middle::exported_symbols;
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::util::profiling::ProfileCategory;
-use rustc::session::config::{self, DebugInfo, EntryFnType};
+use rustc::session::config::{self, DebugInfo, EntryFnType, Lto};
 use rustc::session::Session;
 use rustc_incremental;
 use allocator;
@@ -698,6 +697,50 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> {
     }
 }
 
+#[derive(Debug)]
+enum CguReUsable {
+    PreLto,
+    PostLto,
+    No
+}
+
+fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 cgu: &CodegenUnit<'tcx>)
+                                 -> CguReUsable {
+    if !tcx.dep_graph.is_fully_enabled() {
+        return CguReUsable::No
+    }
+
+    let work_product_id = &cgu.work_product_id();
+    if tcx.dep_graph.previous_work_product(work_product_id).is_none() {
+        // We don't have anything cached for this CGU. This can happen
+        // if the CGU did not exist in the previous session.
+        return CguReUsable::No
+    }
+
+    // Try to mark the CGU as green. If it we can do so, it means that nothing
+    // affecting the LLVM module has changed and we can re-use a cached version.
+    // If we compile with any kind of LTO, this means we can re-use the bitcode
+    // of the Pre-LTO stage (possibly also the Post-LTO version but we'll only
+    // know that later). If we are not doing LTO, there is only one optimized
+    // version of each module, so we re-use that.
+    let dep_node = cgu.codegen_dep_node(tcx);
+    assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
+        "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
+        cgu.name());
+
+    if tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() {
+        // We can re-use either the pre- or the post-thinlto state
+        if tcx.sess.lto() != Lto::No {
+            CguReUsable::PreLto
+        } else {
+            CguReUsable::PostLto
+        }
+    } else {
+        CguReUsable::No
+    }
+}
+
 pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              rx: mpsc::Receiver<Box<dyn Any + Send>>)
                              -> OngoingCodegen {
@@ -734,7 +777,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let metadata_module = ModuleCodegen {
         name: metadata_cgu_name,
-        source: ModuleSource::Codegened(metadata_llvm_module),
+        module_llvm: metadata_llvm_module,
         kind: ModuleKind::Metadata,
     };
 
@@ -823,7 +866,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         Some(ModuleCodegen {
             name: llmod_id,
-            source: ModuleSource::Codegened(modules),
+            module_llvm: modules,
             kind: ModuleKind::Allocator,
         })
     } else {
@@ -851,48 +894,40 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ongoing_codegen.wait_for_signal_to_codegen_item();
         ongoing_codegen.check_for_errors(tcx.sess);
 
-        // First, if incremental compilation is enabled, we try to re-use the
-        // codegen unit from the cache.
-        if tcx.dep_graph.is_fully_enabled() {
-            let cgu_id = cgu.work_product_id();
-
-            // Check whether there is a previous work-product we can
-            // re-use.  Not only must the file exist, and the inputs not
-            // be dirty, but the hash of the symbols we will generate must
-            // be the same.
-            if let Some(buf) = tcx.dep_graph.previous_work_product(&cgu_id) {
-                let dep_node = &DepNode::new(tcx,
-                    DepConstructor::CompileCodegenUnit(cgu.name().clone()));
-
-                // We try to mark the DepNode::CompileCodegenUnit green. If we
-                // succeed it means that none of the dependencies has changed
-                // and we can safely re-use.
-                if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, dep_node) {
-                    let module = ModuleCodegen {
-                        name: cgu.name().to_string(),
-                        source: ModuleSource::Preexisting(buf),
-                        kind: ModuleKind::Regular,
-                    };
-                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
-                    write::submit_codegened_module_to_llvm(tcx, module, 0);
-                    // Continue to next cgu, this one is done.
-                    continue
-                }
-            } else {
-                // This can happen if files were  deleted from the cache
-                // directory for some reason. We just re-compile then.
+        let loaded_from_cache = match determine_cgu_reuse(tcx, &cgu) {
+            CguReUsable::No => {
+                let _timing_guard = time_graph.as_ref().map(|time_graph| {
+                    time_graph.start(write::CODEGEN_WORKER_TIMELINE,
+                                     write::CODEGEN_WORK_PACKAGE_KIND,
+                                     &format!("codegen {}", cgu.name()))
+                });
+                let start_time = Instant::now();
+                let stats = compile_codegen_unit(tcx, *cgu.name());
+                all_stats.extend(stats);
+                total_codegen_time += start_time.elapsed();
+                false
             }
-        }
+            CguReUsable::PreLto => {
+                write::submit_pre_lto_module_to_llvm(tcx, CachedModuleCodegen {
+                    name: cgu.name().to_string(),
+                    source: cgu.work_product(tcx),
+                });
+                true
+            }
+            CguReUsable::PostLto => {
+                write::submit_post_lto_module_to_llvm(tcx, CachedModuleCodegen {
+                    name: cgu.name().to_string(),
+                    source: cgu.work_product(tcx),
+                });
+                true
+            }
+        };
 
-        let _timing_guard = time_graph.as_ref().map(|time_graph| {
-            time_graph.start(write::CODEGEN_WORKER_TIMELINE,
-                             write::CODEGEN_WORK_PACKAGE_KIND,
-                             &format!("codegen {}", cgu.name()))
-        });
-        let start_time = Instant::now();
-        all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
-        total_codegen_time += start_time.elapsed();
-        ongoing_codegen.check_for_errors(tcx.sess);
+        if tcx.dep_graph.is_fully_enabled() {
+            let dep_node = cgu.codegen_dep_node(tcx);
+            let dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
+            tcx.dep_graph.mark_loaded_from_cache(dep_node_index, loaded_from_cache);
+        }
     }
 
     ongoing_codegen.codegen_finished(tcx);
@@ -1156,11 +1191,15 @@ fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool {
 }
 
 fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  cgu: InternedString) -> Stats {
-    let cgu = tcx.codegen_unit(cgu);
-
+                                  cgu_name: InternedString)
+                                  -> Stats {
     let start_time = Instant::now();
-    let (stats, module) = module_codegen(tcx, cgu);
+
+    let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
+    let ((stats, module), _) = tcx.dep_graph.with_task(dep_node,
+                                                       tcx,
+                                                       cgu_name,
+                                                       module_codegen);
     let time_to_codegen = start_time.elapsed();
 
     // We assume that the cost to run LLVM on a CGU is proportional to
@@ -1169,23 +1208,23 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                time_to_codegen.subsec_nanos() as u64;
 
     write::submit_codegened_module_to_llvm(tcx,
-                                            module,
-                                            cost);
+                                           module,
+                                           cost);
     return stats;
 
     fn module_codegen<'a, 'tcx>(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        cgu: Arc<CodegenUnit<'tcx>>)
+        cgu_name: InternedString)
         -> (Stats, ModuleCodegen)
     {
-        let cgu_name = cgu.name().to_string();
+        let cgu = tcx.codegen_unit(cgu_name);
 
         // Instantiate monomorphizations without filling out definitions yet...
-        let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name);
+        let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name.as_str());
         let stats = {
             let cx = CodegenCx::new(tcx, cgu, &llvm_module);
             let mono_items = cx.codegen_unit
-                                 .items_in_deterministic_order(cx.tcx);
+                               .items_in_deterministic_order(cx.tcx);
             for &(mono_item, (linkage, visibility)) in &mono_items {
                 mono_item.predefine(&cx, linkage, visibility);
             }
@@ -1234,8 +1273,8 @@ fn module_codegen<'a, 'tcx>(
         };
 
         (stats, ModuleCodegen {
-            name: cgu_name,
-            source: ModuleSource::Codegened(llvm_module),
+            name: cgu_name.to_string(),
+            module_llvm: llvm_module,
             kind: ModuleKind::Regular,
         })
     }
@@ -1254,7 +1293,6 @@ pub fn provide(providers: &mut Providers) {
             .cloned()
             .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
     };
-    providers.compile_codegen_unit = compile_codegen_unit;
 
     provide_extern(providers);
 }
index 31eeb5633fba9c020c4b49860ec900606f11caa0..dcdd8c1f6e9f99a5c2848af27fba61feaaaa8789 100644 (file)
 extern crate serialize;
 extern crate cc; // Used to locate MSVC
 extern crate tempfile;
+extern crate memmap;
 
 use back::bytecode::RLIB_BYTECODE_EXTENSION;
 
 pub use llvm_util::target_features;
-
 use std::any::Any;
-use std::path::PathBuf;
+use std::path::{PathBuf};
 use std::sync::mpsc;
 use rustc_data_structures::sync::Lrc;
 
@@ -100,7 +100,7 @@ mod back {
     mod command;
     pub mod linker;
     pub mod link;
-    mod lto;
+    pub mod lto;
     pub mod symbol_export;
     pub mod write;
     mod rpath;
@@ -273,10 +273,15 @@ struct ModuleCodegen {
     /// as the crate name and disambiguator.
     /// We currently generate these names via CodegenUnit::build_cgu_name().
     name: String,
-    source: ModuleSource,
+    module_llvm: ModuleLlvm,
     kind: ModuleKind,
 }
 
+struct CachedModuleCodegen {
+    name: String,
+    source: WorkProduct,
+}
+
 #[derive(Copy, Clone, Debug, PartialEq)]
 enum ModuleKind {
     Regular,
@@ -285,22 +290,11 @@ enum ModuleKind {
 }
 
 impl ModuleCodegen {
-    fn llvm(&self) -> Option<&ModuleLlvm> {
-        match self.source {
-            ModuleSource::Codegened(ref llvm) => Some(llvm),
-            ModuleSource::Preexisting(_) => None,
-        }
-    }
-
     fn into_compiled_module(self,
-                                emit_obj: bool,
-                                emit_bc: bool,
-                                emit_bc_compressed: bool,
-                                outputs: &OutputFilenames) -> CompiledModule {
-        let pre_existing = match self.source {
-            ModuleSource::Preexisting(_) => true,
-            ModuleSource::Codegened(_) => false,
-        };
+                            emit_obj: bool,
+                            emit_bc: bool,
+                            emit_bc_compressed: bool,
+                            outputs: &OutputFilenames) -> CompiledModule {
         let object = if emit_obj {
             Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
         } else {
@@ -321,7 +315,6 @@ fn into_compiled_module(self,
         CompiledModule {
             name: self.name.clone(),
             kind: self.kind,
-            pre_existing,
             object,
             bytecode,
             bytecode_compressed,
@@ -333,20 +326,11 @@ fn into_compiled_module(self,
 struct CompiledModule {
     name: String,
     kind: ModuleKind,
-    pre_existing: bool,
     object: Option<PathBuf>,
     bytecode: Option<PathBuf>,
     bytecode_compressed: Option<PathBuf>,
 }
 
-enum ModuleSource {
-    /// Copy the `.o` files or whatever from the incr. comp. directory.
-    Preexisting(WorkProduct),
-
-    /// Rebuild from this LLVM module.
-    Codegened(ModuleLlvm),
-}
-
 struct ModuleLlvm {
     llcx: &'static mut llvm::Context,
     llmod_raw: *const llvm::Module,
index 51b0299e63f46c57eff8199809d3595ccb963716..6c2601bf1ef1255ec229b6533da9b8290bbd55dc 100644 (file)
@@ -363,6 +363,10 @@ pub enum PassKind {
 /// LLVMRustThinLTOBuffer
 extern { pub type ThinLTOBuffer; }
 
+// LLVMRustModuleNameCallback
+pub type ThinLTOModuleNameCallback =
+    unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char);
+
 /// LLVMRustThinLTOModule
 #[repr(C)]
 pub struct ThinLTOModule {
@@ -1622,6 +1626,11 @@ pub fn LLVMRustPrepareThinLTOImport(
         Data: &ThinLTOData,
         Module: &Module,
     ) -> bool;
+    pub fn LLVMRustGetThinLTOModuleImports(
+        Data: *const ThinLTOData,
+        ModuleNameCallback: ThinLTOModuleNameCallback,
+        CallbackPayload: *mut c_void,
+    );
     pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData);
     pub fn LLVMRustParseBitcodeForThinLTO(
         Context: &Context,
index 9fcc33d82cfa4d1ea751db891308dc3680eda081..9e8ff2047036bc6767fe75c04dd97a57f81648ef 100644 (file)
@@ -86,10 +86,14 @@ unsafe fn configure_llvm(sess: &Session) {
 // array, leading to crashes.
 
 const ARM_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("aclass", Some("arm_target_feature")),
     ("mclass", Some("arm_target_feature")),
     ("rclass", Some("arm_target_feature")),
     ("dsp", Some("arm_target_feature")),
     ("neon", Some("arm_target_feature")),
+    ("v5te", Some("arm_target_feature")),
+    ("v6k", Some("arm_target_feature")),
+    ("v6t2", Some("arm_target_feature")),
     ("v7", Some("arm_target_feature")),
     ("vfp2", Some("arm_target_feature")),
     ("vfp3", Some("arm_target_feature")),
@@ -173,6 +177,7 @@ unsafe fn configure_llvm(sess: &Session) {
 
 const WASM_WHITELIST: &[(&str, Option<&str>)] = &[
     ("simd128", Some("wasm_target_feature")),
+    ("atomics", Some("wasm_target_feature")),
 ];
 
 /// When rustdoc is running, provide a list of all known features so that all their respective
index 342c7d1b67866b73573050a2bda970a2cb6b216b..b8e494e4040ec829e52baa89347883c04a287e7a 100644 (file)
@@ -22,3 +22,4 @@ crate-type = ["dylib"]
 [dependencies]
 bitflags = "1.0"
 log = "0.4"
+unicode-width = "0.1.4"
index 481f2f54c5e44abbc9aa322bb6a3854189a1b32a..ebceb00cca8b0b72c7a65bc4af1f944cdc62e170 100644 (file)
@@ -16,3 +16,4 @@
 
 extern crate bitflags;
 extern crate log;
+extern crate unicode_width;
index 0376cf8115756bf43e89d0d2c31d61df566ae25f..5a72fde6a2c8a1d917fb3d6d1efebf12a31084ae 100644 (file)
@@ -22,5 +22,5 @@ rustc-hash = "1.0.1"
 smallvec = { version = "0.6.5", features = ["union"] }
 
 [dependencies.parking_lot]
-version = "0.5"
+version = "0.6"
 features = ["nightly"]
index 3f248dadb66c14b02a556996ffacc77abb4a29bd..f10a9a68bed5b3a73d2354b2e6a2e61b34572fd5 100644 (file)
@@ -239,7 +239,7 @@ fn drop(&mut self) {
 }
 
 #[cfg(windows)]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod imp {
     use std::io;
     use std::mem;
index b72d011c99bad9ea84a98c35e9f368c29d888799..26cc2c9f17cfbd57dba41abe1cdc796fb6022e4b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use fx::FxHashMap;
 use std::cmp::max;
 use std::slice;
 use std::iter;
@@ -18,8 +18,8 @@
 pub struct TestGraph {
     num_nodes: usize,
     start_node: usize,
-    successors: HashMap<usize, Vec<usize>>,
-    predecessors: HashMap<usize, Vec<usize>>,
+    successors: FxHashMap<usize, Vec<usize>>,
+    predecessors: FxHashMap<usize, Vec<usize>>,
 }
 
 impl TestGraph {
@@ -27,8 +27,8 @@ pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self {
         let mut graph = TestGraph {
             num_nodes: start_node + 1,
             start_node,
-            successors: HashMap::new(),
-            predecessors: HashMap::new(),
+            successors: FxHashMap::default(),
+            predecessors: FxHashMap::default(),
         };
         for &(source, target) in edges {
             graph.num_nodes = max(graph.num_nodes, source + 1);
index 1024e69cc2b0e889b67d74b35ad75fbfba58240e..c70a0abe8c7e437e5ed2f92aac748d6dca74b1b3 100644 (file)
@@ -281,6 +281,23 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
+     where T1: HashStable<CTX>,
+           T2: HashStable<CTX>,
+           T3: HashStable<CTX>,
+           T4: HashStable<CTX>,
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let (ref _0, ref _1, ref _2, ref _3) = *self;
+        _0.hash_stable(ctx, hasher);
+        _1.hash_stable(ctx, hasher);
+        _2.hash_stable(ctx, hasher);
+        _3.hash_stable(ctx, hasher);
+    }
+}
+
 impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
     default fn hash_stable<W: StableHasherResult>(&self,
                                                   ctx: &mut CTX,
index 6989cdc0a9a15afaf1e545cb3a10068f918d40b5..a2893a60cb680722c7e8eea40268f06dd767d93d 100644 (file)
@@ -93,8 +93,11 @@ pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
         pub use std::rc::Rc as Lrc;
         pub use std::rc::Weak as Weak;
         pub use std::cell::Ref as ReadGuard;
+        pub use std::cell::Ref as MappedReadGuard;
         pub use std::cell::RefMut as WriteGuard;
+        pub use std::cell::RefMut as MappedWriteGuard;
         pub use std::cell::RefMut as LockGuard;
+        pub use std::cell::RefMut as MappedLockGuard;
 
         use std::cell::RefCell as InnerRwLock;
         use std::cell::RefCell as InnerLock;
@@ -213,9 +216,12 @@ pub fn take(&self) -> Option<T> {
         pub use std::marker::Sync as Sync;
 
         pub use parking_lot::RwLockReadGuard as ReadGuard;
+        pub use parking_lot::MappedRwLockReadGuard as MappedReadGuard;
         pub use parking_lot::RwLockWriteGuard as WriteGuard;
+        pub use parking_lot::MappedRwLockWriteGuard as MappedWriteGuard;
 
         pub use parking_lot::MutexGuard as LockGuard;
+        pub use parking_lot::MappedMutexGuard as MappedLockGuard;
 
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
index 1c2c0ad73a89751a587904d666bdeead2e19a3df..d27b0856c1533358ba39d074ebc286d1b85a1239 100644 (file)
@@ -828,7 +828,6 @@ pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>(
     let (mut krate, features) = syntax::config::features(
         krate,
         &sess.parse_sess,
-        sess.opts.test,
         sess.edition(),
     );
     // these need to be set "early" so that expansion sees `quote` if enabled.
@@ -924,8 +923,8 @@ pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>(
             ls.register_late_pass(Some(sess), true, pass);
         }
 
-        for (name, to) in lint_groups {
-            ls.register_group(Some(sess), true, name, to);
+        for (name, (to, deprecated_name)) in lint_groups {
+            ls.register_group(Some(sess), true, name, deprecated_name, to);
         }
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
index 56cb3e9dbb829feacb179ebc2aa59b98e717f261..e329b037d22aafce284a8e8337467d9fb7fe863e 100644 (file)
 
 use super::*;
 use syntax_pos::SpanData;
+use rustc_data_structures::fx::FxHashMap;
 use rustc::util::common::QueryMsg;
 use std::fs::File;
 use std::time::{Duration, Instant};
-use std::collections::hash_map::HashMap;
 use rustc::dep_graph::{DepNode};
 
 #[derive(Debug, Clone, Eq, PartialEq)]
@@ -149,7 +149,7 @@ fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usi
     }
 }
 
-fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &[Rec]) {
+fn compute_counts_rec(counts: &mut FxHashMap<String,QueryMetric>, traces: &[Rec]) {
     for t in traces.iter() {
         match t.effect {
             Effect::TimeBegin(ref msg) => {
@@ -200,7 +200,7 @@ fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &[Rec])
     }
 }
 
-pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) {
+pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap<String,QueryMetric>) {
     use rustc::util::common::duration_to_secs_str;
     use std::cmp::Reverse;
 
@@ -219,7 +219,7 @@ pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetr
 
 pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) {
     let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len());
-    let mut counts : HashMap<String, QueryMetric> = HashMap::with_capacity(capacity);
+    let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
     compute_counts_rec(&mut counts, traces);
     write_counts(counts_file, &mut counts);
 
index e412d1749d1b2608c880d317c920c9caf23bd177..101ca0650c8a4247d281eb8d06534c52c3105b99 100644 (file)
@@ -12,6 +12,7 @@ crate-type = ["dylib"]
 serialize = { path = "../libserialize" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 unicode-width = "0.1.4"
 atty = "0.2"
-termcolor = "0.3"
+termcolor = "1.0"
index c08cf3d039df53ec68a345d97fe86911924395f6..5f275b700387360eaec802315d1fffc30a726853 100644 (file)
 use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use styled_buffer::StyledBuffer;
 
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use atty;
 use std::borrow::Cow;
 use std::io::prelude::*;
 use std::io;
-use std::collections::HashMap;
 use std::cmp::{min, Reverse};
 use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter};
 use termcolor::{WriteColor, Color, Buffer};
@@ -1090,7 +1090,7 @@ fn emit_message_default(&mut self,
                                             max_line_num_len + 1);
 
                 // Contains the vertical lines' positions for active multiline annotations
-                let mut multilines = HashMap::new();
+                let mut multilines = FxHashMap::default();
 
                 // Next, output the annotate source for this file
                 for line_idx in 0..annotated_file.lines.len() {
@@ -1109,7 +1109,7 @@ fn emit_message_default(&mut self,
                                                          width_offset,
                                                          code_offset);
 
-                    let mut to_add = HashMap::new();
+                    let mut to_add = FxHashMap::default();
 
                     for (depth, style) in depths {
                         if multilines.get(&depth).is_some() {
index dff8d53986db598a204fba5e6c32b355e8bc71cb..e5baf93b00064abf32a50b65f3cd1ea70a0de1af 100644 (file)
@@ -22,7 +22,7 @@
 use std::any::Any;
 
 #[cfg(windows)]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
     use std::ffi::CString;
     use std::io;
index 83737681471e2f6fd9e1db306940e9aee0f9ce60..9a2302171bab3fe8fb222e22f875b15c6f9526f7 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 
 #[derive(Clone)]
 pub struct Registry {
-    descriptions: HashMap<&'static str, &'static str>,
+    descriptions: FxHashMap<&'static str, &'static str>,
 }
 
 impl Registry {
index c3f6062e799d96b6b3628363820df819922c5f7e..b8519ee1ab1a5bff1c839d55e4bb8d2db46abd6e 100644 (file)
@@ -11,7 +11,7 @@ crate-type = ["dylib"]
 [dependencies]
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
-rand = "0.4"
+rand = "0.5"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
index 9b8e2c450d5f835187a37d4bb7feb6dca7fd6188..139159c16395bed9f25718156eb7db36ca56f153 100644 (file)
@@ -89,7 +89,7 @@ fn check_attr(&self, attr: &ast::Attribute) {
             (&user_path[..], None)
         };
 
-        let mut cgu_path_components = user_path.split("-").collect::<Vec<_>>();
+        let mut cgu_path_components = user_path.split('-').collect::<Vec<_>>();
 
         // Remove the crate name
         assert_eq!(cgu_path_components.remove(0), crate_name);
index e100b49c7f244242141a2070cc83c812e7dd9efa..4ffd726c1d47ce2b5aba82c21f2e403fdcc28992 100644 (file)
@@ -44,6 +44,7 @@
 pub use persist::save_dep_graph;
 pub use persist::save_work_product_index;
 pub use persist::in_incr_comp_dir;
+pub use persist::in_incr_comp_dir_sess;
 pub use persist::prepare_session_directory;
 pub use persist::finalize_session_directory;
 pub use persist::delete_workproduct_files;
index f715057541ffaa7476ef5ff2f49424344b8f7cd6..1b3819474c22e6b8e4a3f8ce6ffc49c89ce9d705 100644 (file)
@@ -24,7 +24,6 @@
 //! the required condition is not met.
 //!
 
-use std::collections::HashSet;
 use std::iter::FromIterator;
 use std::vec::Vec;
 use rustc::dep_graph::{DepNode, label_strs};
 //
 //     TypeOfItem for these.
 
-type Labels = HashSet<String>;
+type Labels = FxHashSet<String>;
 
 /// Represents the requested configuration by rustc_clean/dirty
 struct Assertion {
@@ -205,13 +204,13 @@ impl Assertion {
     fn from_clean_labels(labels: Labels) -> Assertion {
         Assertion {
             clean: labels,
-            dirty: Labels::new(),
+            dirty: Labels::default(),
         }
     }
 
     fn from_dirty_labels(labels: Labels) -> Assertion {
         Assertion {
-            clean: Labels::new(),
+            clean: Labels::default(),
             dirty: labels,
         }
     }
@@ -328,7 +327,7 @@ fn except(&self, attr: &Attribute) -> Labels {
             }
         }
         // if no `label` or `except` is given, only the node's group are asserted
-        Labels::new()
+        Labels::default()
     }
 
     /// Return all DepNode labels that should be asserted for this item.
@@ -436,7 +435,7 @@ fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static s
     }
 
     fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels {
-        let mut out: Labels = HashSet::new();
+        let mut out = Labels::default();
         for label in value.split(',') {
             let label = label.trim();
             if DepNode::has_label_string(label) {
index 28d53dc7fb3c47a1fe5d2fa5406c1bb60a8b6622..ec25aef8080593800aea6305b4bfff01546a2764 100644 (file)
 use std::path::{Path, PathBuf};
 use std::time::{UNIX_EPOCH, SystemTime, Duration};
 
-use rand::{thread_rng, Rng};
+use rand::{RngCore, thread_rng};
 
 const LOCK_FILE_EXT: &'static str = ".lock";
 const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
index e1f00db56d5cbc0572214a3a15d94941e7a8b09e..17d36ba3fa7f4bbbd2051ae78b26fcce1e62df99 100644 (file)
@@ -23,6 +23,7 @@
 pub use self::fs::finalize_session_directory;
 pub use self::fs::garbage_collect_session_directories;
 pub use self::fs::in_incr_comp_dir;
+pub use self::fs::in_incr_comp_dir_sess;
 pub use self::fs::prepare_session_directory;
 pub use self::load::dep_graph_tcx_init;
 pub use self::load::load_dep_graph;
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
deleted file mode 100644 (file)
index 09871c0..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::hir::def::Def;
-use rustc::ty;
-use lint::{LateContext, LintContext, LintArray};
-use lint::{LintPass, LateLintPass};
-
-use rustc_target::spec::abi::Abi;
-use syntax::ast;
-use syntax::attr;
-use syntax_pos::Span;
-
-use rustc::hir::{self, GenericParamKind, PatKind};
-use rustc::hir::intravisit::FnKind;
-
-#[derive(PartialEq)]
-pub enum MethodLateContext {
-    TraitAutoImpl,
-    TraitImpl,
-    PlainImpl,
-}
-
-pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext {
-    let def_id = cx.tcx.hir.local_def_id(id);
-    let item = cx.tcx.associated_item(def_id);
-    match item.container {
-        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
-        ty::ImplContainer(cid) => {
-            match cx.tcx.impl_trait_ref(cid) {
-                Some(_) => MethodLateContext::TraitImpl,
-                None => MethodLateContext::PlainImpl,
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_CAMEL_CASE_TYPES,
-    Warn,
-    "types, variants, traits and type parameters should have camel case names"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
-
-impl NonCamelCaseTypes {
-    fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
-        fn char_has_case(c: char) -> bool {
-            c.is_lowercase() || c.is_uppercase()
-        }
-
-        fn is_camel_case(name: ast::Name) -> bool {
-            let name = name.as_str();
-            if name.is_empty() {
-                return true;
-            }
-            let name = name.trim_matches('_');
-
-            // start with a non-lowercase letter rather than non-uppercase
-            // ones (some scripts don't have a concept of upper/lowercase)
-            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
-                !name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
-                    // contains a capitalisable character followed by, or preceded by, an underscore
-                    char_has_case(pair[0]) && pair[1] == '_' ||
-                    char_has_case(pair[1]) && pair[0] == '_'
-                })
-        }
-
-        fn to_camel_case(s: &str) -> String {
-            s.trim_matches('_')
-                .split('_')
-                .map(|word| {
-                    word.chars().enumerate().map(|(i, c)| if i == 0 {
-                        c.to_uppercase().collect::<String>()
-                    } else {
-                        c.to_lowercase().collect()
-                    })
-                    .collect::<String>()
-                })
-                .filter(|x| !x.is_empty())
-                .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
-                    // separate two components with an underscore if their boundary cannot
-                    // be distinguished using a uppercase/lowercase case distinction
-                    let join = if let Some(prev) = prev {
-                                    let l = prev.chars().last().unwrap();
-                                    let f = next.chars().next().unwrap();
-                                    !char_has_case(l) && !char_has_case(f)
-                                } else { false };
-                    (acc + if join { "_" } else { "" } + &next, Some(next))
-                }).0
-        }
-
-        if !is_camel_case(name) {
-            let c = to_camel_case(&name.as_str());
-            let m = if c.is_empty() {
-                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name)
-            } else {
-                format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
-            };
-            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
-        }
-    }
-}
-
-impl LintPass for NonCamelCaseTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        let has_repr_c = it.attrs
-            .iter()
-            .any(|attr| {
-                attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
-                    .iter()
-                    .any(|r| r == &attr::ReprC)
-            });
-
-        if has_repr_c {
-            return;
-        }
-
-        match it.node {
-            hir::ItemKind::Ty(..) |
-            hir::ItemKind::Enum(..) |
-            hir::ItemKind::Struct(..) |
-            hir::ItemKind::Union(..) => self.check_case(cx, "type", it.name, it.span),
-            hir::ItemKind::Trait(..) => self.check_case(cx, "trait", it.name, it.span),
-            _ => (),
-        }
-    }
-
-    fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
-        self.check_case(cx, "variant", v.node.name, v.span);
-    }
-
-    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
-        match param.kind {
-            GenericParamKind::Lifetime { .. } => {}
-            GenericParamKind::Type { synthetic, .. } => {
-                if synthetic.is_none() {
-                    self.check_case(cx, "type parameter", param.name.ident().name, param.span);
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_SNAKE_CASE,
-    Warn,
-    "variables, methods, functions, lifetime parameters and modules should have snake case names"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonSnakeCase;
-
-impl NonSnakeCase {
-    fn to_snake_case(mut str: &str) -> String {
-        let mut words = vec![];
-        // Preserve leading underscores
-        str = str.trim_left_matches(|c: char| {
-            if c == '_' {
-                words.push(String::new());
-                true
-            } else {
-                false
-            }
-        });
-        for s in str.split('_') {
-            let mut last_upper = false;
-            let mut buf = String::new();
-            if s.is_empty() {
-                continue;
-            }
-            for ch in s.chars() {
-                if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
-                    words.push(buf);
-                    buf = String::new();
-                }
-                last_upper = ch.is_uppercase();
-                buf.extend(ch.to_lowercase());
-            }
-            words.push(buf);
-        }
-        words.join("_")
-    }
-
-    fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option<Span>) {
-        fn is_snake_case(ident: &str) -> bool {
-            if ident.is_empty() {
-                return true;
-            }
-            let ident = ident.trim_left_matches('\'');
-            let ident = ident.trim_matches('_');
-
-            let mut allow_underscore = true;
-            ident.chars().all(|c| {
-                allow_underscore = match c {
-                    '_' if !allow_underscore => return false,
-                    '_' => false,
-                    // It would be more obvious to use `c.is_lowercase()`,
-                    // but some characters do not have a lowercase form
-                    c if !c.is_uppercase() => true,
-                    _ => return false,
-                };
-                true
-            })
-        }
-
-        if !is_snake_case(name) {
-            let sc = NonSnakeCase::to_snake_case(name);
-            let msg = if sc != name {
-                format!("{} `{}` should have a snake case name such as `{}`",
-                        sort,
-                        name,
-                        sc)
-            } else {
-                format!("{} `{}` should have a snake case name", sort, name)
-            };
-            match span {
-                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
-                None => cx.lint(NON_SNAKE_CASE, &msg),
-            }
-        }
-    }
-}
-
-impl LintPass for NonSnakeCase {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
-    fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
-        let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name")
-            .and_then(|at| at.value_str().map(|s| (at, s)));
-        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
-            self.check_snake_case(cx, "crate", name, None);
-        } else if let Some((attr, name)) = attr_crate_name {
-            self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span));
-        }
-    }
-
-    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
-        match param.kind {
-            GenericParamKind::Lifetime { .. } => {
-                let name = param.name.ident().as_str();
-                self.check_snake_case(cx, "lifetime", &name, Some(param.span));
-            }
-            GenericParamKind::Type { .. } => {}
-        }
-    }
-
-    fn check_fn(&mut self,
-                cx: &LateContext,
-                fk: FnKind,
-                _: &hir::FnDecl,
-                _: &hir::Body,
-                span: Span,
-                id: ast::NodeId) {
-        match fk {
-            FnKind::Method(name, ..) => {
-                match method_context(cx, id) {
-                    MethodLateContext::PlainImpl => {
-                        self.check_snake_case(cx, "method", &name.as_str(), Some(span))
-                    }
-                    MethodLateContext::TraitAutoImpl => {
-                        self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
-                    }
-                    _ => (),
-                }
-            }
-            FnKind::ItemFn(name, _, header, _, attrs) => {
-                // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
-                if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
-                    return;
-                }
-                self.check_snake_case(cx, "function", &name.as_str(), Some(span))
-            }
-            FnKind::Closure(_) => (),
-        }
-    }
-
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        if let hir::ItemKind::Mod(_) = it.node {
-            self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span));
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
-        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref pnames)) = item.node {
-            self.check_snake_case(cx,
-                                  "trait method",
-                                  &item.ident.as_str(),
-                                  Some(item.span));
-            for param_name in pnames {
-                self.check_snake_case(cx, "variable", &param_name.as_str(), Some(param_name.span));
-            }
-        }
-    }
-
-    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
-        if let &PatKind::Binding(_, _, ref ident, _) = &p.node {
-            self.check_snake_case(cx, "variable", &ident.as_str(), Some(p.span));
-        }
-    }
-
-    fn check_struct_def(&mut self,
-                        cx: &LateContext,
-                        s: &hir::VariantData,
-                        _: ast::Name,
-                        _: &hir::Generics,
-                        _: ast::NodeId) {
-        for sf in s.fields() {
-            self.check_snake_case(cx, "structure field", &sf.ident.as_str(), Some(sf.span));
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_UPPER_CASE_GLOBALS,
-    Warn,
-    "static constants should have uppercase identifiers"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonUpperCaseGlobals;
-
-impl NonUpperCaseGlobals {
-    fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
-        if name.as_str().chars().any(|c| c.is_lowercase()) {
-            let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase();
-            if name != &*uc {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS,
-                             span,
-                             &format!("{} `{}` should have an upper case name such as `{}`",
-                                      sort,
-                                      name,
-                                      uc));
-            } else {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS,
-                             span,
-                             &format!("{} `{}` should have an upper case name", sort, name));
-            }
-        }
-    }
-}
-
-impl LintPass for NonUpperCaseGlobals {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        match it.node {
-            hir::ItemKind::Static(..) => {
-                if attr::find_by_name(&it.attrs, "no_mangle").is_some() {
-                    return;
-                }
-                NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span);
-            }
-            hir::ItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span);
-            }
-            _ => {}
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
-        match ti.node {
-            hir::TraitItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ti.ident.name, ti.span);
-            }
-            _ => {}
-        }
-    }
-
-    fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
-        match ii.node {
-            hir::ImplItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ii.ident.name, ii.span);
-            }
-            _ => {}
-        }
-    }
-
-    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
-        // Lint for constants that look like binding identifiers (#7526)
-        if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
-            if let Def::Const(..) = path.def {
-                if path.segments.len() == 1 {
-                    NonUpperCaseGlobals::check_upper_case(cx,
-                                                          "constant in pattern",
-                                                          path.segments[0].ident.name,
-                                                          path.span);
-                }
-            }
-        }
-    }
-}
index 16aa80c34cc1bcad120bc5307bc46ba2893f2e7a..8ebb181247cfd369599a442887104db3e867db6c 100644 (file)
@@ -39,7 +39,6 @@
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
 
-use std::collections::HashSet;
 use rustc::util::nodemap::FxHashSet;
 
 use syntax::tokenstream::{TokenTree, TokenStream};
@@ -55,7 +54,7 @@
 use rustc::hir::{self, GenericParamKind, PatKind};
 use rustc::hir::intravisit::FnKind;
 
-use bad_style::{MethodLateContext, method_context};
+use nonstandard_style::{MethodLateContext, method_context};
 
 // hardwired lints from librustc
 pub use lint::builtin::*;
@@ -305,14 +304,14 @@ pub struct MissingDoc {
     doc_hidden_stack: Vec<bool>,
 
     /// Private traits or trait items that leaked through. Don't check their methods.
-    private_traits: HashSet<ast::NodeId>,
+    private_traits: FxHashSet<ast::NodeId>,
 }
 
 impl MissingDoc {
     pub fn new() -> MissingDoc {
         MissingDoc {
             doc_hidden_stack: vec![false],
-            private_traits: HashSet::new(),
+            private_traits: FxHashSet::default(),
         }
     }
 
@@ -909,7 +908,7 @@ fn check_fn(&mut self,
         let mut work_queue = vec![cfg.entry];
         let mut reached_exit_without_self_call = false;
         let mut self_call_spans = vec![];
-        let mut visited = HashSet::new();
+        let mut visited = FxHashSet::default();
 
         while let Some(idx) = work_queue.pop() {
             if idx == cfg.exit {
@@ -1836,43 +1835,56 @@ fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
 }
 
 declare_lint! {
-    UNNAMEABLE_TEST_FUNCTIONS,
+    UNNAMEABLE_TEST_ITEMS,
     Warn,
-    "detects an function that cannot be named being marked as #[test]"
+    "detects an item that cannot be named being marked as #[test_case]",
+    report_in_external_macro: true
+}
+
+pub struct UnnameableTestItems {
+    boundary: ast::NodeId, // NodeId of the item under which things are not nameable
+    items_nameable: bool,
 }
 
-pub struct UnnameableTestFunctions;
+impl UnnameableTestItems {
+    pub fn new() -> Self {
+        Self {
+            boundary: ast::DUMMY_NODE_ID,
+            items_nameable: true
+        }
+    }
+}
 
-impl LintPass for UnnameableTestFunctions {
+impl LintPass for UnnameableTestItems {
     fn get_lints(&self) -> LintArray {
-        lint_array!(UNNAMEABLE_TEST_FUNCTIONS)
+        lint_array!(UNNAMEABLE_TEST_ITEMS)
     }
 }
 
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions {
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        match it.node {
-            hir::ItemKind::Fn(..) => {
-                for attr in &it.attrs {
-                    if attr.name() == "test" {
-                        let parent = cx.tcx.hir.get_parent(it.id);
-                        match cx.tcx.hir.find(parent) {
-                            Some(Node::Item(hir::Item {node: hir::ItemKind::Mod(_), ..})) |
-                            None => {}
-                            _ => {
-                                cx.struct_span_lint(
-                                    UNNAMEABLE_TEST_FUNCTIONS,
-                                    attr.span,
-                                    "cannot test inner function",
-                                ).emit();
-                            }
-                        }
-                        break;
-                    }
-                }
+        if self.items_nameable {
+            if let hir::ItemKind::Mod(..) = it.node {}
+            else {
+                self.items_nameable = false;
+                self.boundary = it.id;
             }
-            _ => return,
-        };
+            return;
+        }
+
+        if let Some(attr) = attr::find_by_name(&it.attrs, "rustc_test_marker") {
+            cx.struct_span_lint(
+                UNNAMEABLE_TEST_ITEMS,
+                attr.span,
+                "cannot test inner items",
+            ).emit();
+        }
+    }
+
+    fn check_item_post(&mut self, _cx: &LateContext, it: &hir::Item) {
+        if !self.items_nameable && self.boundary == it.id {
+            self.items_nameable = true;
+        }
     }
 }
 
index 39abfee5fb9ec851c9d99f23817256857c303262..2c32cbdd00f363019a5be05af46a20405fcf79cd 100644 (file)
 use lint::LintId;
 use lint::FutureIncompatibleInfo;
 
-mod bad_style;
+mod nonstandard_style;
 pub mod builtin;
 mod types;
 mod unused;
 
-use bad_style::*;
+use nonstandard_style::*;
 use builtin::*;
 use types::*;
 use unused::*;
@@ -105,7 +105,7 @@ macro_rules! add_early_builtin_with_new {
 
     macro_rules! add_lint_group {
         ($sess:ident, $name:expr, $($lint:ident),*) => (
-            store.register_group($sess, false, $name, vec![$(LintId::of($lint)),*]);
+            store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]);
             )
     }
 
@@ -149,7 +149,7 @@ macro_rules! add_lint_group {
         MutableTransmutes: MutableTransmutes,
         UnionsWithDropFields: UnionsWithDropFields,
         UnreachablePub: UnreachablePub,
-        UnnameableTestFunctions: UnnameableTestFunctions,
+        UnnameableTestItems: UnnameableTestItems::new(),
         TypeAliasBounds: TypeAliasBounds,
         UnusedBrokenConst: UnusedBrokenConst,
         TrivialConstraints: TrivialConstraints,
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
new file mode 100644 (file)
index 0000000..09871c0
--- /dev/null
@@ -0,0 +1,416 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir::def::Def;
+use rustc::ty;
+use lint::{LateContext, LintContext, LintArray};
+use lint::{LintPass, LateLintPass};
+
+use rustc_target::spec::abi::Abi;
+use syntax::ast;
+use syntax::attr;
+use syntax_pos::Span;
+
+use rustc::hir::{self, GenericParamKind, PatKind};
+use rustc::hir::intravisit::FnKind;
+
+#[derive(PartialEq)]
+pub enum MethodLateContext {
+    TraitAutoImpl,
+    TraitImpl,
+    PlainImpl,
+}
+
+pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext {
+    let def_id = cx.tcx.hir.local_def_id(id);
+    let item = cx.tcx.associated_item(def_id);
+    match item.container {
+        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
+        ty::ImplContainer(cid) => {
+            match cx.tcx.impl_trait_ref(cid) {
+                Some(_) => MethodLateContext::TraitImpl,
+                None => MethodLateContext::PlainImpl,
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_CAMEL_CASE_TYPES,
+    Warn,
+    "types, variants, traits and type parameters should have camel case names"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonCamelCaseTypes;
+
+impl NonCamelCaseTypes {
+    fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        fn char_has_case(c: char) -> bool {
+            c.is_lowercase() || c.is_uppercase()
+        }
+
+        fn is_camel_case(name: ast::Name) -> bool {
+            let name = name.as_str();
+            if name.is_empty() {
+                return true;
+            }
+            let name = name.trim_matches('_');
+
+            // start with a non-lowercase letter rather than non-uppercase
+            // ones (some scripts don't have a concept of upper/lowercase)
+            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
+                !name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
+                    // contains a capitalisable character followed by, or preceded by, an underscore
+                    char_has_case(pair[0]) && pair[1] == '_' ||
+                    char_has_case(pair[1]) && pair[0] == '_'
+                })
+        }
+
+        fn to_camel_case(s: &str) -> String {
+            s.trim_matches('_')
+                .split('_')
+                .map(|word| {
+                    word.chars().enumerate().map(|(i, c)| if i == 0 {
+                        c.to_uppercase().collect::<String>()
+                    } else {
+                        c.to_lowercase().collect()
+                    })
+                    .collect::<String>()
+                })
+                .filter(|x| !x.is_empty())
+                .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
+                    // separate two components with an underscore if their boundary cannot
+                    // be distinguished using a uppercase/lowercase case distinction
+                    let join = if let Some(prev) = prev {
+                                    let l = prev.chars().last().unwrap();
+                                    let f = next.chars().next().unwrap();
+                                    !char_has_case(l) && !char_has_case(f)
+                                } else { false };
+                    (acc + if join { "_" } else { "" } + &next, Some(next))
+                }).0
+        }
+
+        if !is_camel_case(name) {
+            let c = to_camel_case(&name.as_str());
+            let m = if c.is_empty() {
+                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name)
+            } else {
+                format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
+            };
+            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
+        }
+    }
+}
+
+impl LintPass for NonCamelCaseTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_CAMEL_CASE_TYPES)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        let has_repr_c = it.attrs
+            .iter()
+            .any(|attr| {
+                attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
+                    .iter()
+                    .any(|r| r == &attr::ReprC)
+            });
+
+        if has_repr_c {
+            return;
+        }
+
+        match it.node {
+            hir::ItemKind::Ty(..) |
+            hir::ItemKind::Enum(..) |
+            hir::ItemKind::Struct(..) |
+            hir::ItemKind::Union(..) => self.check_case(cx, "type", it.name, it.span),
+            hir::ItemKind::Trait(..) => self.check_case(cx, "trait", it.name, it.span),
+            _ => (),
+        }
+    }
+
+    fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
+        self.check_case(cx, "variant", v.node.name, v.span);
+    }
+
+    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
+        match param.kind {
+            GenericParamKind::Lifetime { .. } => {}
+            GenericParamKind::Type { synthetic, .. } => {
+                if synthetic.is_none() {
+                    self.check_case(cx, "type parameter", param.name.ident().name, param.span);
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_SNAKE_CASE,
+    Warn,
+    "variables, methods, functions, lifetime parameters and modules should have snake case names"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonSnakeCase;
+
+impl NonSnakeCase {
+    fn to_snake_case(mut str: &str) -> String {
+        let mut words = vec![];
+        // Preserve leading underscores
+        str = str.trim_left_matches(|c: char| {
+            if c == '_' {
+                words.push(String::new());
+                true
+            } else {
+                false
+            }
+        });
+        for s in str.split('_') {
+            let mut last_upper = false;
+            let mut buf = String::new();
+            if s.is_empty() {
+                continue;
+            }
+            for ch in s.chars() {
+                if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
+                    words.push(buf);
+                    buf = String::new();
+                }
+                last_upper = ch.is_uppercase();
+                buf.extend(ch.to_lowercase());
+            }
+            words.push(buf);
+        }
+        words.join("_")
+    }
+
+    fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option<Span>) {
+        fn is_snake_case(ident: &str) -> bool {
+            if ident.is_empty() {
+                return true;
+            }
+            let ident = ident.trim_left_matches('\'');
+            let ident = ident.trim_matches('_');
+
+            let mut allow_underscore = true;
+            ident.chars().all(|c| {
+                allow_underscore = match c {
+                    '_' if !allow_underscore => return false,
+                    '_' => false,
+                    // It would be more obvious to use `c.is_lowercase()`,
+                    // but some characters do not have a lowercase form
+                    c if !c.is_uppercase() => true,
+                    _ => return false,
+                };
+                true
+            })
+        }
+
+        if !is_snake_case(name) {
+            let sc = NonSnakeCase::to_snake_case(name);
+            let msg = if sc != name {
+                format!("{} `{}` should have a snake case name such as `{}`",
+                        sort,
+                        name,
+                        sc)
+            } else {
+                format!("{} `{}` should have a snake case name", sort, name)
+            };
+            match span {
+                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
+                None => cx.lint(NON_SNAKE_CASE, &msg),
+            }
+        }
+    }
+}
+
+impl LintPass for NonSnakeCase {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_SNAKE_CASE)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
+    fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
+        let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name")
+            .and_then(|at| at.value_str().map(|s| (at, s)));
+        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
+            self.check_snake_case(cx, "crate", name, None);
+        } else if let Some((attr, name)) = attr_crate_name {
+            self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span));
+        }
+    }
+
+    fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
+        match param.kind {
+            GenericParamKind::Lifetime { .. } => {
+                let name = param.name.ident().as_str();
+                self.check_snake_case(cx, "lifetime", &name, Some(param.span));
+            }
+            GenericParamKind::Type { .. } => {}
+        }
+    }
+
+    fn check_fn(&mut self,
+                cx: &LateContext,
+                fk: FnKind,
+                _: &hir::FnDecl,
+                _: &hir::Body,
+                span: Span,
+                id: ast::NodeId) {
+        match fk {
+            FnKind::Method(name, ..) => {
+                match method_context(cx, id) {
+                    MethodLateContext::PlainImpl => {
+                        self.check_snake_case(cx, "method", &name.as_str(), Some(span))
+                    }
+                    MethodLateContext::TraitAutoImpl => {
+                        self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
+                    }
+                    _ => (),
+                }
+            }
+            FnKind::ItemFn(name, _, header, _, attrs) => {
+                // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
+                if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
+                    return;
+                }
+                self.check_snake_case(cx, "function", &name.as_str(), Some(span))
+            }
+            FnKind::Closure(_) => (),
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if let hir::ItemKind::Mod(_) = it.node {
+            self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span));
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref pnames)) = item.node {
+            self.check_snake_case(cx,
+                                  "trait method",
+                                  &item.ident.as_str(),
+                                  Some(item.span));
+            for param_name in pnames {
+                self.check_snake_case(cx, "variable", &param_name.as_str(), Some(param_name.span));
+            }
+        }
+    }
+
+    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
+        if let &PatKind::Binding(_, _, ref ident, _) = &p.node {
+            self.check_snake_case(cx, "variable", &ident.as_str(), Some(p.span));
+        }
+    }
+
+    fn check_struct_def(&mut self,
+                        cx: &LateContext,
+                        s: &hir::VariantData,
+                        _: ast::Name,
+                        _: &hir::Generics,
+                        _: ast::NodeId) {
+        for sf in s.fields() {
+            self.check_snake_case(cx, "structure field", &sf.ident.as_str(), Some(sf.span));
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_UPPER_CASE_GLOBALS,
+    Warn,
+    "static constants should have uppercase identifiers"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonUpperCaseGlobals;
+
+impl NonUpperCaseGlobals {
+    fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        if name.as_str().chars().any(|c| c.is_lowercase()) {
+            let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase();
+            if name != &*uc {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS,
+                             span,
+                             &format!("{} `{}` should have an upper case name such as `{}`",
+                                      sort,
+                                      name,
+                                      uc));
+            } else {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS,
+                             span,
+                             &format!("{} `{}` should have an upper case name", sort, name));
+            }
+        }
+    }
+}
+
+impl LintPass for NonUpperCaseGlobals {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_UPPER_CASE_GLOBALS)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        match it.node {
+            hir::ItemKind::Static(..) => {
+                if attr::find_by_name(&it.attrs, "no_mangle").is_some() {
+                    return;
+                }
+                NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span);
+            }
+            hir::ItemKind::Const(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
+        match ti.node {
+            hir::TraitItemKind::Const(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ti.ident.name, ti.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
+        match ii.node {
+            hir::ImplItemKind::Const(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ii.ident.name, ii.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
+        // Lint for constants that look like binding identifiers (#7526)
+        if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
+            if let Def::Const(..) = path.def {
+                if path.segments.len() == 1 {
+                    NonUpperCaseGlobals::check_upper_case(cx,
+                                                          "constant in pattern",
+                                                          path.segments[0].ident.name,
+                                                          path.span);
+                }
+            }
+        }
+    }
+}
index f4456b96027aeba2c9e3685c5b241250fdccf46a..9907df7ed02400094a1de14a4e2691184ced1f46 100644 (file)
@@ -542,7 +542,13 @@ pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
                           self.def_path_table.def_path_hash(item_id))
     }
 
-    fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
+    fn get_variant(&self,
+                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                   item: &Entry,
+                   index: DefIndex,
+                   adt_kind: ty::AdtKind)
+                   -> ty::VariantDef
+    {
         let data = match item.kind {
             EntryKind::Variant(data) |
             EntryKind::Struct(data, _) |
@@ -550,10 +556,12 @@ fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
             _ => bug!(),
         };
 
-        ty::VariantDef {
-            did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-            name: self.item_name(index).as_symbol(),
-            fields: item.children.decode(self).map(|index| {
+        ty::VariantDef::new(
+            tcx,
+            self.local_def_id(data.struct_ctor.unwrap_or(index)),
+            self.item_name(index).as_symbol(),
+            data.discr,
+            item.children.decode(self).map(|index| {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
@@ -561,9 +569,9 @@ fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
-            discr: data.discr,
-            ctor_kind: data.ctor_kind,
-        }
+            adt_kind,
+            data.ctor_kind
+        )
     }
 
     pub fn get_adt_def(&self,
@@ -584,11 +592,11 @@ pub fn get_adt_def(&self,
             item.children
                 .decode(self)
                 .map(|index| {
-                    self.get_variant(&self.entry(index), index)
+                    self.get_variant(tcx, &self.entry(index), index, kind)
                 })
                 .collect()
         } else {
-            vec![self.get_variant(&item, item_id)]
+            vec![self.get_variant(tcx, &item, item_id, kind)]
         };
 
         tcx.alloc_adt_def(did, kind, variants, repr)
index 8219ec3df248aaebdbb096987fe6fae2cb5339d7..0fd43c592c8535dd3bfeae79456e6f7242a63cc9 100644 (file)
@@ -740,7 +740,9 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
 
         // If the structure is marked as non_exhaustive then lower the visibility
         // to within the crate.
-        if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
+        if adt_def.non_enum_variant().is_field_list_non_exhaustive() &&
+            ctor_vis == ty::Visibility::Public
+        {
             ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
         }
 
index f78a19403acf8b06cf2ae638cf63c12d1bcc152b..9492385957eabe79f7571b120bbfde0a5f868f72 100644 (file)
 use creader::Library;
 use schema::{METADATA_HEADER, rustc_version};
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::{config, Session};
 use rustc_target::spec::{Target, TargetTriple};
 
 use std::cmp;
-use std::collections::HashSet;
 use std::fmt;
 use std::fs;
 use std::io::{self, Read};
@@ -308,7 +308,7 @@ fn paths(&self) -> Vec<PathBuf> {
 
 impl<'a> Context<'a> {
     pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
-        let mut seen_paths = HashSet::new();
+        let mut seen_paths = FxHashSet::default();
         match self.extra_filename {
             Some(s) => self.find_library_crate(s, &mut seen_paths)
                 .or_else(|| self.find_library_crate("", &mut seen_paths)),
@@ -431,7 +431,7 @@ pub fn report_errs(&mut self) -> ! {
 
     fn find_library_crate(&mut self,
                           extra_prefix: &str,
-                          seen_paths: &mut HashSet<PathBuf>)
+                          seen_paths: &mut FxHashSet<PathBuf>)
                           -> Option<Library> {
         // If an SVH is specified, then this is a transitive dependency that
         // must be loaded via -L plus some filtering.
index f1df135f7ee8357a4bd05bc294b4c53d6523fe93..a0b0aabf73e02b40a6beefdb36305933ceca53b6 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
 use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::ty;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::DiagnosticBuilder;
@@ -24,8 +25,9 @@
 use super::{Context, MirBorrowckCtxt};
 use super::{InitializationRequiringAction, PrefixSet};
 
+use dataflow::drop_flag_effects;
+use dataflow::move_paths::indexes::MoveOutIndex;
 use dataflow::move_paths::MovePathIndex;
-use dataflow::{FlowAtLocation, MovingOutStatements};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
@@ -35,17 +37,14 @@ pub(super) fn report_use_of_moved_or_uninitialized(
         desired_action: InitializationRequiringAction,
         (place, span): (&Place<'tcx>, Span),
         mpi: MovePathIndex,
-        curr_move_out: &FlowAtLocation<MovingOutStatements<'_, 'gcx, 'tcx>>,
     ) {
         let use_spans = self
             .move_spans(place, context.loc)
             .or_else(|| self.borrow_spans(span, context.loc));
         let span = use_spans.args_or_use();
 
-        let mois = self.move_data.path_map[mpi]
-            .iter()
-            .filter(|moi| curr_move_out.contains(moi))
-            .collect::<Vec<_>>();
+        let mois = self.get_moved_indexes(context, mpi);
+        debug!("report_use_of_moved_or_uninitialized: mois={:?}", mois);
 
         if mois.is_empty() {
             let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();
@@ -93,7 +92,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
             let mut is_loop_move = false;
             for moi in &mois {
-                let move_out = self.move_data.moves[**moi];
+                let move_out = self.move_data.moves[*moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
 
                 let move_spans = self.move_spans(moved_place, move_out.source);
@@ -148,7 +147,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 };
 
                 if needs_note {
-                    let mpi = self.move_data.moves[*mois[0]].path;
+                    let mpi = self.move_data.moves[mois[0]].path;
                     let place = &self.move_data.move_paths[mpi].place;
 
                     if let Some(ty) = self.retrieve_type_for_place(place) {
@@ -348,10 +347,7 @@ pub(super) fn report_conflicting_borrow(
         if issued_spans == borrow_spans {
             borrow_spans.var_span_label(
                 &mut err,
-                format!(
-                    "borrows occur due to use of `{}` in closure",
-                    desc_place
-                ),
+                format!("borrows occur due to use of `{}` in closure", desc_place),
             );
         } else {
             let borrow_place = &issued_borrow.borrowed_place;
@@ -366,7 +362,10 @@ pub(super) fn report_conflicting_borrow(
 
             borrow_spans.var_span_label(
                 &mut err,
-                format!("second borrow occurs due to use of `{}` in closure", desc_place),
+                format!(
+                    "second borrow occurs due to use of `{}` in closure",
+                    desc_place
+                ),
             );
         }
 
@@ -413,10 +412,7 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
 
         let mut err = match &self.describe_place(&borrow.borrowed_place) {
             Some(_) if self.is_place_thread_local(root_place) => {
-                self.report_thread_local_value_does_not_live_long_enough(
-                    drop_span,
-                    borrow_span,
-                )
+                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
             }
             Some(name) => self.report_local_value_does_not_live_long_enough(
                 context,
@@ -462,7 +458,10 @@ fn report_local_value_does_not_live_long_enough(
         );
 
         let mut err = self.tcx.path_does_not_live_long_enough(
-            borrow_span, &format!("`{}`", name), Origin::Mir);
+            borrow_span,
+            &format!("`{}`", name),
+            Origin::Mir,
+        );
 
         err.span_label(borrow_span, "borrowed value does not live long enough");
         err.span_label(
@@ -486,11 +485,14 @@ fn report_thread_local_value_does_not_live_long_enough(
             drop_span, borrow_span
         );
 
-        let mut err = self.tcx.thread_local_value_does_not_live_long_enough(
-            borrow_span, Origin::Mir);
+        let mut err = self
+            .tcx
+            .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir);
 
-        err.span_label(borrow_span,
-                       "thread-local variables cannot be borrowed beyond the end of the function");
+        err.span_label(
+            borrow_span,
+            "thread-local variables cannot be borrowed beyond the end of the function",
+        );
         err.span_label(drop_span, "end of enclosing function is here");
         err
     }
@@ -521,6 +523,80 @@ fn report_temporary_value_does_not_live_long_enough(
         err
     }
 
+    fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec<MoveOutIndex> {
+        let mir = self.mir;
+
+        let mut stack = Vec::new();
+        stack.extend(mir.predecessor_locations(context.loc));
+
+        let mut visited = FxHashSet();
+        let mut result = vec![];
+
+        'dfs: while let Some(l) = stack.pop() {
+            debug!(
+                "report_use_of_moved_or_uninitialized: current_location={:?}",
+                l
+            );
+
+            if !visited.insert(l) {
+                continue;
+            }
+
+            // check for moves
+            let stmt_kind = mir[l.block]
+                .statements
+                .get(l.statement_index)
+                .map(|s| &s.kind);
+            if let Some(StatementKind::StorageDead(..)) = stmt_kind {
+                // this analysis only tries to find moves explicitly
+                // written by the user, so we ignore the move-outs
+                // created by `StorageDead` and at the beginning
+                // of a function.
+            } else {
+                for moi in &self.move_data.loc_map[l] {
+                    debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
+                    if self.move_data.moves[*moi].path == mpi {
+                        debug!("report_use_of_moved_or_uninitialized: found");
+                        result.push(*moi);
+
+                        // Strictly speaking, we could continue our DFS here. There may be
+                        // other moves that can reach the point of error. But it is kind of
+                        // confusing to highlight them.
+                        //
+                        // Example:
+                        //
+                        // ```
+                        // let a = vec![];
+                        // let b = a;
+                        // let c = a;
+                        // drop(a); // <-- current point of error
+                        // ```
+                        //
+                        // Because we stop the DFS here, we only highlight `let c = a`,
+                        // and not `let b = a`. We will of course also report an error at
+                        // `let c = a` which highlights `let b = a` as the move.
+                        continue 'dfs;
+                    }
+                }
+            }
+
+            // check for inits
+            let mut any_match = false;
+            drop_flag_effects::for_location_inits(self.tcx, self.mir, self.move_data, l, |m| {
+                if m == mpi {
+                    any_match = true;
+                }
+            });
+            if any_match {
+                continue 'dfs;
+            }
+
+            stack.extend(mir.predecessor_locations(l));
+        }
+
+        result
+    }
+
     pub(super) fn report_illegal_mutation_of_borrowed(
         &mut self,
         context: Context,
@@ -890,8 +966,10 @@ pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
             let attrs = self.tcx.get_attrs(statik.def_id);
             let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
 
-            debug!("is_place_thread_local: attrs={:?} is_thread_local={:?}",
-                   attrs, is_thread_local);
+            debug!(
+                "is_place_thread_local: attrs={:?} is_thread_local={:?}",
+                attrs, is_thread_local
+            );
             is_thread_local
         } else {
             debug!("is_place_thread_local: no");
@@ -909,7 +987,7 @@ pub(super) enum UseSpans {
         // it's present.
         args_span: Span,
         // The span of the first use of the captured variable inside the closure.
-        var_span: Span
+        var_span: Span,
     },
     // This access has a single span associated to it: common case.
     OtherUse(Span),
index 192fa2b9eeaf7238dd9c22da42d287d61504262b..6b964fec74fdd1417b1145de05f44ed2df3b696e 100644 (file)
@@ -24,7 +24,7 @@
 use dataflow::move_paths::indexes::BorrowIndex;
 use dataflow::move_paths::HasMoveData;
 use dataflow::Borrows;
-use dataflow::{EverInitializedPlaces, MovingOutStatements};
+use dataflow::EverInitializedPlaces;
 use dataflow::{FlowAtLocation, FlowsAtLocation};
 use dataflow::MaybeUninitializedPlaces;
 use either::Either;
@@ -35,7 +35,6 @@
 crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
     borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
     pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
-    pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
     pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
 
     /// Polonius Output
@@ -46,14 +45,12 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
     crate fn new(
         borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
         uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
-        move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
         ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
         polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
     ) -> Self {
         Flows {
             borrows,
             uninits,
-            move_outs,
             ever_inits,
             polonius_output,
         }
@@ -79,7 +76,6 @@ macro_rules! each_flow {
     ($this:ident, $meth:ident($arg:ident)) => {
         FlowAtLocation::$meth(&mut $this.borrows, $arg);
         FlowAtLocation::$meth(&mut $this.uninits, $arg);
-        FlowAtLocation::$meth(&mut $this.move_outs, $arg);
         FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
     };
 }
@@ -146,18 +142,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         });
         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.operator().move_data().moves[mpi_move_out];
-            s.push_str(&format!("{:?}", move_out));
-        });
-        s.push_str("] ");
-
         s.push_str("ever_init: [");
         let mut saw_one = false;
         self.ever_inits.each_state_bit(|mpi_ever_init| {
index a04d202efcfb02b759a4fc60a4af1b0e8ceb5ae4..272f5024f9f1a5293bbc94c77b44f73b6388fe7f 100644 (file)
@@ -43,7 +43,7 @@
 use dataflow::FlowAtLocation;
 use dataflow::MoveDataParamEnv;
 use dataflow::{do_dataflow, DebugFormatted};
-use dataflow::{EverInitializedPlaces, MovingOutStatements};
+use dataflow::EverInitializedPlaces;
 use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
@@ -186,15 +186,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
-    let flow_move_outs = FlowAtLocation::new(do_dataflow(
-        tcx,
-        mir,
-        id,
-        &attributes,
-        &dead_unwinds,
-        MovingOutStatements::new(tcx, mir, &mdpe),
-        |bd, i| DebugFormatted::new(&bd.move_data().moves[i]),
-    ));
     let flow_ever_inits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
@@ -268,7 +259,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let mut state = Flows::new(
         flow_borrows,
         flow_uninits,
-        flow_move_outs,
         flow_ever_inits,
         polonius_output,
     );
@@ -1620,7 +1610,6 @@ fn check_if_full_path_is_moved(
         let place = self.base_path(place_span.0);
 
         let maybe_uninits = &flow_state.uninits;
-        let curr_move_outs = &flow_state.move_outs;
 
         // Bad scenarios:
         //
@@ -1666,7 +1655,6 @@ fn check_if_full_path_is_moved(
                         desired_action,
                         place_span,
                         mpi,
-                        curr_move_outs,
                     );
                     return; // don't bother finding other problems.
                 }
@@ -1694,7 +1682,6 @@ fn check_if_path_or_subpath_is_moved(
         let place = self.base_path(place_span.0);
 
         let maybe_uninits = &flow_state.uninits;
-        let curr_move_outs = &flow_state.move_outs;
 
         // Bad scenarios:
         //
@@ -1730,7 +1717,6 @@ fn check_if_path_or_subpath_is_moved(
                     desired_action,
                     place_span,
                     child_mpi,
-                    curr_move_outs,
                 );
                 return; // don't bother finding other problems.
             }
index b80f9784d6f8757879ecff6571036725c581fe8b..693210da8d3a8d92d2d8b05e12fa29427e46ee88 100644 (file)
@@ -120,7 +120,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         flow_inits,
         move_data,
         elements,
-        errors_buffer,
     );
 
     if let Some(all_facts) = &mut all_facts {
index 3a5857f775fa458b1be915c99cf2130a1fb5aee2..61c99832448c595df5690083932f92377420c558 100644 (file)
@@ -36,7 +36,6 @@
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
-use rustc_errors::Diagnostic;
 use std::fmt;
 use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
@@ -103,8 +102,7 @@ macro_rules! span_mirbug_and_err {
 /// - `liveness` -- results of a liveness computation on the MIR; used to create liveness
 ///   constraints for the regions in the types of variables
 /// - `flow_inits` -- results of a maybe-init dataflow analysis
-/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
-/// - `errors_buffer` -- errors are sent here for future reporting
+/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysiss
 pub(crate) fn type_check<'gcx, 'tcx>(
     infcx: &InferCtxt<'_, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
@@ -117,7 +115,6 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
     elements: &Rc<RegionValueElements>,
-    errors_buffer: &mut Vec<Diagnostic>,
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
     let mut constraints = MirTypeckRegionConstraints {
@@ -157,7 +154,6 @@ pub(crate) fn type_check<'gcx, 'tcx>(
             &region_bound_pairs,
             Some(implicit_region_bound),
             Some(&mut borrowck_context),
-            Some(errors_buffer),
             |cx| {
                 cx.equate_inputs_and_outputs(
                     mir,
@@ -185,7 +181,6 @@ fn type_check_internal<'a, 'gcx, 'tcx, R>(
     region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
     borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
-    errors_buffer: Option<&mut Vec<Diagnostic>>,
     mut extra: impl FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>) -> R,
 ) -> R where {
     let mut checker = TypeChecker::new(
@@ -205,7 +200,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, R>(
 
     if !errors_reported {
         // if verifier failed, don't do further checks to avoid ICEs
-        checker.typeck_mir(mir, errors_buffer);
+        checker.typeck_mir(mir);
     }
 
     extra(&mut checker)
@@ -989,7 +984,6 @@ fn check_terminator(
         mir: &Mir<'tcx>,
         term: &Terminator<'tcx>,
         term_location: Location,
-        errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
     ) {
         debug!("check_terminator: {:?}", term);
         let tcx = self.tcx();
@@ -1069,7 +1063,7 @@ fn check_terminator(
                     &sig,
                 );
                 let sig = self.normalize(sig, term_location);
-                self.check_call_dest(mir, term, &sig, destination, term_location, errors_buffer);
+                self.check_call_dest(mir, term, &sig, destination, term_location);
 
                 self.prove_predicates(
                     sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
@@ -1143,7 +1137,6 @@ fn check_call_dest(
         sig: &ty::FnSig<'tcx>,
         destination: &Option<(Place<'tcx>, BasicBlock)>,
         term_location: Location,
-        errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
     ) {
         let tcx = self.tcx();
         match *destination {
@@ -1177,7 +1170,7 @@ fn check_call_dest(
                 // this check is done at `check_local`.
                 if self.tcx().features().unsized_locals {
                     let span = term.source_info.span;
-                    self.ensure_place_sized(dest_ty, span, errors_buffer);
+                    self.ensure_place_sized(dest_ty, span);
                 }
             }
             None => {
@@ -1330,7 +1323,6 @@ fn check_local(
         mir: &Mir<'tcx>,
         local: Local,
         local_decl: &LocalDecl<'tcx>,
-        errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
     ) {
         match mir.local_kind(local) {
             LocalKind::ReturnPointer | LocalKind::Arg => {
@@ -1346,18 +1338,15 @@ fn check_local(
         }
 
         // When `#![feature(unsized_locals)]` is enabled, only function calls
-        // are checked in `check_call_dest`.
+        // and nullary ops are checked in `check_call_dest`.
         if !self.tcx().features().unsized_locals {
             let span = local_decl.source_info.span;
             let ty = local_decl.ty;
-            self.ensure_place_sized(ty, span, errors_buffer);
+            self.ensure_place_sized(ty, span);
         }
     }
 
-    fn ensure_place_sized(&mut self,
-                          ty: Ty<'tcx>,
-                          span: Span,
-                          errors_buffer: &mut Option<&mut Vec<Diagnostic>>) {
+    fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
         let tcx = self.tcx();
 
         // Erase the regions from `ty` to get a global type.  The
@@ -1379,15 +1368,13 @@ fn ensure_place_sized(&mut self,
                      cannot be statically determined",
                     ty
                 );
-                if let Some(ref mut errors_buffer) = *errors_buffer {
-                    diag.buffer(errors_buffer);
-                } else {
-                    // we're allowed to use emit() here because the
-                    // NLL migration will be turned on (and thus
-                    // errors will need to be buffered) *only if*
-                    // errors_buffer is Some.
-                    diag.emit();
-                }
+
+                // While this is located in `nll::typeck` this error is not
+                // an NLL error, it's a required check to prevent creation
+                // of unsized rvalues in certain cases:
+                // * operand of a box expression
+                // * callee in a call expression
+                diag.emit();
             }
         }
     }
@@ -1462,6 +1449,12 @@ fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Loc
             },
 
             Rvalue::NullaryOp(_, ty) => {
+                // Even with unsized locals cannot box an unsized value.
+                if self.tcx().features().unsized_locals {
+                    let span = mir.source_info(location).span;
+                    self.ensure_place_sized(ty, span);
+                }
+
                 let trait_ref = ty::TraitRef {
                     def_id: tcx.lang_items().sized_trait().unwrap(),
                     substs: tcx.mk_substs_trait(ty, &[]),
@@ -1895,12 +1888,12 @@ fn prove_predicate(&mut self, predicate: ty::Predicate<'tcx>, locations: Locatio
         })
     }
 
-    fn typeck_mir(&mut self, mir: &Mir<'tcx>, mut errors_buffer: Option<&mut Vec<Diagnostic>>) {
+    fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
         self.last_span = mir.span;
         debug!("run_on_mir: {:?}", mir.span);
 
         for (local, local_decl) in mir.local_decls.iter_enumerated() {
-            self.check_local(mir, local, local_decl, &mut errors_buffer);
+            self.check_local(mir, local, local_decl);
         }
 
         for (block, block_data) in mir.basic_blocks().iter_enumerated() {
@@ -1916,7 +1909,7 @@ fn typeck_mir(&mut self, mir: &Mir<'tcx>, mut errors_buffer: Option<&mut Vec<Dia
                 location.statement_index += 1;
             }
 
-            self.check_terminator(mir, block_data.terminator(), location, &mut errors_buffer);
+            self.check_terminator(mir, block_data.terminator(), location);
             self.check_iscleanup(mir, block_data);
         }
     }
@@ -1973,7 +1966,6 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &
                 &[],
                 None,
                 None,
-                None,
                 |_| (),
             );
 
index b317bb7cff0e3c9a6e0b720f0dd0b2a63e1123f9..d3e67ea7b7d7153c6a5008848918007900a5d86f 100644 (file)
@@ -453,7 +453,7 @@ pub struct Candidate<'pat, 'tcx:'pat> {
     bindings: Vec<Binding<'tcx>>,
 
     // ...and the guard must be evaluated...
-    guard: Option<ExprRef<'tcx>>,
+    guard: Option<Guard<'tcx>>,
 
     // ...and then we branch to arm with this index.
     arm_index: usize,
@@ -998,7 +998,9 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self,
 
             // the block to branch to if the guard fails; if there is no
             // guard, this block is simply unreachable
-            let guard = self.hir.mirror(guard);
+            let guard = match guard {
+                Guard::If(e) => self.hir.mirror(e),
+            };
             let source_info = self.source_info(guard.span);
             let cond = unpack!(block = self.as_local_operand(block, guard));
             if autoref {
index 295fca839c812bd43c11ec858749a84eb863a999..92ddd8777f733eb0398566b1c45fe9f1fccd6867 100644 (file)
@@ -196,6 +196,8 @@ fn into(self) -> EvalError<'tcx> {
     }
 }
 
+impl_stable_hash_for!(struct CompileTimeEvaluator {});
+
 #[derive(Clone, Debug)]
 enum ConstEvalError {
     NeedsRfc(String),
@@ -288,21 +290,17 @@ fn call_intrinsic<'a>(
         )
     }
 
-    fn try_ptr_op<'a>(
+    fn ptr_op<'a>(
         _ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         _bin_op: mir::BinOp,
-        left: Scalar,
+        _left: Scalar,
         _left_layout: TyLayout<'tcx>,
-        right: Scalar,
+        _right: Scalar,
         _right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Scalar, bool)>> {
-        if left.is_bits() && right.is_bits() {
-            Ok(None)
-        } else {
-            Err(
-                ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
-            )
-        }
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        Err(
+            ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
+        )
     }
 
     fn find_foreign_static<'a>(
index ee3bba840c67bfbfe19d79074103aee29501524e..62c6018809f39ef161b8407d8b0c26b0c4c657c1 100644 (file)
 
 use util::elaborate_drops::DropFlagState;
 
-use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex};
+use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex};
 use super::move_paths::{LookupResult, InitKind};
 use super::{BitDenotation, BlockSets, InitialFlow};
 
 use super::drop_flag_effects_for_function_entry;
 use super::drop_flag_effects_for_location;
-use super::{on_lookup_result_bits, for_location_inits};
+use super::on_lookup_result_bits;
 
 mod storage_liveness;
 
@@ -211,40 +211,6 @@ impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, '
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
-/// `MovingOutStatements` tracks the statements that perform moves out
-/// of particular places. More precisely, it tracks whether the
-/// *effect* of such moves (namely, the uninitialization of the
-/// place 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 place.
-///
-/// The resulting dataflow is a more enriched version of
-/// `MaybeUninitializedPlaces`. Both structures on their own only tell
-/// you if a place *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 }
-}
-
 /// `EverInitializedPlaces` tracks all places that might have ever been
 /// initialized upon reaching a particular point in the control flow
 /// for a function, without an intervening `Storage Dead`.
@@ -488,83 +454,6 @@ 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 IdxSet<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;
-
-        match stmt.kind {
-            // this analysis only tries to find moves explicitly
-            // written by the user, so we ignore the move-outs
-            // created by `StorageDead` and at the beginning
-            // of a function.
-            mir::StatementKind::StorageDead(_) => {}
-            _ => {
-                debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
-                       stmt, location, &loc_map[location]);
-                // Every path deinitialized by a *particular move*
-                // has corresponding bit, "gen'ed" (i.e. set)
-                // here, in dataflow vector
-                sets.gen_all_and_assert_dead(&loc_map[location]);
-            }
-        }
-
-        for_location_inits(tcx, mir, move_data, location,
-                           |mpi| sets.kill_all(&path_map[mpi]));
-    }
-
-    fn terminator_effect(&self,
-                         sets: &mut BlockSets<MoveOutIndex>,
-                         location: Location)
-    {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
-        let term = mir[location.block].terminator();
-        let loc_map = &move_data.loc_map;
-        let path_map = &move_data.path_map;
-
-        debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
-               term, location, &loc_map[location]);
-        sets.gen_all_and_assert_dead(&loc_map[location]);
-
-        for_location_inits(tcx, mir, move_data, location,
-                           |mpi| sets.kill_all(&path_map[mpi]));
-    }
-
-    fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<MoveOutIndex>,
-                             _call_bb: mir::BasicBlock,
-                             _dest_bb: mir::BasicBlock,
-                             dest_place: &mir::Place) {
-        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_place),
-                              |mpi| for moi in &path_map[mpi] {
-                                  assert!(moi.index() < bits_per_block);
-                                  in_out.remove(&moi);
-                              });
-    }
-}
-
 impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     type Idx = InitIndex;
     fn name() -> &'static str { "ever_init" }
@@ -682,13 +571,6 @@ fn join(&self, pred1: Word, pred2: Word) -> Word {
     }
 }
 
-impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> {
-    #[inline]
-    fn join(&self, pred1: Word, pred2: Word) -> Word {
-        pred1 | pred2 // moves from both preds are in scope
-    }
-}
-
 impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: Word, pred2: Word) -> Word {
@@ -727,13 +609,6 @@ fn bottom_value() -> bool {
     }
 }
 
-impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> {
-    #[inline]
-    fn bottom_value() -> bool {
-        false // bottom = no loans in scope by default
-    }
-}
-
 impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
index fd6569feb5c201910e6e3873f5b64a25f034a887..bee7d443c85408b430520fd4abc9612f3468e5cd 100644 (file)
@@ -28,7 +28,7 @@
 
 pub use self::impls::{MaybeStorageLive};
 pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
-pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements};
+pub use self::impls::DefinitelyInitializedPlaces;
 pub use self::impls::EverInitializedPlaces;
 pub use self::impls::borrows::Borrows;
 pub use self::impls::HaveBeenBorrowedLocals;
@@ -38,7 +38,7 @@
 use self::move_paths::MoveData;
 
 mod at_location;
-mod drop_flag_effects;
+pub mod drop_flag_effects;
 mod graphviz;
 mod impls;
 pub mod move_paths;
@@ -511,18 +511,6 @@ fn gen_all<I>(&mut self, i: I)
         }
     }
 
-    fn gen_all_and_assert_dead<I>(&mut self, i: I)
-        where I: IntoIterator,
-        I::Item: Borrow<E>
-    {
-        for j in i {
-            let j = j.borrow();
-            let retval = self.gen_set.add(j);
-            self.kill_set.remove(j);
-            assert!(retval);
-        }
-    }
-
     fn kill(&mut self, e: &E) {
         self.gen_set.remove(e);
         self.kill_set.add(e);
index 8be1f52a9cdfc7d39151dc272fea046ddd3865a6..055f238e5db4ea12f2c03d6a079d7ff2fe70b5ea 100644 (file)
@@ -837,7 +837,10 @@ fn to_borrow_kind(&self) -> BorrowKind {
 fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
     Arm {
         patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
-        guard: arm.guard.to_ref(),
+        guard: match arm.guard {
+                Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())),
+                _ => None,
+            },
         body: arm.body.to_ref(),
         // BUG: fix this
         lint_level: LintLevel::Inherited,
index c9fd1d04e547b7f0a8a8b1d4a1e9562cc00c3dbc..b4257a40e38af0dd0ea3ff3de467b5d4cd080ca6 100644 (file)
@@ -18,7 +18,6 @@
 
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::map::blocks::FnLikeNode;
 use rustc::hir::Node;
 use rustc::middle::region;
 use rustc::infer::InferCtxt;
@@ -67,10 +66,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         let constness = match body_owner_kind {
             hir::BodyOwnerKind::Const |
             hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
-            hir::BodyOwnerKind::Fn => {
-                let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id));
-                fn_like.map_or(hir::Constness::NotConst, |f| f.constness())
-            }
+            hir::BodyOwnerKind::Fn => hir::Constness::NotConst,
         };
 
         let attrs = tcx.hir.attrs(src_id);
@@ -83,7 +79,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         // Respect -C overflow-checks.
         check_overflow |= tcx.sess.overflow_checks();
 
-        // Constants and const fn's always need overflow checks.
+        // Constants always need overflow checks.
         check_overflow |= constness == hir::Constness::Const;
 
         let lint_level = lint_level_for_hir_id(tcx, src_id);
index d6037adb53bb7a8a5161e626846df7491b38cde0..2ddb810f4914817e7640e6bdf92cd1a78750ae67 100644 (file)
@@ -316,11 +316,16 @@ pub struct FruInfo<'tcx> {
 #[derive(Clone, Debug)]
 pub struct Arm<'tcx> {
     pub patterns: Vec<Pattern<'tcx>>,
-    pub guard: Option<ExprRef<'tcx>>,
+    pub guard: Option<Guard<'tcx>>,
     pub body: ExprRef<'tcx>,
     pub lint_level: LintLevel,
 }
 
+#[derive(Clone, Debug)]
+pub enum Guard<'tcx> {
+    If(ExprRef<'tcx>),
+}
+
 #[derive(Copy, Clone, Debug)]
 pub enum LogicalOp {
     And,
index e9d65caf08743ac486b4624c8b3d516e53af04da..d7fbbc88cc16d63e864e93c11e174b5163d852c9 100644 (file)
@@ -381,7 +381,7 @@ fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
 
     fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
-            ty::Adt(adt_def, ..) => adt_def.is_enum() && adt_def.is_non_exhaustive(),
+            ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
             _ => false,
         }
     }
index 604cc61a17ecb17073f104a7eb8167793291ddc4..bf878145e1fb972ba906caa194f7928044db9e65 100644 (file)
@@ -208,7 +208,9 @@ fn check_match(
                     }
                     (pattern, &**pat)
                 }).collect(),
-                arm.guard.as_ref().map(|e| &**e)
+                arm.guard.as_ref().map(|g| match g {
+                    hir::Guard::If(ref e) => &**e,
+                })
             )).collect();
 
             // Bail out early if inlining failed.
@@ -540,12 +542,16 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                       "cannot bind by-move into a pattern guard")
                 .span_label(p.span, "moves value into pattern guard")
                 .emit();
-        } else if by_ref_span.is_some() {
-            struct_span_err!(cx.tcx.sess, p.span, E0009,
-                            "cannot bind by-move and by-ref in the same pattern")
-                    .span_label(p.span, "by-move pattern here")
-                    .span_label(by_ref_span.unwrap(), "both by-ref and by-move used")
-                    .emit();
+        } else if let Some(by_ref_span) = by_ref_span {
+            struct_span_err!(
+                cx.tcx.sess,
+                p.span,
+                E0009,
+                "cannot bind by-move and by-ref in the same pattern",
+            )
+            .span_label(p.span, "by-move pattern here")
+            .span_label(by_ref_span, "both by-ref and by-move used")
+            .emit();
         }
     };
 
@@ -575,12 +581,19 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
 /// assign.
 ///
 /// FIXME: this should be done by borrowck.
-fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
+fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Guard) {
     let mut checker = MutationChecker {
         cx,
     };
-    ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None)
-        .walk_expr(guard);
+    match guard {
+        hir::Guard::If(expr) =>
+            ExprUseVisitor::new(&mut checker,
+                                cx.tcx,
+                                cx.param_env,
+                                cx.region_scope_tree,
+                                cx.tables,
+                                None).walk_expr(expr),
+    };
 }
 
 struct MutationChecker<'a, 'tcx: 'a> {
index d0d1c5d6610d08ded9306981689927cc589863c6..83264acf76a31809d7d4047713c592be56c72700 100644 (file)
@@ -14,8 +14,7 @@
 
 use rustc_apfloat::ieee::{Single, Double};
 use rustc::mir::interpret::{
-    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind,
-    truncate, sign_extend
+    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind, truncate
 };
 use rustc::mir::CastKind;
 use rustc_apfloat::Float;
@@ -49,13 +48,13 @@ pub fn cast(
             Misc => {
                 let src = self.read_value(src)?;
                 if self.type_is_fat_ptr(src_layout.ty) {
-                    match (src.value, self.type_is_fat_ptr(dest.layout.ty)) {
+                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
                         // pointers to extern types
                         (Value::Scalar(_),_) |
                         // slices and trait objects to other slices/trait objects
                         (Value::ScalarPair(..), true) => {
                             // No change to value
-                            self.write_value(src.value, dest)?;
+                            self.write_value(*src, dest)?;
                         }
                         // slices and trait objects to thin pointers (dropping the metadata)
                         (Value::ScalarPair(data, _), false) => {
@@ -70,10 +69,7 @@ pub fn cast(
                                     .discriminant_for_variant(*self.tcx, index)
                                     .val;
                                 return self.write_scalar(
-                                    Scalar::Bits {
-                                        bits: discr_val,
-                                        size: dst_layout.size.bytes() as u8,
-                                    },
+                                    Scalar::from_uint(discr_val, dst_layout.size),
                                     dest);
                             }
                         }
@@ -198,41 +194,39 @@ fn cast_from_int(
         match dest_layout.ty.sty {
             Int(_) | Uint(_) => {
                 let v = self.truncate(v, dest_layout);
-                Ok(Scalar::Bits {
-                    bits: v,
-                    size: dest_layout.size.bytes() as u8,
-                })
+                Ok(Scalar::from_uint(v, dest_layout.size))
             }
 
-            Float(FloatTy::F32) if signed => Ok(Scalar::Bits {
-                bits: Single::from_i128(v as i128).value.to_bits(),
-                size: 4,
-            }),
-            Float(FloatTy::F64) if signed => Ok(Scalar::Bits {
-                bits: Double::from_i128(v as i128).value.to_bits(),
-                size: 8,
-            }),
-            Float(FloatTy::F32) => Ok(Scalar::Bits {
-                bits: Single::from_u128(v).value.to_bits(),
-                size: 4,
-            }),
-            Float(FloatTy::F64) => Ok(Scalar::Bits {
-                bits: Double::from_u128(v).value.to_bits(),
-                size: 8,
-            }),
+            Float(FloatTy::F32) if signed => Ok(Scalar::from_uint(
+                Single::from_i128(v as i128).value.to_bits(),
+                Size::from_bits(32)
+            )),
+            Float(FloatTy::F64) if signed => Ok(Scalar::from_uint(
+                Double::from_i128(v as i128).value.to_bits(),
+                Size::from_bits(64)
+            )),
+            Float(FloatTy::F32) => Ok(Scalar::from_uint(
+                Single::from_u128(v).value.to_bits(),
+                Size::from_bits(32)
+            )),
+            Float(FloatTy::F64) => Ok(Scalar::from_uint(
+                Double::from_u128(v).value.to_bits(),
+                Size::from_bits(64)
+            )),
 
             Char => {
-                assert_eq!(v as u8 as u128, v);
-                Ok(Scalar::Bits { bits: v, size: 4 })
+                // `u8` to `char` cast
+                debug_assert_eq!(v as u8 as u128, v);
+                Ok(Scalar::from_uint(v, Size::from_bytes(4)))
             },
 
             // No alignment check needed for raw pointers.
             // But we have to truncate to target ptr size.
             RawPtr(_) => {
-                Ok(Scalar::Bits {
-                    bits: self.memory.truncate_to_ptr(v).0 as u128,
-                    size: self.memory.pointer_size().bytes() as u8,
-                })
+                Ok(Scalar::from_uint(
+                    self.truncate_to_ptr(v).0,
+                    self.pointer_size(),
+                ))
             },
 
             // Casts to bool are not permitted by rustc, no need to handle them here.
@@ -251,56 +245,40 @@ fn cast_from_float(
         match dest_ty.sty {
             // float -> uint
             Uint(t) => {
-                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
+                let width = t.bit_width().unwrap_or(self.pointer_size().bits() as usize);
                 let v = match fty {
                     FloatTy::F32 => Single::from_bits(bits).to_u128(width).value,
                     FloatTy::F64 => Double::from_bits(bits).to_u128(width).value,
                 };
                 // This should already fit the bit width
-                Ok(Scalar::Bits {
-                    bits: v,
-                    size: (width / 8) as u8,
-                })
+                Ok(Scalar::from_uint(v, Size::from_bits(width as u64)))
             },
             // float -> int
             Int(t) => {
-                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
+                let width = t.bit_width().unwrap_or(self.pointer_size().bits() as usize);
                 let v = match fty {
                     FloatTy::F32 => Single::from_bits(bits).to_i128(width).value,
                     FloatTy::F64 => Double::from_bits(bits).to_i128(width).value,
                 };
-                // We got an i128, but we may need something smaller. We have to truncate ourselves.
-                let truncated = truncate(v as u128, Size::from_bits(width as u64));
-                assert_eq!(sign_extend(truncated, Size::from_bits(width as u64)) as i128, v,
-                    "truncating and extending changed the value?!?");
-                Ok(Scalar::Bits {
-                    bits: truncated,
-                    size: (width / 8) as u8,
-                })
+                Ok(Scalar::from_int(v, Size::from_bits(width as u64)))
             },
             // f64 -> f32
             Float(FloatTy::F32) if fty == FloatTy::F64 => {
-                Ok(Scalar::Bits {
-                    bits: Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
-                    size: 4,
-                })
+                Ok(Scalar::from_uint(
+                    Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
+                    Size::from_bits(32),
+                ))
             },
             // f32 -> f64
             Float(FloatTy::F64) if fty == FloatTy::F32 => {
-                Ok(Scalar::Bits {
-                    bits: Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
-                    size: 8,
-                })
+                Ok(Scalar::from_uint(
+                    Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
+                    Size::from_bits(64),
+                ))
             },
             // identity cast
-            Float(FloatTy:: F64) => Ok(Scalar::Bits {
-                bits,
-                size: 8,
-            }),
-            Float(FloatTy:: F32) => Ok(Scalar::Bits {
-                bits,
-                size: 4,
-            }),
+            Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))),
+            Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))),
             _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
         }
     }
index 455c3fc281a6be45b1be6da6d55ffcea13155375..f7277f8d27610b3fb5ac780e62caf498210da9d1 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 use std::fmt::Write;
-use std::hash::{Hash, Hasher};
 use std::mem;
 
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
 use rustc::hir::map::definitions::DefPathData;
+use rustc::ich::StableHashingContext;
 use rustc::mir;
 use rustc::ty::layout::{
     self, Size, Align, HasDataLayout, LayoutOf, TyLayout
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::query::TyCtxtAt;
-use rustc_data_structures::fx::{FxHashSet, FxHasher};
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 use rustc::mir::interpret::{
-    GlobalId, Scalar, FrameInfo,
+    GlobalId, Scalar, FrameInfo, AllocId,
     EvalResult, EvalErrorKind,
     ScalarMaybeUndef,
     truncate, sign_extend,
@@ -38,6 +38,8 @@
     Memory, Machine
 };
 
+use super::snapshot::InfiniteLoopDetector;
+
 pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     /// Stores the `Machine` instance.
     pub machine: M,
@@ -95,7 +97,7 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     /// The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
-    pub locals: IndexVec<mir::Local, LocalValue>,
+    pub locals: IndexVec<mir::Local, LocalValue<AllocId>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -108,38 +110,16 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     pub stmt: usize,
 }
 
-impl<'mir, 'tcx: 'mir> Eq for Frame<'mir, 'tcx> {}
-
-impl<'mir, 'tcx: 'mir> PartialEq for Frame<'mir, 'tcx> {
-    fn eq(&self, other: &Self) -> bool {
-        let Frame {
-            mir: _,
-            instance,
-            span: _,
-            return_to_block,
-            return_place,
-            locals,
-            block,
-            stmt,
-        } = self;
-
-        // Some of these are constant during evaluation, but are included
-        // anyways for correctness.
-        *instance == other.instance
-            && *return_to_block == other.return_to_block
-            && *return_place == other.return_place
-            && *locals == other.locals
-            && *block == other.block
-            && *stmt == other.stmt
-    }
-}
+impl<'a, 'mir, 'tcx: 'mir> HashStable<StableHashingContext<'a>> for Frame<'mir, 'tcx> {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>) {
 
-impl<'mir, 'tcx: 'mir> Hash for Frame<'mir, 'tcx> {
-    fn hash<H: Hasher>(&self, state: &mut H) {
         let Frame {
-            mir: _,
+            mir,
             instance,
-            span: _,
+            span,
             return_to_block,
             return_place,
             locals,
@@ -147,12 +127,8 @@ fn hash<H: Hasher>(&self, state: &mut H) {
             stmt,
         } = self;
 
-        instance.hash(state);
-        return_to_block.hash(state);
-        return_place.hash(state);
-        locals.hash(state);
-        block.hash(state);
-        stmt.hash(state);
+        (mir, instance, span, return_to_block).hash_stable(hcx, hasher);
+        (return_place, locals, block, stmt).hash_stable(hcx, hasher);
     }
 }
 
@@ -168,15 +144,27 @@ pub enum StackPopCleanup {
     None { cleanup: bool },
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for StackPopCleanup {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>) {
+        match self {
+            StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher),
+            StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher),
+        }
+    }
+}
+
 // State of a local variable
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalValue {
+pub enum LocalValue<Id=AllocId> {
     Dead,
     // Mostly for convenience, we re-use the `Operand` type here.
     // This is an optimization over just always having a pointer here;
     // we can thus avoid doing an allocation when the local just stores
     // immediate values *and* never has its address taken.
-    Live(Operand),
+    Live(Operand<Id>),
 }
 
 impl<'tcx> LocalValue {
@@ -195,72 +183,10 @@ pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand> {
     }
 }
 
-/// The virtual machine state during const-evaluation at a given point in time.
-type EvalSnapshot<'a, 'mir, 'tcx, M>
-    = (M, Vec<Frame<'mir, 'tcx>>, Memory<'a, 'mir, 'tcx, M>);
-
-pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
-    /// The set of all `EvalSnapshot` *hashes* observed by this detector.
-    ///
-    /// When a collision occurs in this table, we store the full snapshot in
-    /// `snapshots`.
-    hashes: FxHashSet<u64>,
-
-    /// The set of all `EvalSnapshot`s observed by this detector.
-    ///
-    /// An `EvalSnapshot` will only be fully cloned once it has caused a
-    /// collision in `hashes`. As a result, the detector must observe at least
-    /// *two* full cycles of an infinite loop before it triggers.
-    snapshots: FxHashSet<EvalSnapshot<'a, 'mir, 'tcx, M>>,
-}
-
-impl<'a, 'mir, 'tcx, M> Default for InfiniteLoopDetector<'a, 'mir, 'tcx, M>
-    where M: Machine<'mir, 'tcx>,
-          'tcx: 'a + 'mir,
-{
-    fn default() -> Self {
-        InfiniteLoopDetector {
-            hashes: FxHashSet::default(),
-            snapshots: FxHashSet::default(),
-        }
-    }
-}
-
-impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
-    where M: Machine<'mir, 'tcx>,
-          'tcx: 'a + 'mir,
-{
-    /// Returns `true` if the loop detector has not yet observed a snapshot.
-    pub fn is_empty(&self) -> bool {
-        self.hashes.is_empty()
-    }
-
-    pub fn observe_and_analyze(
-        &mut self,
-        machine: &M,
-        stack: &Vec<Frame<'mir, 'tcx>>,
-        memory: &Memory<'a, 'mir, 'tcx, M>,
-    ) -> EvalResult<'tcx, ()> {
-        let snapshot = (machine, stack, memory);
-
-        let mut fx = FxHasher::default();
-        snapshot.hash(&mut fx);
-        let hash = fx.finish();
-
-        if self.hashes.insert(hash) {
-            // No collision
-            return Ok(())
-        }
-
-        if self.snapshots.insert((machine.clone(), stack.clone(), memory.clone())) {
-            // Spurious collision or first cycle
-            return Ok(())
-        }
-
-        // Second cycle
-        Err(EvalErrorKind::InfiniteLoop.into())
-    }
-}
+impl_stable_hash_for!(enum self::LocalValue {
+    Dead,
+    Live(x),
+});
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a EvalContext<'a, 'mir, 'tcx, M> {
     #[inline]
@@ -270,7 +196,8 @@ fn data_layout(&self) -> &layout::TargetDataLayout {
 }
 
 impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout
-    for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> {
+    for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M>
+{
     #[inline]
     fn data_layout(&self) -> &layout::TargetDataLayout {
         &self.tcx.data_layout
index e809830fad1cf8c0d1d6301c8e98c6ecf6aec728..8cdb0e37f55075ba2e610cd93038050f52a75bad 100644 (file)
@@ -15,6 +15,7 @@
 use syntax::symbol::Symbol;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Primitive};
+use rustc::mir::BinOp;
 use rustc::mir::interpret::{
     EvalResult, EvalErrorKind, Scalar,
 };
@@ -39,9 +40,10 @@ fn numeric_intrinsic<'tcx>(
         "ctlz" => bits.leading_zeros() as u128 - extra,
         "cttz" => (bits << extra).trailing_zeros() as u128 - extra,
         "bswap" => (bits << extra).swap_bytes(),
+        "bitreverse" => (bits << extra).reverse_bits(),
         _ => bug!("not a numeric intrinsic: {}", name),
     };
-    Ok(Scalar::Bits { bits: bits_out, size: size.bytes() as u8 })
+    Ok(Scalar::from_uint(bits_out, size))
 }
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -59,33 +61,30 @@ pub fn emulate_intrinsic(
             "min_align_of" => {
                 let elem_ty = substs.type_at(0);
                 let elem_align = self.layout_of(elem_ty)?.align.abi();
-                let align_val = Scalar::Bits {
-                    bits: elem_align as u128,
-                    size: dest.layout.size.bytes() as u8,
-                };
+                let align_val = Scalar::from_uint(elem_align, dest.layout.size);
                 self.write_scalar(align_val, dest)?;
             }
 
             "size_of" => {
                 let ty = substs.type_at(0);
                 let size = self.layout_of(ty)?.size.bytes() as u128;
-                let size_val = Scalar::Bits {
-                    bits: size,
-                    size: dest.layout.size.bytes() as u8,
-                };
+                let size_val = Scalar::from_uint(size, dest.layout.size);
                 self.write_scalar(size_val, dest)?;
             }
 
             "type_id" => {
                 let ty = substs.type_at(0);
                 let type_id = self.tcx.type_id_hash(ty) as u128;
-                let id_val = Scalar::Bits {
-                    bits: type_id,
-                    size: dest.layout.size.bytes() as u8,
-                };
+                let id_val = Scalar::from_uint(type_id, dest.layout.size);
                 self.write_scalar(id_val, dest)?;
             }
-            "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => {
+            | "ctpop"
+            | "cttz"
+            | "cttz_nonzero"
+            | "ctlz"
+            | "ctlz_nonzero"
+            | "bswap"
+            | "bitreverse" => {
                 let ty = substs.type_at(0);
                 let layout_of = self.layout_of(ty)?;
                 let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
@@ -103,6 +102,33 @@ pub fn emulate_intrinsic(
                 };
                 self.write_scalar(out_val, dest)?;
             }
+            | "overflowing_add"
+            | "overflowing_sub"
+            | "overflowing_mul"
+            | "unchecked_shl"
+            | "unchecked_shr"
+            | "add_with_overflow"
+            | "sub_with_overflow"
+            | "mul_with_overflow" => {
+                let lhs = self.read_value(args[0])?;
+                let rhs = self.read_value(args[1])?;
+                let (bin_op, ignore_overflow) = match intrinsic_name {
+                    "overflowing_add" => (BinOp::Add, true),
+                    "overflowing_sub" => (BinOp::Sub, true),
+                    "overflowing_mul" => (BinOp::Mul, true),
+                    "unchecked_shl" => (BinOp::Shl, true),
+                    "unchecked_shr" => (BinOp::Shr, true),
+                    "add_with_overflow" => (BinOp::Add, false),
+                    "sub_with_overflow" => (BinOp::Sub, false),
+                    "mul_with_overflow" => (BinOp::Mul, false),
+                    _ => bug!("Already checked for int ops")
+                };
+                if ignore_overflow {
+                    self.binop_ignore_overflow(bin_op, lhs, rhs, dest)?;
+                } else {
+                    self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
+                }
+            }
             "transmute" => {
                 // Go through an allocation, to make sure the completely different layouts
                 // do not pose a problem.  (When the user transmutes through a union,
index a8fae2b4871ed7a13d07666fbca0197e3a798516..61963f6d3d354560828405c7cbdd9f4fa758b49f 100644 (file)
 use std::hash::Hash;
 
 use rustc::hir::def_id::DefId;
+use rustc::ich::StableHashingContext;
 use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
 use rustc::mir;
 use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
+use rustc_data_structures::stable_hasher::HashStable;
 
 use super::{EvalContext, PlaceTy, OpTy};
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
 /// and some use case dependent behaviour can instead be applied
-pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
+pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>> {
     /// Additional data that can be accessed via the Memory
-    type MemoryData: Clone + Eq + Hash;
+    type MemoryData: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>>;
 
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;
@@ -69,20 +71,18 @@ fn find_foreign_static<'a>(
         def_id: DefId,
     ) -> EvalResult<'tcx, &'tcx Allocation>;
 
-    /// Called for all binary operations except on float types.
-    ///
-    /// Returns `None` if the operation should be handled by the integer
-    /// op code in order to share more code between machines
+    /// Called for all binary operations on integer(-like) types when one operand is a pointer
+    /// value, and for the `Offset` operation that is inherently about pointers.
     ///
     /// Returns a (value, overflowed) pair if the operation succeeded
-    fn try_ptr_op<'a>(
+    fn ptr_op<'a>(
         ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
         left: Scalar,
         left_layout: TyLayout<'tcx>,
         right: Scalar,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Scalar, bool)>>;
+    ) -> EvalResult<'tcx, (Scalar, bool)>;
 
     /// Heap allocations via the `box` keyword
     ///
index 240f977a5a0e8ddfc045260fae96090ee575e4ab..9e61de92936bdb7cf2fdb84670e9b69b3c15d0f7 100644 (file)
 //! short-circuiting the empty case!
 
 use std::collections::VecDeque;
-use std::hash::{Hash, Hasher};
 use std::ptr;
 
 use rustc::ty::{self, Instance, query::TyCtxtAt};
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
-use rustc::mir::interpret::{Pointer, AllocId, Allocation, ScalarMaybeUndef, GlobalId,
-                            EvalResult, Scalar, EvalErrorKind, AllocType, truncate};
+use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, ScalarMaybeUndef, GlobalId,
+                            EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
+                            truncate};
 pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
-use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
+use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
 use syntax::ast::Mutability;
 
@@ -60,98 +60,15 @@ fn data_layout(&self) -> &TargetDataLayout {
         &self.tcx.data_layout
     }
 }
-
-impl<'a, 'mir, 'tcx, M> Eq for Memory<'a, 'mir, 'tcx, M>
-    where M: Machine<'mir, 'tcx>,
-          'tcx: 'a + 'mir,
-{}
-
-impl<'a, 'mir, 'tcx, M> PartialEq for Memory<'a, 'mir, 'tcx, M>
-    where M: Machine<'mir, 'tcx>,
-          'tcx: 'a + 'mir,
+impl<'a, 'b, 'c, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout
+    for &'b &'c mut Memory<'a, 'mir, 'tcx, M>
 {
-    fn eq(&self, other: &Self) -> bool {
-        let Memory {
-            data,
-            alloc_map,
-            tcx: _,
-        } = self;
-
-        *data == other.data
-            && *alloc_map == other.alloc_map
-    }
-}
-
-impl<'a, 'mir, 'tcx, M> Hash for Memory<'a, 'mir, 'tcx, M>
-    where M: Machine<'mir, 'tcx>,
-          'tcx: 'a + 'mir,
-{
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        let Memory {
-            data,
-            alloc_map: _,
-            tcx: _,
-        } = self;
-
-        data.hash(state);
-
-        // We ignore some fields which don't change between evaluation steps.
-
-        // Since HashMaps which contain the same items may have different
-        // iteration orders, we use a commutative operation (in this case
-        // addition, but XOR would also work), to combine the hash of each
-        // `Allocation`.
-        self.alloc_map.iter()
-            .map(|(&id, alloc)| {
-                let mut h = FxHasher::default();
-                id.hash(&mut h);
-                alloc.hash(&mut h);
-                h.finish()
-            })
-            .fold(0u64, |hash, x| hash.wrapping_add(x))
-            .hash(state);
+    #[inline]
+    fn data_layout(&self) -> &TargetDataLayout {
+        &self.tcx.data_layout
     }
 }
 
-/// Helper function to obtain the global (tcx) allocation for a static
-fn const_eval_static<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>>(
-    tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
-    id: AllocId
-) -> EvalResult<'tcx, &'tcx Allocation> {
-    let alloc = tcx.alloc_map.lock().get(id);
-    let def_id = match alloc {
-        Some(AllocType::Memory(mem)) => {
-            return Ok(mem)
-        }
-        Some(AllocType::Function(..)) => {
-            return err!(DerefFunctionPointer)
-        }
-        Some(AllocType::Static(did)) => {
-            did
-        }
-        None =>
-            return err!(DanglingPointerDeref),
-    };
-    // We got a "lazy" static that has not been computed yet, do some work
-    trace!("static_alloc: Need to compute {:?}", def_id);
-    if tcx.is_foreign_item(def_id) {
-        return M::find_foreign_static(tcx, def_id);
-    }
-    let instance = Instance::mono(tcx.tcx, def_id);
-    let gid = GlobalId {
-        instance,
-        promoted: None,
-    };
-    tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
-        // no need to report anything, the const_eval call takes care of that for statics
-        assert!(tcx.is_static(def_id).is_some());
-        EvalErrorKind::ReferencedConstant(err).into()
-    }).map(|val| {
-        // FIXME We got our static (will be a ByRef), now we make a *copy*?!?
-        tcx.const_to_allocation(val)
-    })
-}
-
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
         Memory {
@@ -277,14 +194,6 @@ pub fn deallocate(
         Ok(())
     }
 
-    pub fn pointer_size(&self) -> Size {
-        self.tcx.data_layout.pointer_size
-    }
-
-    pub fn endianness(&self) -> layout::Endian {
-        self.tcx.data_layout.endian
-    }
-
     /// Check that the pointer is aligned AND non-NULL. This supports scalars
     /// for the benefit of other parts of miri that need to check alignment even for ZST.
     pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> {
@@ -296,13 +205,12 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
             }
             Scalar::Bits { bits, size } => {
                 assert_eq!(size as u64, self.pointer_size().bytes());
-                // FIXME: what on earth does this line do? docs or fix needed!
-                let v = ((bits as u128) % (1 << self.pointer_size().bytes())) as u64;
-                if v == 0 {
+                assert!(bits < (1u128 << self.pointer_size().bits()));
+                if bits == 0 {
                     return err!(InvalidNullPointerUsage);
                 }
-                // the base address if the "integer allocation" is 0 and hence always aligned
-                (v, required_align)
+                // the "base address" is 0 and hence always aligned
+                (bits as u64, required_align)
             }
         };
         // Check alignment
@@ -325,7 +233,11 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
 
     /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
     /// of an allocation (i.e., at the first *inaccessible* location) *is* considered
-    /// in-bounds!  This follows C's/LLVM's rules.
+    /// in-bounds!  This follows C's/LLVM's rules.  The `access` boolean is just used
+    /// for the error message.
+    /// If you want to check bounds before doing a memory access, be sure to
+    /// check the pointer one past the end of your access, then everything will
+    /// work out exactly.
     pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         let allocation_size = alloc.bytes.len() as u64;
@@ -342,13 +254,55 @@ pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> {
 
 /// Allocation accessors
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
+    /// Helper function to obtain the global (tcx) allocation for a static
+    fn get_static_alloc(
+        tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
+        id: AllocId,
+    ) -> EvalResult<'tcx, &'tcx Allocation> {
+        let alloc = tcx.alloc_map.lock().get(id);
+        let def_id = match alloc {
+            Some(AllocType::Memory(mem)) => {
+                return Ok(mem)
+            }
+            Some(AllocType::Function(..)) => {
+                return err!(DerefFunctionPointer)
+            }
+            Some(AllocType::Static(did)) => {
+                did
+            }
+            None =>
+                return err!(DanglingPointerDeref),
+        };
+        // We got a "lazy" static that has not been computed yet, do some work
+        trace!("static_alloc: Need to compute {:?}", def_id);
+        if tcx.is_foreign_item(def_id) {
+            return M::find_foreign_static(tcx, def_id);
+        }
+        let instance = Instance::mono(tcx.tcx, def_id);
+        let gid = GlobalId {
+            instance,
+            promoted: None,
+        };
+        tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
+            // no need to report anything, the const_eval call takes care of that for statics
+            assert!(tcx.is_static(def_id).is_some());
+            EvalErrorKind::ReferencedConstant(err).into()
+        }).map(|const_val| {
+            if let ConstValue::ByRef(_, allocation, _) = const_val.val {
+                allocation
+            } else {
+                bug!("Matching on non-ByRef static")
+            }
+        })
+    }
+
     pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
         match self.alloc_map.get(&id) {
             // Normal alloc?
             Some(alloc) => Ok(&alloc.1),
             // Static. No need to make any copies, just provide read access to the global static
             // memory in tcx.
-            None => const_eval_static::<M>(self.tcx, id),
+            None => Self::get_static_alloc(self.tcx, id),
         }
     }
 
@@ -380,7 +334,7 @@ pub fn get_fn(&self, ptr: Pointer) -> EvalResult<'tcx, Instance<'tcx>> {
         if ptr.offset.bytes() != 0 {
             return err!(InvalidFunctionPointer);
         }
-        debug!("reading fn ptr: {}", ptr.alloc_id);
+        trace!("reading fn ptr: {}", ptr.alloc_id);
         match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
             Some(AllocType::Function(instance)) => Ok(instance),
             _ => Err(EvalErrorKind::ExecuteMemory.into()),
@@ -497,21 +451,29 @@ pub fn leak_report(&self) -> usize {
 
 /// Byte accessors
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    /// This checks alignment!
-    fn get_bytes_unchecked(
+    /// The last argument controls whether we error out when there are undefined
+    /// or pointer bytes.  You should never call this, call `get_bytes` or
+    /// `get_bytes_with_undef_and_ptr` instead,
+    fn get_bytes_internal(
         &self,
         ptr: Pointer,
         size: Size,
         align: Align,
+        check_defined_and_ptr: bool,
     ) -> EvalResult<'tcx, &[u8]> {
-        // Zero-sized accesses can use dangling pointers,
-        // but they still have to be aligned and non-NULL
+        assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        if size.bytes() == 0 {
-            return Ok(&[]);
-        }
         // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
-        self.check_bounds(ptr.offset(size, self)?, true)?;
+        self.check_bounds(ptr.offset(size, &*self)?, true)?;
+
+        if check_defined_and_ptr {
+            self.check_defined(ptr, size)?;
+            self.check_relocations(ptr, size)?;
+        } else {
+            // We still don't want relocations on the *edges*
+            self.check_relocation_edges(ptr, size)?;
+        }
+
         let alloc = self.get(ptr.alloc_id)?;
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         assert_eq!(size.bytes() as usize as u64, size.bytes());
@@ -519,48 +481,45 @@ fn get_bytes_unchecked(
         Ok(&alloc.bytes[offset..offset + size.bytes() as usize])
     }
 
-    /// This checks alignment!
-    fn get_bytes_unchecked_mut(
+    #[inline]
+    fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
+        self.get_bytes_internal(ptr, size, align, true)
+    }
+
+    /// It is the caller's responsibility to handle undefined and pointer bytes.
+    /// However, this still checks that there are no relocations on the egdes.
+    #[inline]
+    fn get_bytes_with_undef_and_ptr(
+        &self,
+        ptr: Pointer,
+        size: Size,
+        align: Align
+    ) -> EvalResult<'tcx, &[u8]> {
+        self.get_bytes_internal(ptr, size, align, false)
+    }
+
+    /// Just calling this already marks everything as defined and removes relocations,
+    /// so be sure to actually put data there!
+    fn get_bytes_mut(
         &mut self,
         ptr: Pointer,
         size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &mut [u8]> {
-        // Zero-sized accesses can use dangling pointers,
-        // but they still have to be aligned and non-NULL
+        assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        if size.bytes() == 0 {
-            return Ok(&mut []);
-        }
         // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
-        self.check_bounds(ptr.offset(size, &*self)?, true)?;
+        self.check_bounds(ptr.offset(size, &self)?, true)?;
+
+        self.mark_definedness(ptr, size, true)?;
+        self.clear_relocations(ptr, size)?;
+
         let alloc = self.get_mut(ptr.alloc_id)?;
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         assert_eq!(size.bytes() as usize as u64, size.bytes());
         let offset = ptr.offset.bytes() as usize;
         Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize])
     }
-
-    fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
-        assert_ne!(size.bytes(), 0);
-        if self.relocations(ptr, size)?.len() != 0 {
-            return err!(ReadPointerAsBytes);
-        }
-        self.check_defined(ptr, size)?;
-        self.get_bytes_unchecked(ptr, size, align)
-    }
-
-    fn get_bytes_mut(
-        &mut self,
-        ptr: Pointer,
-        size: Size,
-        align: Align,
-    ) -> EvalResult<'tcx, &mut [u8]> {
-        assert_ne!(size.bytes(), 0);
-        self.clear_relocations(ptr, size)?;
-        self.mark_definedness(ptr, size, true)?;
-        self.get_bytes_unchecked_mut(ptr, size, align)
-    }
 }
 
 /// Reading and writing
@@ -609,7 +568,7 @@ fn deep_copy_static(
         id: AllocId,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx> {
-        let alloc = const_eval_static::<M>(self.tcx, id)?;
+        let alloc = Self::get_static_alloc(self.tcx, id)?;
         if alloc.mutability == Mutability::Immutable {
             return err!(ModifiedConstantMemory);
         }
@@ -648,11 +607,12 @@ pub fn copy_repeatedly(
         }
         let src = src.to_ptr()?;
         let dest = dest.to_ptr()?;
-        self.check_relocation_edges(src, size)?;
 
         // first copy the relocations to a temporary buffer, because
         // `get_bytes_mut` will clear the relocations, which is correct,
         // since we don't want to keep any relocations at the target.
+        // (`get_bytes_with_undef_and_ptr` below checks that there are no
+        // relocations overlapping the edges; those would not be handled correctly).
         let relocations = {
             let relocations = self.relocations(src, size)?;
             let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
@@ -670,8 +630,8 @@ pub fn copy_repeatedly(
             new_relocations
         };
 
-        // This also checks alignment.
-        let src_bytes = self.get_bytes_unchecked(src, size, src_align)?.as_ptr();
+        // This also checks alignment, and relocation edges on the src.
+        let src_bytes = self.get_bytes_with_undef_and_ptr(src, size, src_align)?.as_ptr();
         let dest_bytes = self.get_bytes_mut(dest, size * length, dest_align)?.as_mut_ptr();
 
         // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
@@ -704,8 +664,9 @@ pub fn copy_repeatedly(
             }
         }
 
+        // copy definedness to the destination
         self.copy_undef_mask(src, dest, size, length)?;
-        // copy back the relocations
+        // copy the relocations to the destination
         self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations);
 
         Ok(())
@@ -718,9 +679,7 @@ pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
         match alloc.bytes[offset..].iter().position(|&c| c == 0) {
             Some(size) => {
                 let p1 = Size::from_bytes((size + 1) as u64);
-                if self.relocations(ptr, p1)?.len() != 0 {
-                    return err!(ReadPointerAsBytes);
-                }
+                self.check_relocations(ptr, p1)?;
                 self.check_defined(ptr, p1)?;
                 Ok(&alloc.bytes[offset..offset + size])
             }
@@ -771,11 +730,10 @@ pub fn read_scalar(
         ptr_align: Align,
         size: Size
     ) -> EvalResult<'tcx, ScalarMaybeUndef> {
-        // Make sure we don't read part of a pointer as a pointer
-        self.check_relocation_edges(ptr, size)?;
-        let endianness = self.endianness();
-        // get_bytes_unchecked tests alignment
-        let bytes = self.get_bytes_unchecked(ptr, size, ptr_align.min(self.int_align(size)))?;
+        // get_bytes_unchecked tests alignment and relocation edges
+        let bytes = self.get_bytes_with_undef_and_ptr(
+            ptr, size, ptr_align.min(self.int_align(size))
+        )?;
         // Undef check happens *after* we established that the alignment is correct.
         // We must not return Ok() for unaligned pointers!
         if !self.is_defined(ptr, size)? {
@@ -784,12 +742,11 @@ pub fn read_scalar(
             return Ok(ScalarMaybeUndef::Undef);
         }
         // Now we do the actual reading
-        let bits = read_target_uint(endianness, bytes).unwrap();
+        let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap();
         // See if we got a pointer
         if size != self.pointer_size() {
-            if self.relocations(ptr, size)?.len() != 0 {
-                return err!(ReadPointerAsBytes);
-            }
+            // *Now* better make sure that the inside also is free of relocations.
+            self.check_relocations(ptr, size)?;
         } else {
             let alloc = self.get(ptr.alloc_id)?;
             match alloc.relocations.get(&ptr.offset) {
@@ -801,10 +758,7 @@ pub fn read_scalar(
             }
         }
         // We don't. Just return the bits.
-        Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
-            bits,
-            size: size.bytes() as u8,
-        }))
+        Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
     }
 
     pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align)
@@ -820,8 +774,6 @@ pub fn write_scalar(
         val: ScalarMaybeUndef,
         type_size: Size,
     ) -> EvalResult<'tcx> {
-        let endianness = self.endianness();
-
         let val = match val {
             ScalarMaybeUndef::Scalar(scalar) => scalar,
             ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
@@ -835,7 +787,7 @@ pub fn write_scalar(
 
             Scalar::Bits { bits, size } => {
                 assert_eq!(size as u64, type_size.bytes());
-                assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
                     "Unexpected value of size {} when writing to memory", size);
                 bits
             },
@@ -843,8 +795,9 @@ pub fn write_scalar(
 
         {
             // get_bytes_mut checks alignment
+            let endian = self.tcx.data_layout.endian;
             let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?;
-            write_target_uint(endianness, dst, bytes).unwrap();
+            write_target_uint(endian, dst, bytes).unwrap();
         }
 
         // See if we have to also write a relocation
@@ -884,16 +837,35 @@ fn int_align(&self, size: Size) -> Align {
 
 /// Relocations
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
+    /// Return all relocations overlapping with the given ptr-offset pair.
     fn relocations(
         &self,
         ptr: Pointer,
         size: Size,
     ) -> EvalResult<'tcx, &[(Size, AllocId)]> {
+        // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
+        // the beginning of this range.
         let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1);
-        let end = ptr.offset + size;
+        let end = ptr.offset + size; // this does overflow checking
         Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end))
     }
 
+    /// Check that there ar eno relocations overlapping with the given range.
+    #[inline(always)]
+    fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+        if self.relocations(ptr, size)?.len() != 0 {
+            err!(ReadPointerAsBytes)
+        } else {
+            Ok(())
+        }
+    }
+
+    /// Remove all relocations inside the given range.
+    /// If there are relocations overlapping with the edges, they
+    /// are removed as well *and* the bytes they cover are marked as
+    /// uninitialized.  This is a somewhat odd "spooky action at a distance",
+    /// but it allows strictly more code to run than if we would just error
+    /// immediately in that case.
     fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
         // Find the start and end of the given range and its outermost relocations.
         let (first, last) = {
@@ -926,12 +898,12 @@ fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
         Ok(())
     }
 
+    /// Error if there are relocations overlapping with the egdes of the
+    /// given memory range.
+    #[inline]
     fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
-        let overlapping_start = self.relocations(ptr, Size::ZERO)?.len();
-        let overlapping_end = self.relocations(ptr.offset(size, self)?, Size::ZERO)?.len();
-        if overlapping_start + overlapping_end != 0 {
-            return err!(ReadPointerAsBytes);
-        }
+        self.check_relocations(ptr, Size::ZERO)?;
+        self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?;
         Ok(())
     }
 }
index 462c4b8889dd1977dc06c8154a388ac92fe56c6e..1e8de02923240652af9a56a30e1b601b82a9f1c3 100644 (file)
@@ -17,6 +17,7 @@
 mod machine;
 mod memory;
 mod operator;
+mod snapshot;
 mod step;
 mod terminator;
 mod traits;
index 9681b705d7eba1d28f8e2a5efee2fb4025ccd6be..4093a6304b360d19e2d849a26c5da07db1a0165a 100644 (file)
 use std::convert::TryInto;
 
 use rustc::{mir, ty};
-use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
+use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
 use rustc_data_structures::indexed_vec::Idx;
-
 use rustc::mir::interpret::{
-    GlobalId, ConstValue, Scalar, EvalResult, Pointer, ScalarMaybeUndef, EvalErrorKind
+    GlobalId, AllocId,
+    ConstValue, Pointer, Scalar, ScalarMaybeUndef,
+    EvalResult, EvalErrorKind
 };
 use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind};
 
@@ -31,9 +32,9 @@
 /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
 /// defined on `Value`, and do not have to work with a `Place`.
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Value {
-    Scalar(ScalarMaybeUndef),
-    ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef),
+pub enum Value<Id=AllocId> {
+    Scalar(ScalarMaybeUndef<Id>),
+    ScalarPair(ScalarMaybeUndef<Id>, ScalarMaybeUndef<Id>),
 }
 
 impl<'tcx> Value {
@@ -42,10 +43,7 @@ pub fn new_slice(
         len: u64,
         cx: impl HasDataLayout
     ) -> Self {
-        Value::ScalarPair(val.into(), Scalar::Bits {
-            bits: len as u128,
-            size: cx.data_layout().pointer_size.bytes() as u8,
-        }.into())
+        Value::ScalarPair(val.into(), Scalar::from_uint(len, cx.data_layout().pointer_size).into())
     }
 
     pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
@@ -84,11 +82,16 @@ pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
     }
 }
 
+impl_stable_hash_for!(enum ::interpret::Value {
+    Scalar(x),
+    ScalarPair(x, y),
+});
+
 // ScalarPair needs a type to interpret, so we often have a value and a type together
 // as input for binary and cast operations.
 #[derive(Copy, Clone, Debug)]
 pub struct ValTy<'tcx> {
-    pub value: Value,
+    value: Value,
     pub layout: TyLayout<'tcx>,
 }
 
@@ -104,22 +107,12 @@ fn deref(&self) -> &Value {
 /// or still in memory.  The latter is an optimization, to delay reading that chunk of
 /// memory and to avoid having to store arbitrary-sized data here.
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Operand {
-    Immediate(Value),
-    Indirect(MemPlace),
+pub enum Operand<Id=AllocId> {
+    Immediate(Value<Id>),
+    Indirect(MemPlace<Id>),
 }
 
 impl Operand {
-    #[inline]
-    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
-        Operand::Indirect(MemPlace::from_ptr(ptr, align))
-    }
-
-    #[inline]
-    pub fn from_scalar_value(val: Scalar) -> Self {
-        Operand::Immediate(Value::Scalar(val.into()))
-    }
-
     #[inline]
     pub fn to_mem_place(self) -> MemPlace {
         match self {
@@ -139,9 +132,14 @@ pub fn to_immediate(self) -> Value {
     }
 }
 
+impl_stable_hash_for!(enum ::interpret::Operand {
+    Immediate(x),
+    Indirect(x),
+});
+
 #[derive(Copy, Clone, Debug)]
 pub struct OpTy<'tcx> {
-    crate op: Operand, // ideally we'd make this private, but we are not there yet
+    crate op: Operand, // ideally we'd make this private, but const_prop needs this
     pub layout: TyLayout<'tcx>,
 }
 
@@ -187,23 +185,6 @@ fn eq(&self, other: &Self) -> bool {
 }
 impl<'tcx> Eq for OpTy<'tcx> {}
 
-impl<'tcx> OpTy<'tcx> {
-    #[inline]
-    pub fn from_ptr(ptr: Pointer, align: Align, layout: TyLayout<'tcx>) -> Self {
-        OpTy { op: Operand::from_ptr(ptr, align), layout }
-    }
-
-    #[inline]
-    pub fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
-        OpTy { op: Operand::from_ptr(ptr, layout.align), layout }
-    }
-
-    #[inline]
-    pub fn from_scalar_value(val: Scalar, layout: TyLayout<'tcx>) -> Self {
-        OpTy { op: Operand::Immediate(Value::Scalar(val.into())), layout }
-    }
-}
-
 // Use the existing layout if given (but sanity check in debug mode),
 // or compute the layout.
 #[inline(always)]
@@ -510,7 +491,7 @@ pub(super) fn const_value_to_op(
             ConstValue::ByRef(id, alloc, offset) => {
                 // We rely on mutability being set correctly in that allocation to prevent writes
                 // where none should happen -- and for `static mut`, we copy on demand anyway.
-                Ok(Operand::from_ptr(Pointer::new(id, offset), alloc.align))
+                Ok(Operand::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)))
             },
             ConstValue::ScalarPair(a, b) =>
                 Ok(Operand::Immediate(Value::ScalarPair(a.into(), b))),
index 13ed527e3496b6e6929ee1828aad9b4d66a014a9..d07d37d43b13e64a7eaa958bacae83018b10e185 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::mir;
-use rustc::ty::{self, layout::TyLayout};
+use rustc::ty::{self, layout::{Size, TyLayout}};
 use syntax::ast::FloatTy;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
@@ -28,7 +28,7 @@ pub fn binop_with_overflow(
         right: ValTy<'tcx>,
         dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
-        let (val, overflowed) = self.binary_op(op, left, right)?;
+        let (val, overflowed) = self.binary_op_val(op, left, right)?;
         let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
         self.write_value(val, dest)
     }
@@ -42,7 +42,7 @@ pub fn binop_ignore_overflow(
         right: ValTy<'tcx>,
         dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
-        let (val, _overflowed) = self.binary_op(op, left, right)?;
+        let (val, _overflowed) = self.binary_op_val(op, left, right)?;
         self.write_scalar(val, dest)
     }
 }
@@ -105,10 +105,8 @@ macro_rules! float_math {
             ($ty:path, $size:expr) => {{
                 let l = <$ty>::from_bits(l);
                 let r = <$ty>::from_bits(r);
-                let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>| Scalar::Bits {
-                    bits: res.value.to_bits(),
-                    size: $size,
-                };
+                let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>|
+                    Scalar::from_uint(res.value.to_bits(), Size::from_bytes($size));
                 let val = match bin_op {
                     Eq => Scalar::from_bool(l == r),
                     Ne => Scalar::from_bool(l != r),
@@ -169,10 +167,7 @@ fn binary_int_op(
                 }
             };
             let truncated = self.truncate(result, left_layout);
-            return Ok((Scalar::Bits {
-                bits: truncated,
-                size: size.bytes() as u8,
-            }, oflo));
+            return Ok((Scalar::from_uint(truncated, size), oflo));
         }
 
         // For the remaining ops, the types must be the same on both sides
@@ -220,7 +215,7 @@ fn binary_int_op(
                     Rem | Div => {
                         // int_min / -1
                         if r == -1 && l == (1 << (size.bits() - 1)) {
-                            return Ok((Scalar::Bits { bits: l, size: size.bytes() as u8 }, true));
+                            return Ok((Scalar::from_uint(l, size), true));
                         }
                     },
                     _ => {},
@@ -232,16 +227,14 @@ fn binary_int_op(
                     let max = 1 << (size.bits() - 1);
                     oflo = result >= max || result < -max;
                 }
+                // this may be out-of-bounds for the result type, so we have to truncate ourselves
                 let result = result as u128;
                 let truncated = self.truncate(result, left_layout);
-                return Ok((Scalar::Bits {
-                    bits: truncated,
-                    size: size.bytes() as u8,
-                }, oflo));
+                return Ok((Scalar::from_uint(truncated, size), oflo));
             }
         }
 
-        let size = left_layout.size.bytes() as u8;
+        let size = left_layout.size;
 
         // only ints left
         let val = match bin_op {
@@ -253,11 +246,12 @@ fn binary_int_op(
             Gt => Scalar::from_bool(l > r),
             Ge => Scalar::from_bool(l >= r),
 
-            BitOr => Scalar::Bits { bits: l | r, size },
-            BitAnd => Scalar::Bits { bits: l & r, size },
-            BitXor => Scalar::Bits { bits: l ^ r, size },
+            BitOr => Scalar::from_uint(l | r, size),
+            BitAnd => Scalar::from_uint(l & r, size),
+            BitXor => Scalar::from_uint(l ^ r, size),
 
             Add | Sub | Mul | Rem | Div => {
+                debug_assert!(!left_layout.abi.is_signed());
                 let op: fn(u128, u128) -> (u128, bool) = match bin_op {
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
@@ -270,10 +264,7 @@ fn binary_int_op(
                 };
                 let (result, oflo) = op(l, r);
                 let truncated = self.truncate(result, left_layout);
-                return Ok((Scalar::Bits {
-                    bits: truncated,
-                    size,
-                }, oflo || truncated != result));
+                return Ok((Scalar::from_uint(truncated, size), oflo || truncated != result));
             }
 
             _ => {
@@ -291,16 +282,31 @@ fn binary_int_op(
         Ok((val, false))
     }
 
+    /// Convenience wrapper that's useful when keeping the layout together with the
+    /// value.
+    #[inline]
+    pub fn binary_op_val(
+        &self,
+        bin_op: mir::BinOp,
+        left: ValTy<'tcx>,
+        right: ValTy<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        self.binary_op(
+            bin_op,
+            left.to_scalar()?, left.layout,
+            right.to_scalar()?, right.layout,
+        )
+    }
+
     /// Returns the result of the specified operation and whether it overflowed.
     pub fn binary_op(
         &self,
         bin_op: mir::BinOp,
-        ValTy { value: left, layout: left_layout }: ValTy<'tcx>,
-        ValTy { value: right, layout: right_layout }: ValTy<'tcx>,
+        left: Scalar,
+        left_layout: TyLayout<'tcx>,
+        right: Scalar,
+        right_layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, (Scalar, bool)> {
-        let left = left.to_scalar()?;
-        let right = right.to_scalar()?;
-
         trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})",
             bin_op, left, left_layout.ty, right, right_layout.ty);
 
@@ -331,15 +337,13 @@ pub fn binary_op(
                     right_layout.ty.is_fn());
 
                 // Handle operations that support pointer values
-                if let Some(handled) =
-                    M::try_ptr_op(self, bin_op, left, left_layout, right, right_layout)?
-                {
-                    return Ok(handled);
+                if left.is_ptr() || right.is_ptr() || bin_op == mir::BinOp::Offset {
+                    return M::ptr_op(self, bin_op, left, left_layout, right, right_layout);
                 }
 
                 // Everything else only works with "proper" bits
-                let left = left.to_bits(left_layout.size)?;
-                let right = right.to_bits(right_layout.size)?;
+                let left = left.to_bits(left_layout.size).expect("we checked is_ptr");
+                let right = right.to_bits(right_layout.size).expect("we checked is_ptr");
                 self.binary_int_op(bin_op, left, left_layout, right, right_layout)
             }
         }
@@ -373,7 +377,7 @@ pub fn unary_op(
                     (Neg, FloatTy::F64) => Double::to_bits(-Double::from_bits(val)),
                     _ => bug!("Invalid float op {:?}", un_op)
                 };
-                Ok(Scalar::Bits { bits: res, size: layout.size.bytes() as u8 })
+                Ok(Scalar::from_uint(res, layout.size))
             }
             _ => {
                 assert!(layout.ty.is_integral());
@@ -386,10 +390,7 @@ pub fn unary_op(
                     }
                 };
                 // res needs tuncating
-                Ok(Scalar::Bits {
-                    bits: self.truncate(res, layout),
-                    size: layout.size.bytes() as u8,
-                })
+                Ok(Scalar::from_uint(self.truncate(res, layout), layout.size))
             }
         }
     }
index 0a6fef3008433c04283d247bbba0d41a357cf315..51a4294452719656c0e14d0a56b48c7b56184ea7 100644 (file)
 
 use std::convert::TryFrom;
 
+use rustc::ich::StableHashingContext;
 use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 
 use rustc::mir::interpret::{
-    GlobalId, Scalar, EvalResult, Pointer, ScalarMaybeUndef
+    GlobalId, AllocId, Scalar, EvalResult, Pointer, ScalarMaybeUndef, PointerArithmetic
 };
 use super::{EvalContext, Machine, Value, ValTy, Operand, OpTy, MemoryKind};
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub struct MemPlace {
+pub struct MemPlace<Id=AllocId> {
     /// A place may have an integral pointer for ZSTs, and since it might
     /// be turned back into a reference before ever being dereferenced.
     /// However, it may never be undef.
-    pub ptr: Scalar,
+    pub ptr: Scalar<Id>,
     pub align: Align,
     /// Metadata for unsized places.  Interpretation is up to the type.
     /// Must not be present for sized types, but can be missing for unsized types
     /// (e.g. `extern type`).
-    pub extra: Option<Scalar>,
+    pub extra: Option<Scalar<Id>>,
 }
 
+impl_stable_hash_for!(struct ::interpret::MemPlace {
+    ptr,
+    align,
+    extra,
+});
+
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Place {
+pub enum Place<Id=AllocId> {
     /// A place referring to a value allocated in the `Memory` system.
-    Ptr(MemPlace),
+    Ptr(MemPlace<Id>),
 
     /// To support alloc-free locals, we are able to write directly to a local.
     /// (Without that optimization, we'd just always be a `MemPlace`.)
@@ -50,6 +58,21 @@ pub enum Place {
     },
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for Place {
+    fn hash_stable<W: StableHasherResult>(
+        &self, hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>) {
+
+        match self {
+            Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher),
+
+            Place::Local { frame, local } => {
+                frame.hash_stable(hcx, hasher);
+                local.hash_stable(hcx, hasher);
+            },
+        }
+    }
+}
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceTy<'tcx> {
     place: Place,
@@ -344,10 +367,7 @@ pub fn mplace_subslice(
             ty::Array(inner, _) =>
                 (None, self.tcx.mk_array(inner, inner_len)),
             ty::Slice(..) => {
-                let len = Scalar::Bits {
-                    bits: inner_len.into(),
-                    size: self.memory.pointer_size().bytes() as u8
-                };
+                let len = Scalar::from_uint(inner_len, self.pointer_size());
                 (Some(len), base.layout.ty)
             }
             _ =>
@@ -625,6 +645,8 @@ pub fn copy_op(
         src: OpTy<'tcx>,
         dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
+        assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
+            "Cannot copy unsized data");
         assert_eq!(src.layout.size, dest.layout.size,
             "Size mismatch when copying!\nsrc: {:#?}\ndest: {:#?}", src, dest);
 
@@ -716,10 +738,7 @@ pub fn write_discriminant_index(
                 let discr_val = (discr_val << shift) >> shift;
 
                 let discr_dest = self.place_field(dest, 0)?;
-                self.write_scalar(Scalar::Bits {
-                    bits: discr_val,
-                    size: size.bytes() as u8,
-                }, discr_dest)?;
+                self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
             }
             layout::Variants::NicheFilling {
                 dataful_variant,
@@ -733,10 +752,10 @@ pub fn write_discriminant_index(
                         self.place_field(dest, 0)?;
                     let niche_value = ((variant_index - niche_variants.start()) as u128)
                         .wrapping_add(niche_start);
-                    self.write_scalar(Scalar::Bits {
-                        bits: niche_value,
-                        size: niche_dest.layout.size.bytes() as u8,
-                    }, niche_dest)?;
+                    self.write_scalar(
+                        Scalar::from_uint(niche_value, niche_dest.layout.size),
+                        niche_dest
+                    )?;
                 }
             }
         }
@@ -766,11 +785,11 @@ pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>)
         let layout = self.layout_of(ty)?;
 
         // More sanity checks
-        let (size, align) = self.read_size_and_align_from_vtable(vtable)?;
-        assert_eq!(size, layout.size);
-        assert_eq!(align.abi(), layout.align.abi()); // only ABI alignment is preserved
-        // FIXME: More checks for the vtable? We could make sure it is exactly
-        // the one one would expect for this type.
+        if cfg!(debug_assertions) {
+            let (size, align) = self.read_size_and_align_from_vtable(vtable)?;
+            assert_eq!(size, layout.size);
+            assert_eq!(align.abi(), layout.align.abi()); // only ABI alignment is preserved
+        }
 
         let mplace = MPlaceTy {
             mplace: MemPlace { extra: None, ..*mplace },
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
new file mode 100644 (file)
index 0000000..8aa053b
--- /dev/null
@@ -0,0 +1,411 @@
+//! This module contains the machinery necessary to detect infinite loops
+//! during const-evaluation by taking snapshots of the state of the interpreter
+//! at regular intervals.
+
+use std::hash::{Hash, Hasher};
+
+use rustc::ich::{StableHashingContext, StableHashingContextProvider};
+use rustc::mir;
+use rustc::mir::interpret::{
+    AllocId, Pointer, Scalar, ScalarMaybeUndef,
+    Relocations, Allocation, UndefMask,
+    EvalResult, EvalErrorKind,
+};
+
+use rustc::ty::{self, TyCtxt};
+use rustc::ty::layout::Align;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use syntax::ast::Mutability;
+use syntax::source_map::Span;
+
+use super::eval_context::{LocalValue, StackPopCleanup};
+use super::{Frame, Memory, Machine, Operand, MemPlace, Place, Value};
+
+pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
+    /// The set of all `EvalSnapshot` *hashes* observed by this detector.
+    ///
+    /// When a collision occurs in this table, we store the full snapshot in
+    /// `snapshots`.
+    hashes: FxHashSet<u64>,
+
+    /// The set of all `EvalSnapshot`s observed by this detector.
+    ///
+    /// An `EvalSnapshot` will only be fully cloned once it has caused a
+    /// collision in `hashes`. As a result, the detector must observe at least
+    /// *two* full cycles of an infinite loop before it triggers.
+    snapshots: FxHashSet<EvalSnapshot<'a, 'mir, 'tcx, M>>,
+}
+
+impl<'a, 'mir, 'tcx, M> Default for InfiniteLoopDetector<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+          'tcx: 'a + 'mir,
+{
+    fn default() -> Self {
+        InfiniteLoopDetector {
+            hashes: FxHashSet::default(),
+            snapshots: FxHashSet::default(),
+        }
+    }
+}
+
+impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+          'tcx: 'a + 'mir,
+{
+    /// Returns `true` if the loop detector has not yet observed a snapshot.
+    pub fn is_empty(&self) -> bool {
+        self.hashes.is_empty()
+    }
+
+    pub fn observe_and_analyze(
+        &mut self,
+        tcx: &TyCtxt<'b, 'tcx, 'tcx>,
+        machine: &M,
+        memory: &Memory<'a, 'mir, 'tcx, M>,
+        stack: &[Frame<'mir, 'tcx>],
+    ) -> EvalResult<'tcx, ()> {
+
+        let mut hcx = tcx.get_stable_hashing_context();
+        let mut hasher = StableHasher::<u64>::new();
+        (machine, stack).hash_stable(&mut hcx, &mut hasher);
+        let hash = hasher.finish();
+
+        if self.hashes.insert(hash) {
+            // No collision
+            return Ok(())
+        }
+
+        info!("snapshotting the state of the interpreter");
+
+        if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) {
+            // Spurious collision or first cycle
+            return Ok(())
+        }
+
+        // Second cycle
+        Err(EvalErrorKind::InfiniteLoop.into())
+    }
+}
+
+trait SnapshotContext<'a> {
+    fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>;
+}
+
+/// Taking a snapshot of the evaluation context produces a view of
+/// the state of the interpreter that is invariant to `AllocId`s.
+trait Snapshot<'a, Ctx: SnapshotContext<'a>> {
+    type Item;
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item;
+}
+
+macro_rules! __impl_snapshot_field {
+    ($field:ident, $ctx:expr) => ($field.snapshot($ctx));
+    ($field:ident, $ctx:expr, $delegate:expr) => ($delegate);
+}
+
+macro_rules! impl_snapshot_for {
+    // FIXME(mark-i-m): Some of these should be `?` rather than `*`.
+    (enum $enum_name:ident {
+        $( $variant:ident $( ( $($field:ident $(-> $delegate:expr)*),* ) )* ),* $(,)*
+    }) => {
+
+        impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name
+            where Ctx: self::SnapshotContext<'a>,
+        {
+            type Item = $enum_name<AllocIdSnapshot<'a>>;
+
+            #[inline]
+            fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
+                match *self {
+                    $(
+                        $enum_name::$variant $( ( $(ref $field),* ) )* =>
+                            $enum_name::$variant $(
+                                ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),* ),
+                            )*
+                    )*
+                }
+            }
+        }
+    };
+
+    // FIXME(mark-i-m): same here.
+    (struct $struct_name:ident { $($field:ident $(-> $delegate:expr)*),*  $(,)* }) => {
+        impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name
+            where Ctx: self::SnapshotContext<'a>,
+        {
+            type Item = $struct_name<AllocIdSnapshot<'a>>;
+
+            #[inline]
+            fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
+                let $struct_name {
+                    $(ref $field),*
+                } = *self;
+
+                $struct_name {
+                    $( $field: __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),*
+                }
+            }
+        }
+    };
+}
+
+impl<'a, Ctx, T> Snapshot<'a, Ctx> for Option<T>
+    where Ctx: SnapshotContext<'a>,
+          T: Snapshot<'a, Ctx>
+{
+    type Item = Option<<T as Snapshot<'a, Ctx>>::Item>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        match self {
+            Some(x) => Some(x.snapshot(ctx)),
+            None => None,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq)]
+struct AllocIdSnapshot<'a>(Option<AllocationSnapshot<'a>>);
+
+impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = AllocIdSnapshot<'a>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx)))
+    }
+}
+
+impl_snapshot_for!(struct Pointer {
+    alloc_id,
+    offset -> *offset,
+});
+
+impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = Scalar<AllocIdSnapshot<'a>>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        match self {
+            Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)),
+            Scalar::Bits{ size, bits } => Scalar::Bits {
+                size: *size,
+                bits: *bits,
+            },
+        }
+    }
+}
+
+impl_snapshot_for!(enum ScalarMaybeUndef {
+    Scalar(s),
+    Undef,
+});
+
+impl_snapshot_for!(struct MemPlace {
+    ptr,
+    extra,
+    align -> *align,
+});
+
+impl<'a, Ctx> Snapshot<'a, Ctx> for Place
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = Place<AllocIdSnapshot<'a>>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        match self {
+            Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)),
+
+            Place::Local{ frame, local } => Place::Local{
+                frame: *frame,
+                local: *local,
+            },
+        }
+    }
+}
+
+impl_snapshot_for!(enum Value {
+    Scalar(s),
+    ScalarPair(s, t),
+});
+
+impl_snapshot_for!(enum Operand {
+    Immediate(v),
+    Indirect(m),
+});
+
+impl_snapshot_for!(enum LocalValue {
+    Live(v),
+    Dead,
+});
+
+impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = Relocations<AllocIdSnapshot<'a>>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        Relocations::from_presorted(self.iter()
+            .map(|(size, id)| (*size, id.snapshot(ctx)))
+            .collect())
+    }
+}
+
+#[derive(Eq, PartialEq)]
+struct AllocationSnapshot<'a> {
+    bytes: &'a [u8],
+    relocations: Relocations<AllocIdSnapshot<'a>>,
+    undef_mask: &'a UndefMask,
+    align: &'a Align,
+    mutability: &'a Mutability,
+}
+
+impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = AllocationSnapshot<'a>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        let Allocation { bytes, relocations, undef_mask, align, mutability } = self;
+
+        AllocationSnapshot {
+            bytes,
+            undef_mask,
+            align,
+            mutability,
+            relocations: relocations.snapshot(ctx),
+        }
+    }
+}
+
+#[derive(Eq, PartialEq)]
+struct FrameSnapshot<'a, 'tcx: 'a> {
+    instance: &'a ty::Instance<'tcx>,
+    span: &'a Span,
+    return_to_block: &'a StackPopCleanup,
+    return_place: Place<AllocIdSnapshot<'a>>,
+    locals: IndexVec<mir::Local, LocalValue<AllocIdSnapshot<'a>>>,
+    block: &'a mir::BasicBlock,
+    stmt: usize,
+}
+
+impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = FrameSnapshot<'a, 'tcx>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        let Frame {
+            mir: _,
+            instance,
+            span,
+            return_to_block,
+            return_place,
+            locals,
+            block,
+            stmt,
+        } = self;
+
+        FrameSnapshot {
+            instance,
+            span,
+            return_to_block,
+            block,
+            stmt: *stmt,
+            return_place: return_place.snapshot(ctx),
+            locals: locals.iter().map(|local| local.snapshot(ctx)).collect(),
+        }
+    }
+}
+
+#[derive(Eq, PartialEq)]
+struct MemorySnapshot<'a, 'mir: 'a, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx> + 'a> {
+    data: &'a M::MemoryData,
+}
+
+impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{
+    fn snapshot<'b: 'a>(&'b self) -> MemorySnapshot<'b, 'mir, 'tcx, M> {
+        let Memory { data, .. } = self;
+        MemorySnapshot { data }
+    }
+}
+
+impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{
+    fn resolve(&'b self, id: &AllocId) -> Option<&'b Allocation> {
+        self.get(*id).ok()
+    }
+}
+
+/// The virtual machine state during const-evaluation at a given point in time.
+struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
+    machine: M,
+    memory: Memory<'a, 'mir, 'tcx, M>,
+    stack: Vec<Frame<'mir, 'tcx>>,
+}
+
+impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{
+    fn new(
+        machine: &M,
+        memory: &Memory<'a, 'mir, 'tcx, M>,
+        stack: &[Frame<'mir, 'tcx>]) -> Self {
+
+        EvalSnapshot {
+            machine: machine.clone(),
+            memory: memory.clone(),
+            stack: stack.into(),
+        }
+    }
+
+    fn snapshot<'b: 'a>(&'b self)
+        -> (&'b M, MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>) {
+        let EvalSnapshot{ machine, memory, stack } = self;
+        (&machine, memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
+    }
+}
+
+impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2)
+        let mut hcx = self.memory.tcx.get_stable_hashing_context();
+        let mut hasher = StableHasher::<u64>::new();
+        self.hash_stable(&mut hcx, &mut hasher);
+        hasher.finish().hash(state)
+    }
+}
+
+impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>>
+    for EvalSnapshot<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'b>,
+        hasher: &mut StableHasher<W>) {
+
+        let EvalSnapshot{ machine, memory, stack } = self;
+        (machine, &memory.data, stack).hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a, 'mir, 'tcx, M> Eq for EvalSnapshot<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{}
+
+impl<'a, 'mir, 'tcx, M> PartialEq for EvalSnapshot<'a, 'mir, 'tcx, M>
+    where M: Machine<'mir, 'tcx>,
+{
+    fn eq(&self, other: &Self) -> bool {
+        self.snapshot() == other.snapshot()
+    }
+}
index 933f06d3d10a0b9da935d2f70ec44c769913fdc2..545333e8791760fd29306e59154c4e51b972d271 100644 (file)
@@ -14,7 +14,7 @@
 
 use rustc::mir;
 use rustc::ty::layout::LayoutOf;
-use rustc::mir::interpret::{EvalResult, Scalar};
+use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic};
 
 use super::{EvalContext, Machine};
 
@@ -73,7 +73,12 @@ pub fn inc_step_counter_and_detect_loops(&mut self) -> EvalResult<'tcx, ()> {
                 "Constant evaluating a complex constant, this might take some time");
         }
 
-        self.loop_detector.observe_and_analyze(&self.machine, &self.stack, &self.memory)
+        self.loop_detector.observe_and_analyze(
+            &self.tcx,
+            &self.machine,
+            &self.memory,
+            &self.stack[..],
+        )
     }
 
     pub fn run(&mut self) -> EvalResult<'tcx> {
@@ -269,12 +274,9 @@ fn eval_rvalue_into_place(
                 let src = self.eval_place(place)?;
                 let mplace = self.force_allocation(src)?;
                 let len = mplace.len(&self)?;
-                let size = self.memory.pointer_size().bytes() as u8;
+                let size = self.pointer_size();
                 self.write_scalar(
-                    Scalar::Bits {
-                        bits: len as u128,
-                        size,
-                    },
+                    Scalar::from_uint(len, size),
                     dest,
                 )?;
             }
@@ -294,12 +296,9 @@ fn eval_rvalue_into_place(
                 let layout = self.layout_of(ty)?;
                 assert!(!layout.is_unsized(),
                         "SizeOf nullary MIR operator called for unsized type");
-                let size = self.memory.pointer_size().bytes() as u8;
+                let size = self.pointer_size();
                 self.write_scalar(
-                    Scalar::Bits {
-                        bits: layout.size.bytes() as u128,
-                        size,
-                    },
+                    Scalar::from_uint(layout.size.bytes(), size),
                     dest,
                 )?;
             }
@@ -313,11 +312,8 @@ fn eval_rvalue_into_place(
             Discriminant(ref place) => {
                 let place = self.eval_place(place)?;
                 let discr_val = self.read_discriminant(self.place_to_op(place)?)?.0;
-                let size = dest.layout.size.bytes() as u8;
-                self.write_scalar(Scalar::Bits {
-                    bits: discr_val,
-                    size,
-                }, dest)?;
+                let size = dest.layout.size;
+                self.write_scalar(Scalar::from_uint(discr_val, size), dest)?;
             }
         }
 
index 11826e0ce0c25897a31a1d2748905df7cc0a8f9e..de8681062740938f62df21db9c279c3b17cfd5d3 100644 (file)
 
 use std::borrow::Cow;
 
-use rustc::mir;
-use rustc::ty::{self, Ty};
-use rustc::ty::layout::LayoutOf;
+use rustc::{mir, ty};
+use rustc::ty::layout::{self, TyLayout, LayoutOf};
 use syntax::source_map::Span;
 use rustc_target::spec::abi::Abi;
 
-use rustc::mir::interpret::{EvalResult, Scalar};
+use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar};
 use super::{
-    EvalContext, Machine, Value, OpTy, Place, PlaceTy, ValTy, Operand, StackPopCleanup
+    EvalContext, Machine, Value, OpTy, Place, PlaceTy, Operand, StackPopCleanup
 };
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -59,14 +58,11 @@ pub(super) fn eval_terminator(
                 let mut target_block = targets[targets.len() - 1];
 
                 for (index, &const_int) in values.iter().enumerate() {
-                    // Compare using binary_op
-                    let const_int = Scalar::Bits {
-                        bits: const_int,
-                        size: discr.layout.size.bytes() as u8
-                    };
+                    // Compare using binary_op, to also support pointer values
+                    let const_int = Scalar::from_uint(const_int, discr.layout.size);
                     let (res, _) = self.binary_op(mir::BinOp::Eq,
-                        discr,
-                        ValTy { value: Value::Scalar(const_int.into()), layout: discr.layout }
+                        discr.to_scalar()?, discr.layout,
+                        const_int, discr.layout,
                     )?;
                     if res.to_bool()? {
                         target_block = targets[index];
@@ -89,37 +85,16 @@ pub(super) fn eval_terminator(
                 };
 
                 let func = self.eval_operand(func, None)?;
-                let (fn_def, sig) = match func.layout.ty.sty {
+                let (fn_def, abi) = match func.layout.ty.sty {
                     ty::FnPtr(sig) => {
+                        let caller_abi = sig.abi();
                         let fn_ptr = self.read_scalar(func)?.to_ptr()?;
                         let instance = self.memory.get_fn(fn_ptr)?;
-                        let instance_ty = instance.ty(*self.tcx);
-                        match instance_ty.sty {
-                            ty::FnDef(..) => {
-                                let sig = self.tcx.normalize_erasing_late_bound_regions(
-                                    self.param_env,
-                                    &sig,
-                                );
-                                let real_sig = instance_ty.fn_sig(*self.tcx);
-                                let real_sig = self.tcx.normalize_erasing_late_bound_regions(
-                                    self.param_env,
-                                    &real_sig,
-                                );
-                                if !self.check_sig_compat(sig, real_sig)? {
-                                    return err!(FunctionPointerTyMismatch(real_sig, sig));
-                                }
-                                (instance, sig)
-                            }
-                            _ => bug!("unexpected fn ptr to ty: {:?}", instance_ty),
-                        }
+                        (instance, caller_abi)
                     }
                     ty::FnDef(def_id, substs) => {
                         let sig = func.layout.ty.fn_sig(*self.tcx);
-                        let sig = self.tcx.normalize_erasing_late_bound_regions(
-                            self.param_env,
-                            &sig,
-                        );
-                        (self.resolve(def_id, substs)?, sig)
+                        (self.resolve(def_id, substs)?, sig.abi())
                     },
                     _ => {
                         let msg = format!("can't handle callee of type {:?}", func.layout.ty);
@@ -129,11 +104,11 @@ pub(super) fn eval_terminator(
                 let args = self.eval_operands(args)?;
                 self.eval_fn_call(
                     fn_def,
+                    terminator.source_info.span,
+                    abi,
                     &args[..],
                     dest,
                     ret,
-                    terminator.source_info.span,
-                    Some(sig),
                 )?;
             }
 
@@ -168,6 +143,7 @@ pub(super) fn eval_terminator(
                 if expected == cond_val {
                     self.goto_block(Some(target))?;
                 } else {
+                    // Compute error message
                     use rustc::mir::interpret::EvalErrorKind::*;
                     return match *msg {
                         BoundsCheck { ref len, ref index } => {
@@ -190,11 +166,11 @@ pub(super) fn eval_terminator(
                 }
             }
 
-            Yield { .. } => unimplemented!("{:#?}", terminator.kind),
-            GeneratorDrop => unimplemented!(),
-            DropAndReplace { .. } => unimplemented!(),
-            Resume => unimplemented!(),
-            Abort => unimplemented!(),
+            Yield { .. } |
+            GeneratorDrop |
+            DropAndReplace { .. } |
+            Resume |
+            Abort => unimplemented!("{:#?}", terminator.kind),
             FalseEdges { .. } => bug!("should have been eliminated by\
                                       `simplify_branches` mir pass"),
             FalseUnwind { .. } => bug!("should have been eliminated by\
@@ -205,91 +181,67 @@ pub(super) fn eval_terminator(
         Ok(())
     }
 
-    /// Decides whether it is okay to call the method with signature `real_sig`
-    /// using signature `sig`.
-    /// FIXME: This should take into account the platform-dependent ABI description.
-    fn check_sig_compat(
-        &mut self,
-        sig: ty::FnSig<'tcx>,
-        real_sig: ty::FnSig<'tcx>,
-    ) -> EvalResult<'tcx, bool> {
-        fn check_ty_compat<'tcx>(ty: Ty<'tcx>, real_ty: Ty<'tcx>) -> bool {
-            if ty == real_ty {
-                return true;
-            } // This is actually a fast pointer comparison
-            return match (&ty.sty, &real_ty.sty) {
-                // Permit changing the pointer type of raw pointers and references as well as
-                // mutability of raw pointers.
-                // FIXME: Should not be allowed when fat pointers are involved.
-                (&ty::RawPtr(_), &ty::RawPtr(_)) => true,
-                (&ty::Ref(_, _, _), &ty::Ref(_, _, _)) => {
-                    ty.is_mutable_pointer() == real_ty.is_mutable_pointer()
-                }
-                // rule out everything else
-                _ => false,
-            };
+    fn check_argument_compat(
+        caller: TyLayout<'tcx>,
+        callee: TyLayout<'tcx>,
+    ) -> bool {
+        if caller.ty == callee.ty {
+            // No question
+            return true;
         }
-
-        if sig.abi == real_sig.abi && sig.variadic == real_sig.variadic &&
-            sig.inputs_and_output.len() == real_sig.inputs_and_output.len() &&
-            sig.inputs_and_output
-                .iter()
-                .zip(real_sig.inputs_and_output)
-                .all(|(ty, real_ty)| check_ty_compat(ty, real_ty))
-        {
-            // Definitely good.
-            return Ok(true);
+        // Compare layout
+        match (&caller.abi, &callee.abi) {
+            (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) =>
+                // Different valid ranges are okay (once we enforce validity,
+                // that will take care to make it UB to leave the range, just
+                // like for transmute).
+                caller.value == callee.value,
+            // Be conservative
+            _ => false
         }
+    }
 
-        if sig.variadic || real_sig.variadic {
-            // We're not touching this
-            return Ok(false);
+    /// Pass a single argument, checking the types for compatibility.
+    fn pass_argument(
+        &mut self,
+        skip_zst: bool,
+        caller_arg: &mut impl Iterator<Item=OpTy<'tcx>>,
+        callee_arg: PlaceTy<'tcx>,
+    ) -> EvalResult<'tcx> {
+        if skip_zst && callee_arg.layout.is_zst() {
+            // Nothing to do.
+            trace!("Skipping callee ZST");
+            return Ok(());
         }
-
-        // We need to allow what comes up when a non-capturing closure is cast to a fn().
-        match (sig.abi, real_sig.abi) {
-            (Abi::Rust, Abi::RustCall) // check the ABIs.  This makes the test here non-symmetric.
-                if check_ty_compat(sig.output(), real_sig.output())
-                    && real_sig.inputs_and_output.len() == 3 => {
-                // First argument of real_sig must be a ZST
-                let fst_ty = real_sig.inputs_and_output[0];
-                if self.layout_of(fst_ty)?.is_zst() {
-                    // Second argument must be a tuple matching the argument list of sig
-                    let snd_ty = real_sig.inputs_and_output[1];
-                    match snd_ty.sty {
-                        ty::Tuple(tys) if sig.inputs().len() == tys.len() =>
-                            if sig.inputs()
-                                .iter()
-                                .zip(tys)
-                                .all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) {
-                                return Ok(true)
-                            },
-                        _ => {}
-                    }
-                }
-            }
-            _ => {}
-        };
-
-        // Nope, this doesn't work.
-        return Ok(false);
+        let caller_arg = caller_arg.next()
+            .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
+        if skip_zst {
+            debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
+        }
+        // Now, check
+        if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) {
+            return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
+        }
+        self.copy_op(caller_arg, callee_arg)
     }
 
     /// Call this function -- pushing the stack frame and initializing the arguments.
-    /// `sig` is optional in case of FnPtr/FnDef -- but mandatory for closures!
     fn eval_fn_call(
         &mut self,
         instance: ty::Instance<'tcx>,
+        span: Span,
+        caller_abi: Abi,
         args: &[OpTy<'tcx>],
         dest: Option<PlaceTy<'tcx>>,
         ret: Option<mir::BasicBlock>,
-        span: Span,
-        sig: Option<ty::FnSig<'tcx>>,
     ) -> EvalResult<'tcx> {
         trace!("eval_fn_call: {:#?}", instance);
 
         match instance.def {
             ty::InstanceDef::Intrinsic(..) => {
+                if caller_abi != Abi::RustIntrinsic {
+                    return err!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic));
+                }
                 // The intrinsic itself cannot diverge, so if we got here without a return
                 // place... (can happen e.g. for transmute returning `!`)
                 let dest = match dest {
@@ -308,6 +260,26 @@ fn eval_fn_call(
             ty::InstanceDef::DropGlue(..) |
             ty::InstanceDef::CloneShim(..) |
             ty::InstanceDef::Item(_) => {
+                // ABI check
+                {
+                    let callee_abi = {
+                        let instance_ty = instance.ty(*self.tcx);
+                        match instance_ty.sty {
+                            ty::FnDef(..) =>
+                                instance_ty.fn_sig(*self.tcx).abi(),
+                            ty::Closure(..) => Abi::RustCall,
+                            ty::Generator(..) => Abi::Rust,
+                            _ => bug!("unexpected callee ty: {:?}", instance_ty),
+                        }
+                    };
+                    // Rust and RustCall are compatible
+                    let normalize_abi = |abi| if abi == Abi::RustCall { Abi::Rust } else { abi };
+                    if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
+                        return err!(FunctionAbiMismatch(caller_abi, callee_abi));
+                    }
+                }
+
+                // We need MIR for this fn
                 let mir = match M::find_fn(self, instance, args, dest, ret)? {
                     Some(mir) => mir,
                     None => return Ok(()),
@@ -325,93 +297,95 @@ fn eval_fn_call(
                     StackPopCleanup::Goto(ret),
                 )?;
 
-                // If we didn't get a signture, ask `fn_sig`
-                let sig = sig.unwrap_or_else(|| {
-                    let fn_sig = instance.ty(*self.tcx).fn_sig(*self.tcx);
-                    self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig)
-                });
-                assert_eq!(sig.inputs().len(), args.len());
-                // We can't test the types, as it is fine if the types are ABI-compatible but
-                // not equal.
-
-                // Figure out how to pass which arguments.
-                // FIXME: Somehow this is horribly full of special cases here, and codegen has
-                // none of that.  What is going on?
-                trace!(
-                    "ABI: {:?}, args: {:#?}",
-                    sig.abi,
-                    args.iter()
-                        .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
-                        .collect::<Vec<_>>()
-                );
-                trace!(
-                    "spread_arg: {:?}, locals: {:#?}",
-                    mir.spread_arg,
-                    mir.args_iter()
-                        .map(|local|
-                            (local, self.layout_of_local(self.cur_frame(), local).unwrap().ty)
-                        )
-                        .collect::<Vec<_>>()
-                );
-
-                // We have two iterators: Where the arguments come from,
-                // and where they go to.
-
-                // For where they come from: If the ABI is RustCall, we untuple the
-                // last incoming argument.  These do not have the same type,
-                // so to keep the code paths uniform we accept an allocation
-                // (for RustCall ABI only).
-                let args_effective : Cow<[OpTy<'tcx>]> =
-                    if sig.abi == Abi::RustCall && !args.is_empty() {
-                        // Untuple
-                        let (&untuple_arg, args) = args.split_last().unwrap();
-                        trace!("eval_fn_call: Will pass last argument by untupling");
-                        Cow::from(args.iter().map(|&a| Ok(a))
-                            .chain((0..untuple_arg.layout.fields.count()).into_iter()
-                                .map(|i| self.operand_field(untuple_arg, i as u64))
+                // We want to pop this frame again in case there was an error, to put
+                // the blame in the right location.  Until the 2018 edition is used in
+                // the compiler, we have to do this with an immediately invoked function.
+                let res = (||{
+                    trace!(
+                        "caller ABI: {:?}, args: {:#?}",
+                        caller_abi,
+                        args.iter()
+                            .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
+                            .collect::<Vec<_>>()
+                    );
+                    trace!(
+                        "spread_arg: {:?}, locals: {:#?}",
+                        mir.spread_arg,
+                        mir.args_iter()
+                            .map(|local|
+                                (local, self.layout_of_local(self.cur_frame(), local).unwrap().ty)
                             )
-                            .collect::<EvalResult<Vec<OpTy<'tcx>>>>()?)
-                    } else {
-                        // Plain arg passing
-                        Cow::from(args)
+                            .collect::<Vec<_>>()
+                    );
+
+                    // Figure out how to pass which arguments.
+                    // We have two iterators: Where the arguments come from,
+                    // and where they go to.
+                    let skip_zst = match caller_abi {
+                        Abi::Rust | Abi::RustCall => true,
+                        _ => false
                     };
 
-                // Now we have to spread them out across the callee's locals,
-                // taking into account the `spread_arg`.
-                let mut args_iter = args_effective.iter();
-                let mut local_iter = mir.args_iter();
-                // HACK: ClosureOnceShim calls something that expects a ZST as
-                // first argument, but the callers do not actually pass that ZST.
-                // Codegen doesn't care because ZST arguments do not even exist there.
-                match instance.def {
-                    ty::InstanceDef::ClosureOnceShim { .. } if sig.abi == Abi::Rust => {
-                        let local = local_iter.next().unwrap();
+                    // For where they come from: If the ABI is RustCall, we untuple the
+                    // last incoming argument.  These two iterators do not have the same type,
+                    // so to keep the code paths uniform we accept an allocation
+                    // (for RustCall ABI only).
+                    let caller_args : Cow<[OpTy<'tcx>]> =
+                        if caller_abi == Abi::RustCall && !args.is_empty() {
+                            // Untuple
+                            let (&untuple_arg, args) = args.split_last().unwrap();
+                            trace!("eval_fn_call: Will pass last argument by untupling");
+                            Cow::from(args.iter().map(|&a| Ok(a))
+                                .chain((0..untuple_arg.layout.fields.count()).into_iter()
+                                    .map(|i| self.operand_field(untuple_arg, i as u64))
+                                )
+                                .collect::<EvalResult<Vec<OpTy<'tcx>>>>()?)
+                        } else {
+                            // Plain arg passing
+                            Cow::from(args)
+                        };
+                    // Skip ZSTs
+                    let mut caller_iter = caller_args.iter()
+                        .filter(|op| !skip_zst || !op.layout.is_zst())
+                        .map(|op| *op);
+
+                    // Now we have to spread them out across the callee's locals,
+                    // taking into account the `spread_arg`.  If we could write
+                    // this is a single iterator (that handles `spread_arg`), then
+                    // `pass_argument` would be the loop body. It takes care to
+                    // not advance `caller_iter` for ZSTs.
+                    let mut locals_iter = mir.args_iter();
+                    while let Some(local) = locals_iter.next() {
                         let dest = self.eval_place(&mir::Place::Local(local))?;
-                        assert!(dest.layout.is_zst());
-                    }
-                    _ => {}
-                }
-                // Now back to norml argument passing.
-                while let Some(local) = local_iter.next() {
-                    let dest = self.eval_place(&mir::Place::Local(local))?;
-                    if Some(local) == mir.spread_arg {
-                        // Must be a tuple
-                        for i in 0..dest.layout.fields.count() {
-                            let dest = self.place_field(dest, i as u64)?;
-                            self.copy_op(*args_iter.next().unwrap(), dest)?;
+                        if Some(local) == mir.spread_arg {
+                            // Must be a tuple
+                            for i in 0..dest.layout.fields.count() {
+                                let dest = self.place_field(dest, i as u64)?;
+                                self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                            }
+                        } else {
+                            // Normal argument
+                            self.pass_argument(skip_zst, &mut caller_iter, dest)?;
                         }
-                    } else {
-                        // Normal argument
-                        self.copy_op(*args_iter.next().unwrap(), dest)?;
                     }
+                    // Now we should have no more caller args
+                    if caller_iter.next().is_some() {
+                        trace!("Caller has too many args over");
+                        return err!(FunctionArgCountMismatch);
+                    }
+                    Ok(())
+                })();
+                match res {
+                    Err(err) => {
+                        self.stack.pop();
+                        Err(err)
+                    }
+                    Ok(v) => Ok(v)
                 }
-                // Now we should be done
-                assert!(args_iter.next().is_none());
-                Ok(())
             }
             // cannot use the shim here, because that will only result in infinite recursion
             ty::InstanceDef::Virtual(_, idx) => {
-                let ptr_size = self.memory.pointer_size();
+                let ptr_size = self.pointer_size();
                 let ptr_align = self.tcx.data_layout.pointer_align;
                 let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
                 let vtable = ptr.vtable()?;
@@ -431,7 +405,7 @@ fn eval_fn_call(
                 args[0].op = Operand::Immediate(Value::Scalar(ptr.ptr.into())); // strip vtable
                 trace!("Patched self operand to {:#?}", args[0]);
                 // recurse with concrete function
-                self.eval_fn_call(instance, &args, dest, ret, span, sig)
+                self.eval_fn_call(instance, span, caller_abi, &args, dest, ret)
             }
         }
     }
@@ -467,11 +441,11 @@ fn drop_in_place(
 
         self.eval_fn_call(
             instance,
+            span,
+            Abi::Rust,
             &[arg],
             Some(dest),
             Some(target),
-            span,
-            None,
         )
     }
 }
index 74567b429749175bbfd6f3a17df1d03a41903290..0e09f65f0a8eaba3b4f370b13cfbfa582401ed7f 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{Size, Align, LayoutOf};
-use rustc::mir::interpret::{Scalar, Pointer, EvalResult};
+use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
 
 use syntax::ast::Mutability;
 
@@ -35,7 +35,7 @@ pub fn get_vtable(
         let size = layout.size.bytes();
         let align = layout.align.abi();
 
-        let ptr_size = self.memory.pointer_size();
+        let ptr_size = self.pointer_size();
         let ptr_align = self.tcx.data_layout.pointer_align;
         let methods = self.tcx.vtable_methods(trait_ref);
         let vtable = self.memory.allocate(
@@ -49,15 +49,10 @@ pub fn get_vtable(
         self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?;
 
         let size_ptr = vtable.offset(ptr_size, &self)?;
-        self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::Bits {
-            bits: size as u128,
-            size: ptr_size.bytes() as u8,
-        }.into())?;
+        self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::from_uint(size, ptr_size).into())?;
         let align_ptr = vtable.offset(ptr_size * 2, &self)?;
-        self.memory.write_ptr_sized(align_ptr, ptr_align, Scalar::Bits {
-            bits: align as u128,
-            size: ptr_size.bytes() as u8,
-        }.into())?;
+        self.memory.write_ptr_sized(align_ptr, ptr_align,
+            Scalar::from_uint(align, ptr_size).into())?;
 
         for (i, method) in methods.iter().enumerate() {
             if let Some((def_id, substs)) = *method {
@@ -97,7 +92,7 @@ pub fn read_size_and_align_from_vtable(
         &self,
         vtable: Pointer,
     ) -> EvalResult<'tcx, (Size, Align)> {
-        let pointer_size = self.memory.pointer_size();
+        let pointer_size = self.pointer_size();
         let pointer_align = self.tcx.data_layout.pointer_align;
         let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)?
             .to_bits(pointer_size)? as u64;
index d50fd6e13c1069b137cf35c4ea443747436ea7c2..329651f038f8bd8d5d5a85b0ad652f92819ce22a 100644 (file)
@@ -15,7 +15,7 @@
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
-    Scalar, AllocType, EvalResult, ScalarMaybeUndef, EvalErrorKind
+    Scalar, AllocType, EvalResult, ScalarMaybeUndef, EvalErrorKind, PointerArithmetic
 };
 
 use super::{
@@ -118,7 +118,25 @@ fn validate_scalar(
                 bits
             },
             Scalar::Ptr(_) => {
-                let ptr_size = self.memory.pointer_size();
+                match ty.sty {
+                    ty::Bool |
+                    ty::Char |
+                    ty::Float(_) |
+                    ty::Int(_) |
+                    ty::Uint(_) => {
+                        return validation_failure!(
+                                "a pointer",
+                                path,
+                                format!("the type {}", ty.sty)
+                            );
+                    }
+                    ty::RawPtr(_) |
+                    ty::Ref(_, _, _) |
+                    ty::FnPtr(_) => {}
+                    _ => { unreachable!(); }
+                }
+
+                let ptr_size = self.pointer_size();
                 let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
                 return if lo > hi {
                     if lo - hi == 1 {
@@ -376,6 +394,7 @@ pub fn validate_operand(
                                         "non-pointer vtable in fat pointer", path
                                     ),
                             }
+                            // FIXME: More checks for the vtable.
                         }
                         ty::Slice(..) | ty::Str => {
                             match ptr.extra.unwrap().to_usize(self) {
index f91ff3642cd10638149313a876f1f11f4f19386c..be04f75c7260c3dfe8699c7592745961fe0b797a 100644 (file)
@@ -23,7 +23,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
-#![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
 #![cfg_attr(stage0, feature(macro_vis_matcher))]
@@ -38,6 +37,7 @@
 #![feature(slice_concat_ext)]
 #![feature(if_while_or_patterns)]
 #![feature(try_from)]
+#![feature(reverse_bits)]
 
 #![recursion_limit="256"]
 
@@ -93,7 +93,6 @@ pub fn provide(providers: &mut Providers) {
     shim::provide(providers);
     transform::provide(providers);
     providers.const_eval = interpret::const_eval_provider;
-    providers.const_to_allocation = interpret::const_to_allocation_provider;
     providers.check_match = hair::pattern::check_match;
 }
 
index c480fa4124665763d516c763247c327b70b1b449..fd094ffc1cf4f7fd02d09f4bff3cde03224a44ab 100644 (file)
 //! inlining, even when they are not marked #[inline].
 
 use monomorphize::collector::InliningMap;
-use rustc::dep_graph::WorkProductId;
+use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor};
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
 use rustc::hir::map::DefPathData;
@@ -150,6 +150,15 @@ fn work_product_id(&self) -> WorkProductId {
         WorkProductId::from_cgu_name(&self.name().as_str())
     }
 
+    fn work_product(&self, tcx: TyCtxt) -> WorkProduct {
+        let work_product_id = self.work_product_id();
+        tcx.dep_graph
+           .previous_work_product(&work_product_id)
+           .unwrap_or_else(|| {
+                panic!("Could not find work-product for CGU `{}`", self.name())
+            })
+    }
+
     fn items_in_deterministic_order<'a>(&self,
                                         tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                         -> Vec<(MonoItem<'tcx>,
@@ -194,6 +203,10 @@ fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
         items
     }
+
+    fn codegen_dep_node(&self, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> DepNode {
+        DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name().clone()))
+    }
 }
 
 impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
index f6006ae045ee787e238d520d2c2836378fafab30..ec7fd371a442bb8ca406751b2953587379eb3173 100644 (file)
@@ -28,6 +28,7 @@
 
 pub struct UnsafetyChecker<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
+    min_const_fn: bool,
     source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
     violations: Vec<UnsafetyViolation>,
     source_info: SourceInfo,
@@ -38,12 +39,16 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
-    fn new(mir: &'a Mir<'tcx>,
-           source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
-           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: ty::ParamEnv<'tcx>) -> Self {
+    fn new(
+        min_const_fn: bool,
+        mir: &'a Mir<'tcx>,
+        source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Self {
         Self {
             mir,
+            min_const_fn,
             source_scope_local_data,
             violations: vec![],
             source_info: SourceInfo {
@@ -269,6 +274,15 @@ fn require_unsafe(&mut self,
     fn register_violations(&mut self,
                            violations: &[UnsafetyViolation],
                            unsafe_blocks: &[(ast::NodeId, bool)]) {
+        if self.min_const_fn {
+            for violation in violations {
+                let mut violation = violation.clone();
+                violation.kind = UnsafetyViolationKind::MinConstFn;
+                if !self.violations.contains(&violation) {
+                    self.violations.push(violation)
+                }
+            }
+        }
         let within_unsafe = match self.source_scope_local_data[self.source_info.scope].safety {
             Safety::Safe => {
                 for violation in violations {
@@ -276,7 +290,6 @@ fn register_violations(&mut self,
                         self.violations.push(violation.clone())
                     }
                 }
-
                 false
             }
             Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
@@ -369,6 +382,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 
     let param_env = tcx.param_env(def_id);
     let mut checker = UnsafetyChecker::new(
+        tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id),
         mir, source_scope_local_data, tcx, param_env);
     checker.visit_mir(mir);
 
@@ -478,6 +492,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                     .note(&details.as_str()[..])
                     .emit();
             }
+            UnsafetyViolationKind::MinConstFn => {
+                tcx.sess.struct_span_err(
+                    source_info.span,
+                    &format!("{} is unsafe and unsafe operations \
+                            are not allowed in const fn", description))
+                    .span_label(source_info.span, &description.as_str()[..])
+                    .note(&details.as_str()[..])
+                    .emit();
+            }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
                 tcx.lint_node_note(SAFE_EXTERN_STATICS,
                               lint_node_id,
index 1715930dbb61cc6ab276edfca09b7f71ca07db58..e2b1a255eaca29fba90b48c664c84f5b27b2e5c0 100644 (file)
@@ -22,7 +22,7 @@
 };
 use rustc::ty::{TyCtxt, self, Instance};
 use interpret::{EvalContext, CompileTimeEvaluator, eval_promoted, mk_borrowck_eval_cx};
-use interpret::{Value, OpTy, MemoryKind};
+use interpret::{self, Value, OpTy, MemoryKind};
 use transform::{MirPass, MirSource};
 use syntax::source_map::{Span, DUMMY_SP};
 use rustc::ty::subst::Substs;
@@ -153,7 +153,9 @@ fn use_ecx<F, T>(
                     | MachineError(_)
                     // at runtime these transformations might make sense
                     // FIXME: figure out the rules and start linting
-                    | FunctionPointerTyMismatch(..)
+                    | FunctionAbiMismatch(..)
+                    | FunctionArgMismatch(..)
+                    | FunctionArgCountMismatch
                     // fine at runtime, might be a register address or sth
                     | ReadBytesAsPointer
                     // fine at runtime
@@ -356,13 +358,15 @@ fn const_prop(
             Rvalue::Len(_) => None,
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
                 type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
-                    OpTy::from_scalar_value(
-                        Scalar::Bits {
-                            bits: n as u128,
-                            size: self.tcx.data_layout.pointer_size.bytes() as u8,
-                        },
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ),
+                    OpTy {
+                        op: interpret::Operand::Immediate(Value::Scalar(
+                            Scalar::Bits {
+                                bits: n as u128,
+                                size: self.tcx.data_layout.pointer_size.bytes() as u8,
+                            }.into()
+                        )),
+                        layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+                    },
                     span,
                 )))
             }
@@ -397,7 +401,11 @@ fn const_prop(
                     // Now run the actual operation.
                     this.ecx.unary_op(op, prim, arg.layout)
                 })?;
-                Some((OpTy::from_scalar_value(val, place_layout), span))
+                let res = OpTy {
+                    op: interpret::Operand::Immediate(Value::Scalar(val.into())),
+                    layout: place_layout,
+                };
+                Some((res, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -452,7 +460,7 @@ fn const_prop(
                 })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
                 let (val, overflow) = self.use_ecx(source_info, |this| {
-                    this.ecx.binary_op(op, l, r)
+                    this.ecx.binary_op_val(op, l, r)
                 })?;
                 let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
                     Value::ScalarPair(
@@ -468,7 +476,7 @@ fn const_prop(
                     Value::Scalar(val.into())
                 };
                 let res = OpTy {
-                    op: ::interpret::Operand::Immediate(val),
+                    op: interpret::Operand::Immediate(val),
                     layout: place_layout,
                 };
                 Some((res, span))
index e9afa7df5c4f23d7536c8c445e576e7342c32414..dcbf92b57b13a2a895a0ee897fd44b1b20eb4aad 100644 (file)
@@ -67,9 +67,9 @@
 use rustc::ty::subst::Substs;
 use util::dump_mir;
 use util::liveness::{self, IdentityMap};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_set::IdxSet;
-use std::collections::HashMap;
 use std::borrow::Cow;
 use std::iter::once;
 use std::mem;
@@ -142,10 +142,12 @@ struct TransformVisitor<'a, 'tcx: 'a> {
     state_field: usize,
 
     // Mapping from Local to (type of local, generator struct index)
-    remap: HashMap<Local, (Ty<'tcx>, usize)>,
+    // FIXME(eddyb) This should use `IndexVec<Local, Option<_>>`.
+    remap: FxHashMap<Local, (Ty<'tcx>, usize)>,
 
     // A map from a suspension point in a block to the locals which have live storage at that point
-    storage_liveness: HashMap<BasicBlock, liveness::LiveVarSet<Local>>,
+    // FIXME(eddyb) This should use `IndexVec<BasicBlock, Option<_>>`.
+    storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
 
     // A list of suspension points, generated during the transform
     suspension_points: Vec<SuspensionPoint>,
@@ -364,12 +366,15 @@ fn visit_rvalue(&mut self,
     }
 }
 
-fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                               mir: &Mir<'tcx>,
-                                               source: MirSource,
-                                               movable: bool) ->
-                                               (liveness::LiveVarSet<Local>,
-                                                HashMap<BasicBlock, liveness::LiveVarSet<Local>>) {
+fn locals_live_across_suspend_points(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &Mir<'tcx>,
+    source: MirSource,
+    movable: bool,
+) -> (
+    liveness::LiveVarSet<Local>,
+    FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
+) {
     let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
     let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
 
@@ -413,7 +418,7 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         &liveness,
     );
 
-    let mut storage_liveness_map = HashMap::new();
+    let mut storage_liveness_map = FxHashMap::default();
 
     for (block, data) in mir.basic_blocks().iter_enumerated() {
         if let TerminatorKind::Yield { .. } = data.terminator().kind {
@@ -477,9 +482,9 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             interior: Ty<'tcx>,
                             movable: bool,
                             mir: &mut Mir<'tcx>)
-    -> (HashMap<Local, (Ty<'tcx>, usize)>,
+    -> (FxHashMap<Local, (Ty<'tcx>, usize)>,
         GeneratorLayout<'tcx>,
-        HashMap<BasicBlock, liveness::LiveVarSet<Local>>)
+        FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>)
 {
     // Use a liveness analysis to compute locals which are live across a suspension point
     let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx,
index 90dfebeef1b0ca7b0bb194b1bc46d3808e2ca251..1e05b07030ef898436f6740b9ebce4076a11d749 100644 (file)
@@ -36,6 +36,7 @@
 pub mod add_call_guards;
 pub mod promote_consts;
 pub mod qualify_consts;
+mod qualify_min_const_fn;
 pub mod remove_noop_landing_pads;
 pub mod dump_mir;
 pub mod deaggregator;
index 36dcd1714716cdd67a2df18b64e017ae5c7c1a43..050901b9b508a7ab7f3cca1c8e8b7eed7dfd3b17 100644 (file)
@@ -127,6 +127,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            mir: &'a Mir<'tcx>,
            mode: Mode)
            -> Qualifier<'a, 'tcx, 'tcx> {
+        assert!(def_id.is_local());
         let mut rpo = traversal::reverse_postorder(mir);
         let temps = promote_consts::collect_temps(mir, &mut rpo);
         rpo.reset();
@@ -825,11 +826,20 @@ fn visit_terminator_kind(&mut self,
                             | "min_align_of"
                             | "type_id"
                             | "bswap"
+                            | "bitreverse"
                             | "ctpop"
                             | "cttz"
                             | "cttz_nonzero"
                             | "ctlz"
-                            | "ctlz_nonzero" => is_const_fn = Some(def_id),
+                            | "ctlz_nonzero"
+                            | "overflowing_add"
+                            | "overflowing_sub"
+                            | "overflowing_mul"
+                            | "unchecked_shl"
+                            | "unchecked_shr"
+                            | "add_with_overflow"
+                            | "sub_with_overflow"
+                            | "mul_with_overflow" => is_const_fn = Some(def_id),
                             "transmute" => {
                                 if self.mode != Mode::Fn {
                                     is_const_fn = Some(def_id);
@@ -916,9 +926,7 @@ fn visit_terminator_kind(&mut self,
                         );
                     }
                 } else if let Some(&attr::Stability {
-                    rustc_const_unstable: Some(attr::RustcConstUnstable {
-                        feature: ref feature_name
-                    }),
+                    const_stability: Some(ref feature_name),
                 .. }) = self.tcx.lookup_stability(def_id) {
                     if
                         // feature-gate is not enabled,
@@ -927,9 +935,6 @@ fn visit_terminator_kind(&mut self,
                             .iter()
                             .any(|&(ref sym, _)| sym == feature_name) &&
 
-                        // this doesn't come from a crate with the feature-gate enabled,
-                        self.def_id.is_local() &&
-
                         // this doesn't come from a macro that has #[allow_internal_unstable]
                         !self.span.allows_unstable()
                     {
@@ -1175,8 +1180,20 @@ fn run_pass<'a, 'tcx>(&self,
             let (temps, candidates) = {
                 let mut qualifier = Qualifier::new(tcx, def_id, mir, mode);
                 if mode == Mode::ConstFn {
-                    // Enforce a constant-like CFG for `const fn`.
-                    qualifier.qualify_const();
+                    if tcx.is_min_const_fn(def_id) {
+                        // enforce `min_const_fn` for stable const fns
+                        use super::qualify_min_const_fn::is_min_const_fn;
+                        if let Err((span, err)) = is_min_const_fn(tcx, def_id, mir) {
+                            tcx.sess.span_err(span, &err);
+                        } else {
+                            // this should not produce any errors, but better safe than sorry
+                            // FIXME(#53819)
+                            qualifier.qualify_const();
+                        }
+                    } else {
+                        // Enforce a constant-like CFG for `const fn`.
+                        qualifier.qualify_const();
+                    }
                 } else {
                     while let Some((bb, data)) = qualifier.rpo.next() {
                         qualifier.visit_basic_block_data(bb, data);
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
new file mode 100644 (file)
index 0000000..56e32ea
--- /dev/null
@@ -0,0 +1,358 @@
+use rustc::hir::def_id::DefId;
+use rustc::hir;
+use rustc::mir::*;
+use rustc::ty::{self, Predicate, TyCtxt};
+use std::borrow::Cow;
+use syntax_pos::Span;
+
+type McfResult = Result<(), (Span, Cow<'static, str>)>;
+
+pub fn is_min_const_fn(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    mir: &'a Mir<'tcx>,
+) -> McfResult {
+    let mut current = def_id;
+    loop {
+        let predicates = tcx.predicates_of(current);
+        for predicate in &predicates.predicates {
+            match predicate {
+                | Predicate::RegionOutlives(_)
+                | Predicate::TypeOutlives(_)
+                | Predicate::WellFormed(_)
+                | Predicate::ConstEvaluatable(..) => continue,
+                | Predicate::ObjectSafe(_) => {
+                    bug!("object safe predicate on function: {:#?}", predicate)
+                }
+                Predicate::ClosureKind(..) => {
+                    bug!("closure kind predicate on function: {:#?}", predicate)
+                }
+                Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
+                Predicate::Projection(_) => {
+                    let span = tcx.def_span(current);
+                    // we'll hit a `Predicate::Trait` later which will report an error
+                    tcx.sess
+                        .delay_span_bug(span, "projection without trait bound");
+                    continue;
+                }
+                Predicate::Trait(pred) => {
+                    if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
+                        continue;
+                    }
+                    match pred.skip_binder().self_ty().sty {
+                        ty::Param(ref p) => {
+                            let generics = tcx.generics_of(current);
+                            let def = generics.type_param(p, tcx);
+                            let span = tcx.def_span(def.def_id);
+                            return Err((
+                                span,
+                                "trait bounds other than `Sized` \
+                                 on const fn parameters are unstable"
+                                    .into(),
+                            ));
+                        }
+                        // other kinds of bounds are either tautologies
+                        // or cause errors in other passes
+                        _ => continue,
+                    }
+                }
+            }
+        }
+        match predicates.parent {
+            Some(parent) => current = parent,
+            None => break,
+        }
+    }
+
+    for local in mir.vars_iter() {
+        return Err((
+            mir.local_decls[local].source_info.span,
+            "local variables in const fn are unstable".into(),
+        ));
+    }
+    for local in &mir.local_decls {
+        check_ty(tcx, local.ty, local.source_info.span)?;
+    }
+    // impl trait is gone in MIR, so check the return type manually
+    check_ty(
+        tcx,
+        tcx.fn_sig(def_id).output().skip_binder(),
+        mir.local_decls.iter().next().unwrap().source_info.span,
+    )?;
+
+    for bb in mir.basic_blocks() {
+        check_terminator(tcx, mir, bb.terminator())?;
+        for stmt in &bb.statements {
+            check_statement(tcx, mir, stmt)?;
+        }
+    }
+    Ok(())
+}
+
+fn check_ty(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    span: Span,
+) -> McfResult {
+    for ty in ty.walk() {
+        match ty.sty {
+            ty::Ref(_, _, hir::Mutability::MutMutable) => return Err((
+                span,
+                "mutable references in const fn are unstable".into(),
+            )),
+            ty::Anon(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+            ty::FnPtr(..) => {
+                return Err((span, "function pointers in const fn are unstable".into()))
+            }
+            ty::Dynamic(preds, _) => {
+                for pred in preds.iter() {
+                    match pred.skip_binder() {
+                        | ty::ExistentialPredicate::AutoTrait(_)
+                        | ty::ExistentialPredicate::Projection(_) => {
+                            return Err((
+                                span,
+                                "trait bounds other than `Sized` \
+                                 on const fn parameters are unstable"
+                                    .into(),
+                            ))
+                        }
+                        ty::ExistentialPredicate::Trait(trait_ref) => {
+                            if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() {
+                                return Err((
+                                    span,
+                                    "trait bounds other than `Sized` \
+                                     on const fn parameters are unstable"
+                                        .into(),
+                                ));
+                            }
+                        }
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+    Ok(())
+}
+
+fn check_rvalue(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    rvalue: &Rvalue<'tcx>,
+    span: Span,
+) -> McfResult {
+    match rvalue {
+        Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
+            check_operand(tcx, mir, operand, span)
+        }
+        Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
+            check_place(tcx, mir, place, span, PlaceMode::Read)
+        }
+        Rvalue::Cast(_, operand, cast_ty) => {
+            use rustc::ty::cast::CastTy;
+            let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast");
+            let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+            match (cast_in, cast_out) {
+                (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => Err((
+                    span,
+                    "casting pointers to ints is unstable in const fn".into(),
+                )),
+                (CastTy::RPtr(_), CastTy::Float) => bug!(),
+                (CastTy::RPtr(_), CastTy::Int(_)) => bug!(),
+                (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(),
+                _ => check_operand(tcx, mir, operand, span),
+            }
+        }
+        // binops are fine on integers
+        Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
+            check_operand(tcx, mir, lhs, span)?;
+            check_operand(tcx, mir, rhs, span)?;
+            let ty = lhs.ty(mir, tcx);
+            if ty.is_integral() || ty.is_bool() || ty.is_char() {
+                Ok(())
+            } else {
+                Err((
+                    span,
+                    "only int, `bool` and `char` operations are stable in const fn".into(),
+                ))
+            }
+        }
+        // checked by regular const fn checks
+        Rvalue::NullaryOp(..) => Ok(()),
+        Rvalue::UnaryOp(_, operand) => {
+            let ty = operand.ty(mir, tcx);
+            if ty.is_integral() || ty.is_bool() {
+                check_operand(tcx, mir, operand, span)
+            } else {
+                Err((
+                    span,
+                    "only int and `bool` operations are stable in const fn".into(),
+                ))
+            }
+        }
+        Rvalue::Aggregate(_, operands) => {
+            for operand in operands {
+                check_operand(tcx, mir, operand, span)?;
+            }
+            Ok(())
+        }
+    }
+}
+
+enum PlaceMode {
+    Assign,
+    Read,
+}
+
+fn check_statement(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    statement: &Statement<'tcx>,
+) -> McfResult {
+    let span = statement.source_info.span;
+    match &statement.kind {
+        StatementKind::Assign(place, rval) => {
+            check_place(tcx, mir, place, span, PlaceMode::Assign)?;
+            check_rvalue(tcx, mir, rval, span)
+        }
+
+        StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())),
+
+        // just an assignment
+        StatementKind::SetDiscriminant { .. } => Ok(()),
+
+        | StatementKind::InlineAsm { .. } => {
+            Err((span, "cannot use inline assembly in const fn".into()))
+        }
+
+        // These are all NOPs
+        | StatementKind::StorageLive(_)
+        | StatementKind::StorageDead(_)
+        | StatementKind::Validate(..)
+        | StatementKind::EndRegion(_)
+        | StatementKind::UserAssertTy(..)
+        | StatementKind::Nop => Ok(()),
+    }
+}
+
+fn check_operand(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    operand: &Operand<'tcx>,
+    span: Span,
+) -> McfResult {
+    match operand {
+        Operand::Move(place) | Operand::Copy(place) => {
+            check_place(tcx, mir, place, span, PlaceMode::Read)
+        }
+        Operand::Constant(_) => Ok(()),
+    }
+}
+
+fn check_place(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    place: &Place<'tcx>,
+    span: Span,
+    mode: PlaceMode,
+) -> McfResult {
+    match place {
+        Place::Local(l) => match mode {
+            PlaceMode::Assign => match mir.local_kind(*l) {
+                LocalKind::Temp | LocalKind::ReturnPointer => Ok(()),
+                LocalKind::Arg | LocalKind::Var => {
+                    Err((span, "assignments in const fn are unstable".into()))
+                }
+            },
+            PlaceMode::Read => Ok(()),
+        },
+        // promoteds are always fine, they are essentially constants
+        Place::Promoted(_) => Ok(()),
+        Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
+        Place::Projection(proj) => {
+            match proj.elem {
+                | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {
+                    check_place(tcx, mir, &proj.base, span, mode)
+                }
+                // slice patterns are unstable
+                | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
+                    return Err((span, "slice patterns in const fn are unstable".into()))
+                }
+                | ProjectionElem::Downcast(..) => {
+                    Err((span, "`match` or `if let` in `const fn` is unstable".into()))
+                }
+            }
+        }
+    }
+}
+
+fn check_terminator(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    terminator: &Terminator<'tcx>,
+) -> McfResult {
+    let span = terminator.source_info.span;
+    match &terminator.kind {
+        | TerminatorKind::Goto { .. }
+        | TerminatorKind::Return
+        | TerminatorKind::Resume => Ok(()),
+
+        TerminatorKind::Drop { location, .. } => {
+            check_place(tcx, mir, location, span, PlaceMode::Read)
+        }
+        TerminatorKind::DropAndReplace { location, value, .. } => {
+            check_place(tcx, mir, location, span, PlaceMode::Read)?;
+            check_operand(tcx, mir, value, span)
+        },
+        TerminatorKind::SwitchInt { .. } => Err((
+            span,
+            "`if`, `match`, `&&` and `||` are not stable in const fn".into(),
+        )),
+        | TerminatorKind::Abort | TerminatorKind::Unreachable => {
+            Err((span, "const fn with unreachable code is not stable".into()))
+        }
+        | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
+            Err((span, "const fn generators are unstable".into()))
+        }
+
+        TerminatorKind::Call {
+            func,
+            args,
+            destination: _,
+            cleanup: _,
+        } => {
+            let fn_ty = func.ty(mir, tcx);
+            if let ty::FnDef(def_id, _) = fn_ty.sty {
+                if tcx.is_min_const_fn(def_id) {
+                    check_operand(tcx, mir, func, span)?;
+
+                    for arg in args {
+                        check_operand(tcx, mir, arg, span)?;
+                    }
+                    Ok(())
+                } else {
+                    Err((
+                        span,
+                        "can only call other `min_const_fn` within a `min_const_fn`".into(),
+                    ))
+                }
+            } else {
+                Err((span, "can only call other const fns within const fn".into()))
+            }
+        }
+
+        TerminatorKind::Assert {
+            cond,
+            expected: _,
+            msg: _,
+            target: _,
+            cleanup: _,
+        } => check_operand(tcx, mir, cond, span),
+
+        | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!(
+            terminator.source_info.span,
+            "min_const_fn encountered `{:#?}`",
+            terminator
+        ),
+    }
+}
index fca1c7f27ab37a590274385579ca5b7cf94a2efe..ea4fba3e1248182af89e6b6b99149195c9045e0e 100644 (file)
@@ -178,9 +178,7 @@ fn handle_const_fn_call(&mut self, def_id: DefId,
         }
 
         if let Some(&attr::Stability {
-            rustc_const_unstable: Some(attr::RustcConstUnstable {
-                                           feature: ref feature_name
-                                       }),
+            const_stability: Some(ref feature_name),
             .. }) = self.tcx.lookup_stability(def_id) {
             let stable_check =
                 // feature-gate is enabled,
@@ -189,9 +187,6 @@ fn handle_const_fn_call(&mut self, def_id: DefId,
                     .iter()
                     .any(|&(ref sym, _)| sym == feature_name) ||
 
-                    // this comes from a crate with the feature-gate enabled,
-                    !def_id.is_local() ||
-
                     // this comes from a macro that has #[allow_internal_unstable]
                     span.allows_unstable();
             if !stable_check {
@@ -582,7 +577,7 @@ fn check_expr_kind<'a, 'tcx>(
             for index in hirvec_arm.iter() {
                 let _ = v.check_expr(&*index.body);
                 match index.guard {
-                    Some(ref expr) => {
+                    Some(hir::Guard::If(ref expr)) => {
                         let _ = v.check_expr(&expr);
                     },
                     None => {},
index 62405150cd29a5d3c6ed07258e5211eeab3a3759..f093d672498ad4b2483ad71133cb43b4a38cd852 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 
 #![cfg_attr(not(stage0), feature(nll))]
 #![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
index b1ab86674cf90fa74388effcfa7b49e6c403f3a3..6c10ac7ea5ceaf230f7b449f877237a37b9785ca 100644 (file)
@@ -12,6 +12,7 @@
 
 use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
 use rustc::session::Session;
+use rustc::util::nodemap::FxHashMap;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
 use syntax::ext::base::MacroExpanderFn;
@@ -21,7 +22,6 @@
 use syntax::feature_gate::AttributeType;
 use syntax_pos::Span;
 
-use std::collections::HashMap;
 use std::borrow::ToOwned;
 
 /// Structure used to register plugins.
@@ -53,7 +53,7 @@ pub struct Registry<'a> {
     pub late_lint_passes: Vec<LateLintPassObject>,
 
     #[doc(hidden)]
-    pub lint_groups: HashMap<&'static str, Vec<LintId>>,
+    pub lint_groups: FxHashMap<&'static str, (Vec<LintId>, Option<&'static str>)>,
 
     #[doc(hidden)]
     pub llvm_passes: Vec<String>,
@@ -74,7 +74,7 @@ pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
             syntax_exts: vec![],
             early_lint_passes: vec![],
             late_lint_passes: vec![],
-            lint_groups: HashMap::new(),
+            lint_groups: FxHashMap::default(),
             llvm_passes: vec![],
             attributes: vec![],
             whitelisted_custom_derives: Vec::new(),
@@ -170,8 +170,15 @@ pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) {
         self.late_lint_passes.push(lint_pass);
     }
     /// Register a lint group.
-    pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
-        self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
+    pub fn register_lint_group(
+        &mut self,
+        name: &'static str,
+        deprecated_name: Option<&'static str>,
+        to: Vec<&'static Lint>
+    ) {
+        self.lint_groups.insert(name,
+                                (to.into_iter().map(|x| LintId::of(x)).collect(),
+                                 deprecated_name));
     }
 
     /// Register an LLVM pass.
index 5166f69ba03304c49572d760cb514139184e2436..4245136ef213174cf3e16ffb8a8358636fa2d4f4 100644 (file)
@@ -686,7 +686,9 @@ fn def_id_visibility(&self, did: DefId) -> ty::Visibility {
                         // visibility to within the crate.
                         let struct_def_id = self.tcx.hir.get_parent_did(node_id);
                         let adt_def = self.tcx.adt_def(struct_def_id);
-                        if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
+                        if adt_def.non_enum_variant().is_field_list_non_exhaustive()
+                            && ctor_vis == ty::Visibility::Public
+                        {
                             ctor_vis = ty::Visibility::Restricted(
                                 DefId::local(CRATE_DEF_INDEX));
                         }
index 80f6c263e199969648d80321edbe79fb49ad4612..37868a83e342168727f1623c8f2b0e7c5724cca4 100644 (file)
@@ -181,6 +181,23 @@ fn build_reduced_graph_for_use_tree(
                     self.session.features_untracked().uniform_paths);
 
             let source = module_path[0];
+
+            // HACK(eddyb) For `use x::{self, ...};`, use the ID of the
+            // `self` nested import for the canary. This allows the
+            // ambiguity reporting scope to ignore false positives
+            // in the same way it does for `use x;` (by comparing IDs).
+            let mut canary_id = id;
+            if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
+                for &(ref use_tree, id) in items {
+                    if let ast::UseTreeKind::Simple(..) = use_tree.kind {
+                        if use_tree.ident().name == keywords::SelfValue.name() {
+                            canary_id = id;
+                            break;
+                        }
+                    }
+                }
+            }
+
             // Helper closure to emit a canary with the given base path.
             let emit = |this: &mut Self, base: Option<Ident>| {
                 let subclass = SingleImport {
@@ -200,7 +217,7 @@ fn build_reduced_graph_for_use_tree(
                     base.into_iter().collect(),
                     subclass.clone(),
                     source.span,
-                    id,
+                    canary_id,
                     root_use_tree.span,
                     root_id,
                     ty::Visibility::Invisible,
index 78c518aea961da2b419c07ca4370c5aa7bbff5f7..65fe01ff96aa561f2c6e2e101764aa25552090f1 100644 (file)
@@ -70,7 +70,7 @@
 use syntax::ptr::P;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -221,9 +221,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let sugg_msg = "try using a local type parameter instead";
             if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
-                err.span_suggestion(sugg_span,
-                                    sugg_msg,
-                                    new_snippet);
+                err.span_suggestion_with_applicability(
+                    sugg_span,
+                    sugg_msg,
+                    new_snippet,
+                    Applicability::MachineApplicable,
+                );
             } else if let Some(sp) = cm.generate_fn_name_span(span) {
                 err.span_label(sp, "try adding a local type parameter in this method instead");
             } else {
@@ -1409,6 +1412,7 @@ pub struct Resolver<'a, 'b: 'a> {
     crate_loader: &'a mut CrateLoader<'b>,
     macro_names: FxHashSet<Ident>,
     macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
+    unshadowable_attrs: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Def>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
     macro_defs: FxHashMap<Mark, DefId>,
@@ -1726,6 +1730,7 @@ pub fn new(session: &'a Session,
             crate_loader,
             macro_names: FxHashSet(),
             macro_prelude: FxHashMap(),
+            unshadowable_attrs: FxHashMap(),
             all_macros: FxHashMap(),
             macro_map: FxHashMap(),
             invocations,
@@ -2698,7 +2703,10 @@ fn resolve_arm(&mut self, arm: &Arm) {
         // This has to happen *after* we determine which pat_idents are variants
         self.check_consistent_bindings(&arm.pats);
 
-        walk_list!(self, visit_expr, &arm.guard);
+        match arm.guard {
+            Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
+            _ => {}
+        }
         self.visit_expr(&arm.body);
 
         self.ribs[ValueNS].pop();
@@ -3004,8 +3012,12 @@ fn smart_resolve_path_fragment(&mut self,
                                         enum_path);
                         err.help(&msg);
                     } else {
-                        err.span_suggestion(span, "you can try using the variant's enum",
-                                            enum_path);
+                        err.span_suggestion_with_applicability(
+                            span,
+                            "you can try using the variant's enum",
+                            enum_path,
+                            Applicability::MachineApplicable,
+                        );
                     }
                 }
             }
@@ -3014,20 +3026,32 @@ fn smart_resolve_path_fragment(&mut self,
                     let self_is_available = this.self_value_is_available(path[0].span, span);
                     match candidate {
                         AssocSuggestion::Field => {
-                            err.span_suggestion(span, "try",
-                                                format!("self.{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("self.{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                             if !self_is_available {
                                 err.span_label(span, format!("`self` value is only available in \
                                                                methods with `self` parameter"));
                             }
                         }
                         AssocSuggestion::MethodWithSelf if self_is_available => {
-                            err.span_suggestion(span, "try",
-                                                format!("self.{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("self.{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                         }
                         AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
-                            err.span_suggestion(span, "try",
-                                                format!("Self::{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("Self::{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                         }
                     }
                     return (err, candidates);
@@ -4662,15 +4686,16 @@ fn report_conflict<'b>(&mut self,
                     format!("other_{}", name)
                 };
 
-                err.span_suggestion(binding.span,
-                                    rename_msg,
-                                    if snippet.ends_with(';') {
-                                        format!("{} as {};",
-                                                &snippet[..snippet.len()-1],
-                                                suggested_name)
-                                    } else {
-                                        format!("{} as {}", snippet, suggested_name)
-                                    });
+                err.span_suggestion_with_applicability(
+                    binding.span,
+                    rename_msg,
+                    if snippet.ends_with(';') {
+                        format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name)
+                    } else {
+                        format!("{} as {}", snippet, suggested_name)
+                    },
+                    Applicability::MachineApplicable,
+                );
             } else {
                 err.span_label(binding.span, rename_msg);
             }
index 879b4ea3fe579f8568aeb1b685af9760e46e932e..f403e09b7f768c54d812fd1bccac338d5b9e4fb6 100644 (file)
@@ -207,6 +207,23 @@ fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
         self.macro_prelude.insert(ident.name, binding);
     }
 
+    fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
+        let def_id = DefId {
+            krate: BUILTIN_MACROS_CRATE,
+            index: DefIndex::from_array_index(self.macro_map.len(),
+                                              DefIndexAddressSpace::Low),
+        };
+        let kind = ext.kind();
+        self.macro_map.insert(def_id, ext);
+        let binding = self.arenas.alloc_name_binding(NameBinding {
+            kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
+            span: DUMMY_SP,
+            vis: ty::Visibility::Invisible,
+            expansion: Mark::root(),
+        });
+        self.unshadowable_attrs.insert(ident.name, binding);
+    }
+
     fn resolve_imports(&mut self) {
         ImportResolver { resolver: self }.resolve_imports()
     }
@@ -462,6 +479,12 @@ pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind,
             return def;
         }
 
+        if kind == MacroKind::Attr {
+            if let Some(ext) = self.unshadowable_attrs.get(&path[0].name) {
+                return Ok(ext.def());
+            }
+        }
+
         let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false);
         let result = if let Some((legacy_binding, _)) = legacy_resolution {
             Ok(legacy_binding.def())
index c60f9293d58e71428481cec776465b558a81d418..73c9af0d11c47f155046f52d018720fd4b2a6aee 100644 (file)
@@ -664,6 +664,14 @@ struct UniformPathsCanaryResult {
 
                 self.per_ns(|_, ns| {
                     if let Some(result) = result[ns].get().ok() {
+                        if let NameBindingKind::Import { directive, .. } = result.kind {
+                            // Skip canaries that resolve to the import itself.
+                            // These come from `use crate_name;`, which isn't really
+                            // ambiguous, as the import can't actually shadow itself.
+                            if directive.id == import.id {
+                                return;
+                            }
+                        }
                         if has_explicit_self {
                             // There should only be one `self::x` (module-scoped) canary.
                             assert_eq!(canary_results[ns].module_scope, None);
@@ -718,22 +726,6 @@ struct UniformPathsCanaryResult {
 
                 errors = true;
 
-                // Special-case the error when `self::x` finds its own `use x;`.
-                if has_external_crate &&
-                   results.module_scope == Some(span) &&
-                   results.block_scopes.is_empty() {
-                    let msg = format!("`{}` import is redundant", name);
-                    this.session.struct_span_err(span, &msg)
-                        .span_label(span,
-                            format!("refers to external crate `::{}`", name))
-                        .span_label(span,
-                            format!("defines `self::{}`, shadowing itself", name))
-                        .help(&format!("remove or write `::{}` explicitly instead", name))
-                        .note("relative `use` paths enabled by `#![feature(uniform_paths)]`")
-                        .emit();
-                    return;
-                }
-
                 let msg = format!("`{}` import is ambiguous", name);
                 let mut err = this.session.struct_span_err(span, &msg);
                 let mut suggestion_choices = String::new();
index dc9310cdcdaa40990e0cf71db31a6b41896ef0a1..d719d257f352c6a9d61cd017a2cab3a665f24183 100644 (file)
@@ -91,7 +91,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> {
     // of macro use (callsite) spans. We store these to ensure
     // we only write one macro def per unique macro definition, and
     // one macro use per unique callsite span.
-    // mac_defs: HashSet<Span>,
+    // mac_defs: FxHashSet<Span>,
     macro_calls: FxHashSet<Span>,
 }
 
@@ -107,7 +107,7 @@ pub fn new(
             dumper,
             span: span_utils.clone(),
             cur_scope: CRATE_NODE_ID,
-            // mac_defs: HashSet::new(),
+            // mac_defs: FxHashSet::default(),
             macro_calls: FxHashSet(),
         }
     }
@@ -147,9 +147,9 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
         let crate_root = source_file.map(|source_file| {
             let source_file = Path::new(source_file);
             match source_file.file_name() {
-                Some(_) => source_file.parent().unwrap().display().to_string(),
-                None => source_file.display().to_string(),
-            }
+                Some(_) => source_file.parent().unwrap().display(),
+                None => source_file.display(),
+            }.to_string()
         });
 
         let data = CratePreludeData {
@@ -176,8 +176,8 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         let segments = &path.segments[if path.is_global() { 1 } else { 0 }..];
 
         let mut result = Vec::with_capacity(segments.len());
+        let mut segs = Vec::with_capacity(segments.len());
 
-        let mut segs = vec![];
         for (i, seg) in segments.iter().enumerate() {
             segs.push(seg.clone());
             let sub_path = ast::Path {
@@ -591,9 +591,7 @@ fn process_enum(
 
         for variant in &enum_definition.variants {
             let name = variant.node.ident.name.to_string();
-            let mut qualname = enum_data.qualname.clone();
-            qualname.push_str("::");
-            qualname.push_str(&name);
+            let qualname = format!("{}::{}", enum_data.qualname, name);
 
             match variant.node.data {
                 ast::VariantData::Struct(ref fields, _) => {
@@ -973,9 +971,9 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
             match self.save_ctxt.get_path_def(id) {
                 HirDef::Local(id) => {
                     let mut value = if immut == ast::Mutability::Immutable {
-                        self.span.snippet(ident.span).to_string()
+                        self.span.snippet(ident.span)
                     } else {
-                        "<mutable>".to_string()
+                        "<mutable>".to_owned()
                     };
                     let hir_id = self.tcx.hir.node_to_hir_id(id);
                     let typ = self.save_ctxt
@@ -1103,10 +1101,9 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
     /// mac_uses and mac_defs sets to prevent multiples.
     fn process_macro_use(&mut self, span: Span) {
         let source_span = span.source_callsite();
-        if self.macro_calls.contains(&source_span) {
+        if !self.macro_calls.insert(source_span) {
             return;
         }
-        self.macro_calls.insert(source_span);
 
         let data = match self.save_ctxt.get_macro_use_data(span) {
             None => return,
@@ -1362,6 +1359,14 @@ fn process_use_tree(&mut self,
             }
         }
     }
+
+    fn process_bounds(&mut self, bounds: &'l ast::GenericBounds) {
+        for bound in bounds {
+            if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
+                self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
+            }
+        }
+    }
 }
 
 impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, O> {
@@ -1527,20 +1532,19 @@ fn visit_item(&mut self, item: &'l ast::Item) {
 
     fn visit_generics(&mut self, generics: &'l ast::Generics) {
         for param in &generics.params {
-            match param.kind {
-                ast::GenericParamKind::Lifetime { .. } => {}
-                ast::GenericParamKind::Type { ref default, .. } => {
-                    for bound in &param.bounds {
-                        if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
-                            self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
-                        }
-                    }
-                    if let Some(ref ty) = default {
-                        self.visit_ty(&ty);
-                    }
+            if let ast::GenericParamKind::Type { ref default, .. } = param.kind {
+                self.process_bounds(&param.bounds);
+                if let Some(ref ty) = default {
+                    self.visit_ty(&ty);
                 }
             }
         }
+        for pred in &generics.where_clause.predicates {
+            if let ast::WherePredicate::BoundPredicate(ref wbp) = *pred {
+                self.process_bounds(&wbp.bounds);
+                self.visit_ty(&wbp.bounded_ty);
+            }
+        }
     }
 
     fn visit_ty(&mut self, t: &'l ast::Ty) {
@@ -1601,8 +1605,7 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                 }
             }
             ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => {
-                let mut id = String::from("$");
-                id.push_str(&ex.id.to_string());
+                let id = format!("${}", ex.id);
 
                 // walk arg and return types
                 for arg in &decl.inputs {
@@ -1663,7 +1666,10 @@ fn visit_pat(&mut self, p: &'l ast::Pat) {
 
     fn visit_arm(&mut self, arm: &'l ast::Arm) {
         self.process_var_decl_multi(&arm.pats);
-        walk_list!(self, visit_expr, &arm.guard);
+        match arm.guard {
+            Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
+            _ => {}
+        }
         self.visit_expr(&arm.body);
     }
 
index fd29dac5af8cc87a72e62767698067eaee508f15..48e4d93e07b36f82fb06aba96834cdd0f82ba3e6 100644 (file)
@@ -101,7 +101,7 @@ fn span_from_span(&self, span: Span) -> SpanData {
         let end = cm.lookup_char_pos(span.hi());
 
         SpanData {
-            file_name: start.file.name.clone().to_string().into(),
+            file_name: start.file.name.to_string().into(),
             byte_start: span.lo().0,
             byte_end: span.hi().0,
             line_start: Row::new_one_indexed(start.line as u32),
@@ -113,7 +113,7 @@ fn span_from_span(&self, span: Span) -> SpanData {
 
     // List external crates used by the current crate.
     pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
-        let mut result = Vec::new();
+        let mut result = Vec::with_capacity(self.tcx.crates().len());
 
         for &n in self.tcx.crates().iter() {
             let span = match *self.tcx.extern_crate(n.as_def_id()) {
@@ -148,7 +148,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
                 filter!(self.span_utils, sub_span, item.span, None);
 
                 Some(Data::DefData(Def {
-                    kind: DefKind::Function,
+                    kind: DefKind::ForeignFunction,
                     id: id_from_node_id(item.id, self),
                     span: self.span_from_span(sub_span.unwrap()),
                     name: item.ident.to_string(),
@@ -171,7 +171,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
                 let span = self.span_from_span(sub_span.unwrap());
 
                 Some(Data::DefData(Def {
-                    kind: DefKind::Static,
+                    kind: DefKind::ForeignStatic,
                     id,
                     span,
                     name: item.ident.to_string(),
@@ -321,7 +321,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.to_owned(), self),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
             ast::ItemKind::Impl(.., ref trait_ref, ref typ, ref impls) => {
index 130325628796ecbd74f0d253e290c02954631ac7..9cf64a9d1ca81ba1b6f583e0f3263ed66d102ac4 100644 (file)
@@ -435,7 +435,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     },
                 ];
                 text.push_str(&name);
-                // Could be either `mod foo;` or `mod foo { ... }`, but we'll just puck one.
+                // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
                 text.push(';');
 
                 Ok(Signature {
@@ -630,7 +630,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
 
         let mut text = "<".to_owned();
 
-        let mut defs = vec![];
+        let mut defs = Vec::with_capacity(self.params.len());
         for param in &self.params {
             let mut param_text = param.ident.to_string();
             defs.push(SigElement {
index e1a3829cd75388cabb18002acecdb57fee585f6a..2550a312c5d6de6d13856b0fc111a6fb63f51aa5 100644 (file)
@@ -154,8 +154,7 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
                 let loc = self.sess.source_map().lookup_char_pos(span.lo());
                 span_bug!(
                     span,
-                    "Mis-counted brackets when breaking path? Parsing '{}' \
-                     in {}, line {}",
+                    "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                     self.snippet(span),
                     loc.file.name,
                     loc.line
@@ -264,11 +263,8 @@ fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span>
     /// such as references to macro internal variables.
     pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
         if !generated_code(parent) {
-            if sub_span.is_none() {
-                // Edge case - this occurs on generated code with incorrect expansion info.
-                return true;
-            }
-            return false;
+            // Edge case - this occurs on generated code with incorrect expansion info.
+            return sub_span.is_none()
         }
         // If sub_span is none, filter out generated code.
         let sub_span = match sub_span {
index 1e70a806cce895ee707e5f7a8a71ed25ad8dda56..e4d958e3b6f3520e84ae3a76b6f6fa098a65fc25 100644 (file)
@@ -22,7 +22,8 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![cfg_attr(not(stage0), feature(nll))]
 #![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(slice_patterns)]
index 7c0cdf991ef4451a4b7a25457b01b2be950bafeb..2514909ba75f3082a490e5ede673aa3d0bb3edd1 100644 (file)
@@ -74,6 +74,7 @@
 mod l4re_base;
 mod fuchsia_base;
 mod redox_base;
+mod riscv_base;
 
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
          RustcEncodable, RustcDecodable)]
@@ -406,6 +407,7 @@ fn $module() {
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
 
+    ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
 
     ("aarch64-unknown-none", aarch64_unknown_none),
index ce56cdd44bb2ff2c87d0937d79211d11b21be00c..b199a50f0ca389a3d8faa5e0e37c54481823fde9 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
-use spec::abi::{Abi};
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
+           Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -22,31 +22,19 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         arch: "riscv32".to_string(),
-        linker_flavor: LinkerFlavor::Ld,
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
 
         options: TargetOptions {
-            linker: Some("riscv32-unknown-elf-ld".to_string()),
+            linker: Some("rust-lld".to_string()),
             cpu: "generic-rv32".to_string(),
             max_atomic_width: Some(32),
             atomic_cas: false, // incomplete +a extension
-            features: "+m,+a".to_string(), // disable +c extension
+            features: "+m,+a,+c".to_string(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: "static".to_string(),
             emit_debug_gdb_scripts: false,
-            abi_blacklist: vec![
-                Abi::Cdecl,
-                Abi::Stdcall,
-                Abi::Fastcall,
-                Abi::Vectorcall,
-                Abi::Thiscall,
-                Abi::Aapcs,
-                Abi::Win64,
-                Abi::SysV64,
-                Abi::PtxKernel,
-                Abi::Msp430Interrupt,
-                Abi::X86Interrupt,
-            ],
+            abi_blacklist: super::riscv_base::abi_blacklist(),
             .. Default::default()
         },
     })
diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
new file mode 100644 (file)
index 0000000..68da1b6
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, LldFlavor, PanicStrategy,
+           Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: "unknown".to_string(),
+        arch: "riscv32".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            linker: Some("rust-lld".to_string()),
+            cpu: "generic-rv32".to_string(),
+            // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86005
+            max_atomic_width: None, //Some(32),
+            atomic_cas: false,
+            features: "+m,+c".to_string(),
+            executables: true,
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: "static".to_string(),
+            emit_debug_gdb_scripts: false,
+            abi_blacklist: super::riscv_base::abi_blacklist(),
+            .. Default::default()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/riscv_base.rs b/src/librustc_target/spec/riscv_base.rs
new file mode 100644 (file)
index 0000000..701ddf5
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::abi::Abi;
+
+// All the calling conventions trigger an assertion(Unsupported calling
+// convention) in llvm on RISCV
+pub fn abi_blacklist() -> Vec<Abi> {
+    vec![
+        Abi::Cdecl,
+        Abi::Stdcall,
+        Abi::Fastcall,
+        Abi::Vectorcall,
+        Abi::Thiscall,
+        Abi::Aapcs,
+        Abi::Win64,
+        Abi::SysV64,
+        Abi::PtxKernel,
+        Abi::Msp430Interrupt,
+        Abi::X86Interrupt,
+        Abi::AmdGpuKernel,
+    ]
+}
index 6c368e09003a39afc7a9aeed62242944a3908735..c0455ceb8390ce669802e9bc9650153882e9ef08 100644 (file)
@@ -36,8 +36,7 @@ pub fn target() -> Result<Target, String> {
         dll_suffix: ".wasm".to_string(),
         linker_is_gnu: false,
 
-        // A bit of a lie, but "eh"
-        max_atomic_width: Some(32),
+        max_atomic_width: Some(64),
 
         // Unwinding doesn't work right now, so the whole target unconditionally
         // defaults to panic=abort. Note that this is guaranteed to change in
index ae68584f2446f617cf0c4440f273059049ead174..2a8ee4bd8df0eeeb9feb5e19bbecb337641271c0 100644 (file)
@@ -663,9 +663,11 @@ pub fn check_match(&self,
         };
 
         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
-            if let Some(ref e) = arm.guard {
+            if let Some(ref g) = arm.guard {
                 self.diverges.set(pats_diverge);
-                self.check_expr_has_type_or_error(e, tcx.types.bool);
+                match g {
+                    hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
+                };
             }
 
             self.diverges.set(pats_diverge);
@@ -948,7 +950,7 @@ fn check_struct_pat_fields(&self,
         }
 
         // Require `..` if struct has non_exhaustive attribute.
-        if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc {
+        if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
             span_err!(tcx.sess, span, E0638,
                       "`..` required with {} marked as non-exhaustive",
                       kind_name);
index 85646b9ab675af19da19ce9ce470e30aa9a47326..4e22ead8db987a0514b885a992a43eac35332084 100644 (file)
@@ -351,11 +351,14 @@ pub fn check_ref(&self,
                             if !self.infcx.type_moves_by_default(self.param_env,
                                                                 checked,
                                                                 sp) {
-                                let sp = cm.call_span_if_macro(sp);
-                                if let Ok(code) = cm.span_to_snippet(sp) {
-                                    return Some((sp,
-                                                 "consider dereferencing the borrow",
-                                                 format!("*{}", code)));
+                                // do not suggest if the span comes from a macro (#52783)
+                                if let (Ok(code),
+                                        true) = (cm.span_to_snippet(sp), sp == expr.span) {
+                                    return Some((
+                                        sp,
+                                        "consider dereferencing the borrow",
+                                        format!("*{}", code),
+                                    ));
                                 }
                             }
                         }
index 23872ddf2f64b8c836d12fdd4fbbfc31012e5611..c7db3debf5a0d6dfacd6b276249715e1202d0a95 100644 (file)
 
 use std::iter;
 
-fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   it: &hir::ForeignItem,
-                                   n_tps: usize,
-                                   abi: Abi,
-                                   inputs: Vec<Ty<'tcx>>,
-                                   output: Ty<'tcx>) {
+fn equate_intrinsic_type<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    it: &hir::ForeignItem,
+    n_tps: usize,
+    abi: Abi,
+    safety: hir::Unsafety,
+    inputs: Vec<Ty<'tcx>>,
+    output: Ty<'tcx>,
+) {
     let def_id = tcx.hir.local_def_id(it.id);
 
     match it.node {
@@ -65,7 +68,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         inputs.into_iter(),
         output,
         false,
-        hir::Unsafety::Unsafe,
+        safety,
         abi
     )));
     let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
@@ -78,7 +81,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
     let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
     let name = it.name.as_str();
-    let (n_tps, inputs, output) = if name.starts_with("atomic_") {
+    let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
 
@@ -109,10 +112,14 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 return;
             }
         };
-        (n_tps, inputs, output)
+        (n_tps, inputs, output, hir::Unsafety::Unsafe)
     } else if &name[..] == "abort" || &name[..] == "unreachable" {
-        (0, Vec::new(), tcx.types.never)
+        (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
     } else {
+        let unsafety = match &name[..] {
+            "size_of" | "min_align_of" => hir::Unsafety::Normal,
+            _ => hir::Unsafety::Unsafe,
+        };
         let (n_tps, inputs, output) = match &name[..] {
             "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
             "size_of" |
@@ -327,9 +334,9 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 return;
             }
         };
-        (n_tps, inputs, output)
+        (n_tps, inputs, output, unsafety)
     };
-    equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, inputs, output)
+    equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -439,7 +446,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     };
 
-    equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic,
+    equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe,
                           inputs, output)
 }
 
index bbb45c04e4e9823d2ba8aed0c79c994c2b2c8fbe..a45e5c8ec2a4511da865c1f128e0729ab0899ca3 100644 (file)
@@ -94,7 +94,7 @@
 use rustc::infer::anon_types::AnonTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
-use rustc::mir::interpret::{GlobalId};
+use rustc::mir::interpret::{ConstValue, GlobalId};
 use rustc::ty::subst::{CanonicalSubsts, UnpackedKind, Subst, Substs};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
@@ -1178,6 +1178,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                         }
                     }
                 } else {
+                    let span = fcx.tcx.sess.source_map().def_span(span);
                     fcx.tcx.sess.span_err(span, "function should have one argument");
                 }
             } else {
@@ -1226,6 +1227,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                         }
                     }
                 } else {
+                    let span = fcx.tcx.sess.source_map().def_span(span);
                     fcx.tcx.sess.span_err(span, "function should have one argument");
                 }
             } else {
@@ -1375,7 +1377,11 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) {
     };
     let param_env = ty::ParamEnv::reveal_all();
     if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
-        let alloc = tcx.const_to_allocation(static_);
+        let alloc = if let ConstValue::ByRef(_, allocation, _) = static_.val {
+            allocation
+        } else {
+            bug!("Matching on non-ByRef static")
+        };
         if alloc.relocations.len() != 0 {
             let msg = "statics with a custom `#[link_section]` must be a \
                        simple list of bytes on the wasm target with no \
@@ -3465,7 +3471,7 @@ fn check_expr_struct_fields(&self,
         // re-link the regions that EIfEO can erase.
         self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
-        let (substs, adt_kind, kind_name) = match &adt_ty.sty{
+        let (substs, adt_kind, kind_name) = match &adt_ty.sty {
             &ty::Adt(adt, substs) => {
                 (substs, adt.adt_kind(), adt.variant_descr())
             }
@@ -3639,13 +3645,13 @@ fn check_expr_struct(&self,
                          base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
     {
         // Find the relevant variant
-        let (variant, struct_ty) =
-        if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) {
-            variant_ty
-        } else {
-            self.check_struct_fields_on_error(fields, base_expr);
-            return self.tcx.types.err;
-        };
+        let (variant, adt_ty) =
+            if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) {
+                variant_ty
+            } else {
+                self.check_struct_fields_on_error(fields, base_expr);
+                return self.tcx.types.err;
+            };
 
         let path_span = match *qpath {
             hir::QPath::Resolved(_, ref path) => path.span,
@@ -3653,23 +3659,22 @@ fn check_expr_struct(&self,
         };
 
         // Prohibit struct expressions when non exhaustive flag is set.
-        if let ty::Adt(adt, _) = struct_ty.sty {
-            if !adt.did.is_local() && adt.is_non_exhaustive() {
-                span_err!(self.tcx.sess, expr.span, E0639,
-                          "cannot create non-exhaustive {} using struct expression",
-                          adt.variant_descr());
-            }
+        let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
+        if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
+            span_err!(self.tcx.sess, expr.span, E0639,
+                      "cannot create non-exhaustive {} using struct expression",
+                      adt.variant_descr());
         }
 
-        let error_happened = self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span,
+        let error_happened = self.check_expr_struct_fields(adt_ty, expected, expr.id, path_span,
                                                            variant, fields, base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
             // If check_expr_struct_fields hit an error, do not attempt to populate
             // the fields with the base_expr. This could cause us to hit errors later
             // when certain fields are assumed to exist that in fact do not.
             if !error_happened {
-                self.check_expr_has_type_or_error(base_expr, struct_ty);
-                match struct_ty.sty {
+                self.check_expr_has_type_or_error(base_expr, adt_ty);
+                match adt_ty.sty {
                     ty::Adt(adt, substs) if adt.is_struct() => {
                         let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| {
                             self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs))
@@ -3687,8 +3692,8 @@ fn check_expr_struct(&self,
                 }
             }
         }
-        self.require_type_is_sized(struct_ty, expr.span, traits::StructInitializerSized);
-        struct_ty
+        self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
+        adt_ty
     }
 
 
index b7cf6819e21803638ad4ba85f77b54e865354374..edfa62f10953877f9f7e0ef26a99ef0c07edf949 100644 (file)
@@ -256,14 +256,19 @@ fn check_overloaded_binop(&self,
                     let source_map = self.tcx.sess.source_map();
                     match is_assign {
                         IsAssign::Yes => {
-                            let mut err = struct_span_err!(self.tcx.sess, expr.span, E0368,
-                                                "binary assignment operation `{}=` \
-                                                cannot be applied to type `{}`",
-                                                op.node.as_str(),
-                                                lhs_ty);
-                            err.span_label(lhs_expr.span,
-                                    format!("cannot use `{}=` on type `{}`",
-                                    op.node.as_str(), lhs_ty));
+                            let mut err = struct_span_err!(
+                                self.tcx.sess,
+                                expr.span,
+                                E0368,
+                                "binary assignment operation `{}=` cannot be applied to type `{}`",
+                                op.node.as_str(),
+                                lhs_ty,
+                            );
+                            err.span_label(
+                                lhs_expr.span,
+                                format!("cannot use `{}=` on type `{}`",
+                                op.node.as_str(), lhs_ty),
+                            );
                             let mut suggested_deref = false;
                             if let Ref(_, mut rty, _) = lhs_ty.sty {
                                 if {
@@ -280,13 +285,17 @@ fn check_overloaded_binop(&self,
                                             rty = rty_inner;
                                         }
                                         let msg = &format!(
-                                                "`{}=` can be used on '{}', you can \
-                                                dereference `{2}`: `*{2}`",
-                                                op.node.as_str(),
-                                                rty,
-                                                lstring
+                                            "`{}=` can be used on '{}', you can dereference `{}`",
+                                            op.node.as_str(),
+                                            rty,
+                                            lstring,
+                                        );
+                                        err.span_suggestion_with_applicability(
+                                            lhs_expr.span,
+                                            msg,
+                                            format!("*{}", lstring),
+                                            errors::Applicability::MachineApplicable,
                                         );
-                                        err.help(msg);
                                         suggested_deref = true;
                                     }
                                 }
index a42667ab45fc8726993b72d44000b4054f6ff702..7997801a9a5fb435fead11d698c4eb8a761e098f 100644 (file)
@@ -549,12 +549,13 @@ fn convert_enum_variant_types<'a, 'tcx>(
     }
 }
 
-fn convert_struct_variant<'a, 'tcx>(
+fn convert_variant<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     did: DefId,
     name: ast::Name,
     discr: ty::VariantDiscr,
     def: &hir::VariantData,
+    adt_kind: ty::AdtKind
 ) -> ty::VariantDef {
     let mut seen_fields: FxHashMap<ast::Ident, Span> = FxHashMap();
     let node_id = tcx.hir.as_local_node_id(did).unwrap();
@@ -585,13 +586,13 @@ fn convert_struct_variant<'a, 'tcx>(
             }
         })
         .collect();
-    ty::VariantDef {
+    ty::VariantDef::new(tcx,
         did,
         name,
         discr,
         fields,
-        ctor_kind: CtorKind::from_hir(def),
-    }
+        adt_kind,
+        CtorKind::from_hir(def))
 }
 
 fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef {
@@ -621,7 +622,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
                         };
                         distance_from_explicit += 1;
 
-                        convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data)
+                        convert_variant(tcx, did, v.node.name, discr, &v.node.data, AdtKind::Enum)
                     })
                     .collect(),
             )
@@ -635,23 +636,25 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
             };
             (
                 AdtKind::Struct,
-                vec![convert_struct_variant(
+                vec![convert_variant(
                     tcx,
                     ctor_id.unwrap_or(def_id),
                     item.name,
                     ty::VariantDiscr::Relative(0),
                     def,
+                    AdtKind::Struct
                 )],
             )
         }
         ItemKind::Union(ref def, _) => (
             AdtKind::Union,
-            vec![convert_struct_variant(
+            vec![convert_variant(
                 tcx,
                 def_id,
                 item.name,
                 ty::VariantDiscr::Relative(0),
                 def,
+                AdtKind::Union
             )],
         ),
         _ => bug!(),
@@ -1796,6 +1799,21 @@ fn explicit_predicates_of<'a, 'tcx>(
             &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
                 let ty = icx.to_ty(&bound_pred.bounded_ty);
 
+                // Keep the type around in a WF predicate, in case of no bounds.
+                // That way, `where Ty:` is not a complete noop (see #53696).
+                if bound_pred.bounds.is_empty() {
+                    if let ty::Param(_) = ty.sty {
+                        // This is a `where T:`, which can be in the HIR from the
+                        // transformation that moves `?Sized` to `T`'s declaration.
+                        // We can skip the predicate because type parameters are
+                        // trivially WF, but also we *should*, to avoid exposing
+                        // users who never wrote `where Type:,` themselves, to
+                        // compiler/tooling bugs from not handling WF predicates.
+                    } else {
+                        predicates.push(ty::Predicate::WellFormed(ty));
+                    }
+                }
+
                 for bound in bound_pred.bounds.iter() {
                     match bound {
                         &hir::GenericBound::Trait(ref poly_trait_ref, _) => {
@@ -1981,12 +1999,15 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     decl: &hir::FnDecl,
     abi: abi::Abi,
 ) -> ty::PolyFnSig<'tcx> {
-    let fty = AstConv::ty_of_fn(
-        &ItemCtxt::new(tcx, def_id),
-        hir::Unsafety::Unsafe,
-        abi,
-        decl,
-    );
+    let unsafety = if abi == abi::Abi::RustIntrinsic {
+        match &*tcx.item_name(def_id).as_str() {
+            "size_of" | "min_align_of" => hir::Unsafety::Normal,
+            _ => hir::Unsafety::Unsafe,
+        }
+    } else {
+        hir::Unsafety::Unsafe
+    };
+    let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl);
 
     // feature gate SIMD types in FFI, since I (huonw) am not sure the
     // ABIs are handled at all correctly.
index ffd9da8c8b95c803ec870ff93738027effccda2d..12863cc66a053ecb02149a573d1c276dd0e34628 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::session::Session;
 use syntax_pos::Span;
-use errors::{DiagnosticId, DiagnosticBuilder};
+use errors::{Applicability, DiagnosticId, DiagnosticBuilder};
 use rustc::ty::{Ty, TypeFoldable};
 
 pub trait StructuredDiagnostic<'tcx> {
@@ -73,9 +73,12 @@ fn common(&self) -> DiagnosticBuilder<'tcx> {
             )
         };
         if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
-            err.span_suggestion(self.span,
-                                &format!("cast the value to `{}`", self.cast_ty),
-                                format!("{} as {}", snippet, self.cast_ty));
+            err.span_suggestion_with_applicability(
+                self.span,
+                &format!("cast the value to `{}`", self.cast_ty),
+                format!("{} as {}", snippet, self.cast_ty),
+                Applicability::MachineApplicable,
+            );
         } else {
             err.help(&format!("cast the value to `{}`", self.cast_ty));
         }
index 5c23d0f6b399083a1172e7ee631ca9d5f721fde1..da18e3e6b91b39d52c18cafb7fa3991f06ed8dc7 100644 (file)
@@ -1312,7 +1312,13 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
             Predicate::Projection(ref pred) => pred.clean(cx),
-            Predicate::WellFormed(_) => panic!("not user writable"),
+            Predicate::WellFormed(ty) => {
+                // This comes from `where Ty:` (i.e. no bounds) (see #53696).
+                WherePredicate::BoundPredicate {
+                    ty: ty.clean(cx),
+                    bounds: vec![],
+                }
+            }
             Predicate::ObjectSafe(_) => panic!("not user writable"),
             Predicate::ClosureKind(..) => panic!("not user writable"),
             Predicate::ConstEvaluatable(..) => panic!("not user writable"),
index c104b883340615d88948f4d1b48f464c42cd0abc..18ad862c11bb0915953059768629af09e8959ccb 100644 (file)
@@ -29,8 +29,9 @@
 
 #![allow(non_camel_case_types)]
 
+use rustc_data_structures::fx::FxHashMap;
 use std::cell::RefCell;
-use std::collections::{HashMap, VecDeque};
+use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::{self, Write};
 use std::borrow::Cow;
@@ -417,14 +418,14 @@ fn next(&mut self) -> Option<Self::Item> {
 /// references.
 struct Footnotes<'a, I: Iterator<Item = Event<'a>>> {
     inner: I,
-    footnotes: HashMap<String, (Vec<Event<'a>>, u16)>,
+    footnotes: FxHashMap<String, (Vec<Event<'a>>, u16)>,
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> Footnotes<'a, I> {
     fn new(iter: I) -> Self {
         Footnotes {
             inner: iter,
-            footnotes: HashMap::new(),
+            footnotes: FxHashMap::default(),
         }
     }
     fn get_entry(&mut self, key: &str) -> &mut (Vec<Event<'a>>, u16) {
@@ -865,7 +866,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
 
 #[derive(Default)]
 pub struct IdMap {
-    map: HashMap<String, usize>,
+    map: FxHashMap<String, usize>,
 }
 
 impl IdMap {
@@ -880,7 +881,7 @@ pub fn populate<I: IntoIterator<Item=String>>(&mut self, ids: I) {
     }
 
     pub fn reset(&mut self) {
-        self.map = HashMap::new();
+        self.map = FxHashMap::default();
     }
 
     pub fn derive(&mut self, candidate: String) -> String {
index 8fb3b570f8a4b38f83818e8e1e1bb99d7ece235d..368c056f021c135b359c70bc2ec00c9908bb79ca 100644 (file)
@@ -38,7 +38,7 @@
 use std::borrow::Cow;
 use std::cell::RefCell;
 use std::cmp::Ordering;
-use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::collections::{BTreeMap, VecDeque};
 use std::default::Default;
 use std::error;
 use std::fmt::{self, Display, Formatter, Write as FmtWrite};
@@ -479,6 +479,7 @@ pub fn initial_ids() -> Vec<String> {
 
 /// Generates the documentation for `crate` into the directory `dst`
 pub fn run(mut krate: clean::Crate,
+           extern_urls: BTreeMap<String, String>,
            external_html: &ExternalHtml,
            playground_url: Option<String>,
            dst: PathBuf,
@@ -611,8 +612,9 @@ pub fn run(mut krate: clean::Crate,
             },
             _ => PathBuf::new(),
         };
+        let extern_url = extern_urls.get(&e.name).map(|u| &**u);
         cache.extern_locations.insert(n, (e.name.clone(), src_root,
-                                          extern_location(e, &cx.dst)));
+                                          extern_location(e, extern_url, &cx.dst)));
 
         let did = DefId { krate: n, index: CRATE_DEF_INDEX };
         cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
@@ -741,7 +743,7 @@ fn write_shared(cx: &Context,
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
-    let mut themes: HashSet<String> = HashSet::new();
+    let mut themes: FxHashSet<String> = FxHashSet::default();
 
     for entry in &cx.shared.themes {
         let mut content = Vec::with_capacity(100000);
@@ -1096,13 +1098,23 @@ fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) wh
 
 /// Attempts to find where an external crate is located, given that we're
 /// rendering in to the specified source destination.
-fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
+fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path)
+    -> ExternalLocation
+{
     // See if there's documentation generated into the local directory
     let local_location = dst.join(&e.name);
     if local_location.is_dir() {
         return Local;
     }
 
+    if let Some(url) = extern_url {
+        let mut url = url.to_string();
+        if !url.ends_with("/") {
+            url.push('/');
+        }
+        return Remote(url);
+    }
+
     // Failing that, see if there's an attribute specifying where to find this
     // external crate
     e.attrs.lists("doc")
@@ -1539,35 +1551,36 @@ fn cmp(&self, other: &ItemEntry) -> ::std::cmp::Ordering {
 
 #[derive(Debug)]
 struct AllTypes {
-    structs: HashSet<ItemEntry>,
-    enums: HashSet<ItemEntry>,
-    unions: HashSet<ItemEntry>,
-    primitives: HashSet<ItemEntry>,
-    traits: HashSet<ItemEntry>,
-    macros: HashSet<ItemEntry>,
-    functions: HashSet<ItemEntry>,
-    typedefs: HashSet<ItemEntry>,
-    existentials: HashSet<ItemEntry>,
-    statics: HashSet<ItemEntry>,
-    constants: HashSet<ItemEntry>,
-    keywords: HashSet<ItemEntry>,
+    structs: FxHashSet<ItemEntry>,
+    enums: FxHashSet<ItemEntry>,
+    unions: FxHashSet<ItemEntry>,
+    primitives: FxHashSet<ItemEntry>,
+    traits: FxHashSet<ItemEntry>,
+    macros: FxHashSet<ItemEntry>,
+    functions: FxHashSet<ItemEntry>,
+    typedefs: FxHashSet<ItemEntry>,
+    existentials: FxHashSet<ItemEntry>,
+    statics: FxHashSet<ItemEntry>,
+    constants: FxHashSet<ItemEntry>,
+    keywords: FxHashSet<ItemEntry>,
 }
 
 impl AllTypes {
     fn new() -> AllTypes {
+        let new_set = |cap| FxHashSet::with_capacity_and_hasher(cap, Default::default());
         AllTypes {
-            structs: HashSet::with_capacity(100),
-            enums: HashSet::with_capacity(100),
-            unions: HashSet::with_capacity(100),
-            primitives: HashSet::with_capacity(26),
-            traits: HashSet::with_capacity(100),
-            macros: HashSet::with_capacity(100),
-            functions: HashSet::with_capacity(100),
-            typedefs: HashSet::with_capacity(100),
-            existentials: HashSet::with_capacity(100),
-            statics: HashSet::with_capacity(100),
-            constants: HashSet::with_capacity(100),
-            keywords: HashSet::with_capacity(100),
+            structs: new_set(100),
+            enums: new_set(100),
+            unions: new_set(100),
+            primitives: new_set(26),
+            traits: new_set(100),
+            macros: new_set(100),
+            functions: new_set(100),
+            typedefs: new_set(100),
+            existentials: new_set(100),
+            statics: new_set(100),
+            constants: new_set(100),
+            keywords: new_set(100),
         }
     }
 
@@ -1595,7 +1608,7 @@ fn append(&mut self, item_name: String, item_type: &ItemType) {
     }
 }
 
-fn print_entries(f: &mut fmt::Formatter, e: &HashSet<ItemEntry>, title: &str,
+fn print_entries(f: &mut fmt::Formatter, e: &FxHashSet<ItemEntry>, title: &str,
                  class: &str) -> fmt::Result {
     if !e.is_empty() {
         let mut e: Vec<&ItemEntry> = e.iter().collect();
@@ -2943,12 +2956,16 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
                 </h2>
             ")?;
 
+            let mut foreign_cache = FxHashSet();
             for implementor in foreign {
-                let assoc_link = AssocItemLink::GotoSource(
-                    implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods
-                );
-                render_impl(w, cx, &implementor, assoc_link,
-                            RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
+                if foreign_cache.insert(implementor.inner_impl().to_string()) {
+                    let assoc_link = AssocItemLink::GotoSource(
+                        implementor.impl_item.def_id,
+                        &implementor.inner_impl().provided_trait_methods
+                    );
+                    render_impl(w, cx, &implementor, assoc_link,
+                                RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
+                }
             }
         }
 
@@ -4185,7 +4202,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                 }
             }
             let format_impls = |impls: Vec<&Impl>| {
-                let mut links = HashSet::new();
+                let mut links = FxHashSet::default();
                 impls.iter()
                            .filter_map(|i| {
                                let is_negative_impl = is_negative_impl(i.inner_impl());
index 88c25567d2963e7c3f4b5181b92657594a6974b8..51ed62678292662fd4201c4e1ddcf630819c1c88 100644 (file)
         }
     }
 
+    highlightSourceLines(null);
     window.onhashchange = highlightSourceLines;
 
     // Gets the human-readable string for the virtual-key code of the
index ffe6a40b369988d7a83558a558b722c6a1989669..5145e9f449b17571d8edc8cba762888379771b4b 100644 (file)
@@ -502,6 +502,7 @@ h4 > code, h3 > code, .invisible > code {
        margin-left: 33px;
        margin-top: -13px;
 }
+
 .content .stability::before {
        content: '˪';
        font-size: 30px;
@@ -509,6 +510,13 @@ h4 > code, h3 > code, .invisible > code {
        top: -9px;
        left: -13px;
 }
+.methods > .stability {
+       margin-top: -8px;
+}
+
+#main > .stability {
+       margin-top: 0;
+}
 
 nav {
        border-bottom: 1px solid;
index 2ed7f7a926a4808a02843d7bbc87d6cff5073f7c..12d2208489368a52e7466c1f964990eebcdd2229 100644 (file)
@@ -407,3 +407,7 @@ kbd {
 .search-results td span.grey {
        color: #ccc;
 }
+
+.impl-items code {
+       background-color: rgba(0, 0, 0, 0);
+}
index f7cb51163ecfc2153f861b1e61aa3e1ad0ef8369..043d7ae23c2e4aaa6876541d41ce131b68316844 100644 (file)
@@ -401,3 +401,7 @@ kbd {
 .search-results td span.grey {
        color: #999;
 }
+
+.impl-items code {
+       background-color: rgba(0, 0, 0, 0);
+}
index 279151eb26def8943d4606c7a854fdd6f9ba6e34..1acae86f0068f5f7ba61180eac9d9717791690ca 100644 (file)
@@ -162,6 +162,10 @@ fn opts() -> Vec<RustcOptGroup> {
         stable("extern", |o| {
             o.optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH")
         }),
+        unstable("extern-html-root-url", |o| {
+            o.optmulti("", "extern-html-root-url",
+                       "base URL to use for dependencies", "NAME=URL")
+        }),
         stable("plugin-path", |o| {
             o.optmulti("", "plugin-path", "removed", "DIR")
         }),
@@ -453,6 +457,13 @@ fn main_args(args: &[String]) -> isize {
             return 1;
         }
     };
+    let extern_urls = match parse_extern_html_roots(&matches) {
+        Ok(ex) => ex,
+        Err(err) => {
+            diag.struct_err(err).emit();
+            return 1;
+        }
+    };
 
     let test_args = matches.opt_strs("test-args");
     let test_args: Vec<String> = test_args.iter()
@@ -466,7 +477,8 @@ fn main_args(args: &[String]) -> isize {
 
     let output = matches.opt_str("o").map(|s| PathBuf::from(&s));
     let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
-    let cfgs = matches.opt_strs("cfg");
+    let mut cfgs = matches.opt_strs("cfg");
+    cfgs.push("rustdoc".to_string());
 
     if let Some(ref p) = css_file_extension {
         if !p.is_file() {
@@ -553,7 +565,7 @@ fn main_args(args: &[String]) -> isize {
         info!("going to format");
         match output_format.as_ref().map(|s| &**s) {
             Some("html") | None => {
-                html::render::run(krate, &external_html, playground_url,
+                html::render::run(krate, extern_urls, &external_html, playground_url,
                                   output.unwrap_or(PathBuf::from("doc")),
                                   resource_suffix.unwrap_or(String::new()),
                                   passes.into_iter().collect(),
@@ -612,6 +624,23 @@ fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
     Ok(Externs::new(externs))
 }
 
+/// Extracts `--extern-html-root-url` arguments from `matches` and returns a map of crate names to
+/// the given URLs. If an `--extern-html-root-url` argument was ill-formed, returns an error
+/// describing the issue.
+fn parse_extern_html_roots(matches: &getopts::Matches)
+    -> Result<BTreeMap<String, String>, &'static str>
+{
+    let mut externs = BTreeMap::new();
+    for arg in &matches.opt_strs("extern-html-root-url") {
+        let mut parts = arg.splitn(2, '=');
+        let name = parts.next().ok_or("--extern-html-root-url must not be empty")?;
+        let url = parts.next().ok_or("--extern-html-root-url must be of the form name=url")?;
+        externs.insert(name.to_string(), url.to_string());
+    }
+
+    Ok(externs)
+}
+
 /// Interprets the input file as a rust source file, passing it through the
 /// compiler all the way through the analysis passes. The rustdoc output is then
 /// generated from the cleaned AST of the crate.
@@ -643,7 +672,8 @@ fn rust_input<R, F>(cratefile: PathBuf,
     for s in &matches.opt_strs("L") {
         paths.add_path(s, ErrorOutputType::default());
     }
-    let cfgs = matches.opt_strs("cfg");
+    let mut cfgs = matches.opt_strs("cfg");
+    cfgs.push("rustdoc".to_string());
     let triple = matches.opt_str("target").map(|target| {
         if target.ends_with(".json") {
             TargetTriple::TargetPath(PathBuf::from(target))
index 96a67e078875800bbc06e84183ee88a242a4b7d5..55a11d1976599b5d562a6be085c8a96dd44d3055 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashSet;
+use rustc_data_structures::fx::FxHashSet;
 use std::fs::File;
 use std::hash::{Hash, Hasher};
 use std::io::Read;
@@ -31,7 +31,7 @@ macro_rules! try_something {
 #[derive(Debug, Clone, Eq)]
 pub struct CssPath {
     pub name: String,
-    pub children: HashSet<CssPath>,
+    pub children: FxHashSet<CssPath>,
 }
 
 // This PartialEq implementation IS NOT COMMUTATIVE!!!
@@ -66,7 +66,7 @@ impl CssPath {
     fn new(name: String) -> CssPath {
         CssPath {
             name,
-            children: HashSet::new(),
+            children: FxHashSet::default(),
         }
     }
 }
@@ -205,13 +205,13 @@ fn build_rule(v: &[u8], positions: &[usize]) -> String {
              .replace("\t", " ")
              .replace("{", "")
              .replace("}", "")
-             .split(" ")
+             .split(' ')
              .filter(|s| s.len() > 0)
              .collect::<Vec<&str>>()
              .join(" ")
 }
 
-fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> HashSet<CssPath> {
+fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> FxHashSet<CssPath> {
     let mut paths = Vec::with_capacity(50);
 
     while *pos < events.len() {
index 5348c9a0f349842e057985b7fdfce779d3714082..bcdd1b4b088029fea45a223e733b9a27b60da69f 100644 (file)
@@ -25,7 +25,7 @@ profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
 
 [dev-dependencies]
-rand = "0.4"
+rand = "0.5"
 
 [target.x86_64-apple-darwin.dependencies]
 rustc_asan = { path = "../librustc_asan" }
index 29534696abc5be232de994c97448fe71c6e3b398..3de4a1bd4170b62a454a5091fe05a6e4cdec29ed 100644 (file)
@@ -138,7 +138,72 @@ fn description(&self) -> &str {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn cause(&self) -> Option<&dyn Error> { None }
+    #[rustc_deprecated(since = "1.33.0", reason = "replaced by Error::source, which can support \
+                                                   downcasting")]
+    fn cause(&self) -> Option<&dyn Error> {
+        self.source()
+    }
+
+    /// The lower-level source of this error, if any.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    ///
+    /// #[derive(Debug)]
+    /// struct SuperError {
+    ///     side: SuperErrorSideKick,
+    /// }
+    ///
+    /// impl fmt::Display for SuperError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "SuperError is here!")
+    ///     }
+    /// }
+    ///
+    /// impl Error for SuperError {
+    ///     fn description(&self) -> &str {
+    ///         "I'm the superhero of errors"
+    ///     }
+    ///
+    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
+    ///         Some(&self.side)
+    ///     }
+    /// }
+    ///
+    /// #[derive(Debug)]
+    /// struct SuperErrorSideKick;
+    ///
+    /// impl fmt::Display for SuperErrorSideKick {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "SuperErrorSideKick is here!")
+    ///     }
+    /// }
+    ///
+    /// impl Error for SuperErrorSideKick {
+    ///     fn description(&self) -> &str {
+    ///         "I'm SuperError side kick"
+    ///     }
+    /// }
+    ///
+    /// fn get_super_error() -> Result<(), SuperError> {
+    ///     Err(SuperError { side: SuperErrorSideKick })
+    /// }
+    ///
+    /// fn main() {
+    ///     match get_super_error() {
+    ///         Err(e) => {
+    ///             println!("Error: {}", e.description());
+    ///             println!("Caused by: {}", e.source().unwrap());
+    ///         }
+    ///         _ => println!("No error"),
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "error_source", since = "1.30.0")]
+    fn source(&self) -> Option<&(dyn Error + 'static)> { None }
 
     /// Get the `TypeId` of `self`
     #[doc(hidden)]
index 7632fbc41f5a322e64fe0ddfca7050178ce94e22..e177d4a988ae7d9c5ac943307f42f323ffe37a3b 100644 (file)
@@ -2076,7 +2076,7 @@ mod tests {
     use fs::{self, File, OpenOptions};
     use io::{ErrorKind, SeekFrom};
     use path::Path;
-    use rand::{StdRng, Rng};
+    use rand::{StdRng, FromEntropy, RngCore};
     use str;
     use sys_common::io::test::{TempDir, tmpdir};
     use thread;
@@ -3110,7 +3110,7 @@ fn _assert_send_sync<T: Send + Sync>() {}
     #[test]
     fn binary_file() {
         let mut bytes = [0; 1024];
-        StdRng::new().unwrap().fill_bytes(&mut bytes);
+        StdRng::from_entropy().fill_bytes(&mut bytes);
 
         let tmpdir = tmpdir();
 
@@ -3123,7 +3123,7 @@ fn binary_file() {
     #[test]
     fn write_then_read() {
         let mut bytes = [0; 1024];
-        StdRng::new().unwrap().fill_bytes(&mut bytes);
+        StdRng::from_entropy().fill_bytes(&mut bytes);
 
         let tmpdir = tmpdir();
 
index 4fb367fb6ba524147e9a1806d02eab4759a8d0b6..24965ff69318435e874eaad52f9dc8a1b58edcc3 100644 (file)
@@ -18,7 +18,6 @@ pub struct Lazy<T> {
     // We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
     lock: Mutex,
     ptr: Cell<*mut Arc<T>>,
-    init: fn() -> Arc<T>,
 }
 
 #[inline]
@@ -26,33 +25,32 @@ const fn done<T>() -> *mut Arc<T> { 1_usize as *mut _ }
 
 unsafe impl<T> Sync for Lazy<T> {}
 
-impl<T: Send + Sync + 'static> Lazy<T> {
-    /// Safety: `init` must not call `get` on the variable that is being
-    /// initialized.
-    pub const unsafe fn new(init: fn() -> Arc<T>) -> Lazy<T> {
+impl<T> Lazy<T> {
+    pub const fn new() -> Lazy<T> {
         Lazy {
             lock: Mutex::new(),
             ptr: Cell::new(ptr::null_mut()),
-            init,
         }
     }
+}
 
-    pub fn get(&'static self) -> Option<Arc<T>> {
-        unsafe {
-            let _guard = self.lock.lock();
-            let ptr = self.ptr.get();
-            if ptr.is_null() {
-                Some(self.init())
-            } else if ptr == done() {
-                None
-            } else {
-                Some((*ptr).clone())
-            }
+impl<T: Send + Sync + 'static> Lazy<T> {
+    /// Safety: `init` must not call `get` on the variable that is being
+    /// initialized.
+    pub unsafe fn get(&'static self, init: fn() -> Arc<T>) -> Option<Arc<T>> {
+        let _guard = self.lock.lock();
+        let ptr = self.ptr.get();
+        if ptr.is_null() {
+            Some(self.init(init))
+        } else if ptr == done() {
+            None
+        } else {
+            Some((*ptr).clone())
         }
     }
 
     // Must only be called with `lock` held
-    unsafe fn init(&'static self) -> Arc<T> {
+    unsafe fn init(&'static self, init: fn() -> Arc<T>) -> Arc<T> {
         // If we successfully register an at exit handler, then we cache the
         // `Arc` allocation in our own internal box (it will get deallocated by
         // the at exit handler). Otherwise we just return the freshly allocated
@@ -66,8 +64,8 @@ unsafe fn init(&'static self) -> Arc<T> {
         });
         // This could reentrantly call `init` again, which is a problem
         // because our `lock` allows reentrancy!
-        // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens.
-        let ret = (self.init)();
+        // That's why `get` is unsafe and requires the caller to ensure no reentrancy happens.
+        let ret = init();
         if registered.is_ok() {
             self.ptr.set(Box::into_raw(Box::new(ret.clone())));
         }
index 1f256f518c7ce083585f57b74ddccbfb95912b04..a413432cdaabc6ba2b0075a2e10e161379ec7578 100644 (file)
@@ -197,9 +197,11 @@ pub struct StdinLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) };
+    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
     return Stdin {
-        inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
+        inner: unsafe {
+            INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown")
+        },
     };
 
     fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
@@ -396,10 +398,11 @@ pub struct StdoutLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
-        = unsafe { Lazy::new(stdout_init) };
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
     return Stdout {
-        inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
+        inner: unsafe {
+            INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown")
+        },
     };
 
     fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
@@ -533,10 +536,11 @@ pub struct StderrLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> =
-        unsafe { Lazy::new(stderr_init) };
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new();
     return Stderr {
-        inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
+        inner: unsafe {
+            INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown")
+        },
     };
 
     fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
index 310475d31fdede876081aef27c22295a16135f70..e7195b3e21ee37c4ca3c60db1574bbd9be82ff57 100644 (file)
 #![feature(cfg_target_vendor)]
 #![feature(char_error_internals)]
 #![feature(compiler_builtins_lib)]
-#![feature(const_fn)]
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(min_const_fn))]
 #![feature(const_int_ops)]
 #![feature(const_ip)]
 #![feature(core_intrinsics)]
index 6945a41a5e73bef0e94cb7614a0a1af936ce621a..b649ec2340e93df33e87121b1143dff8c780e840 100644 (file)
@@ -309,7 +309,7 @@ macro_rules! assert_approx_eq {
 /// These macros do not have any corresponding definition with a `macro_rules!`
 /// macro, but are documented here. Their implementations can be found hardcoded
 /// into libsyntax itself.
-#[cfg(dox)]
+#[cfg(rustdoc)]
 mod builtin {
 
     /// Unconditionally causes compilation to fail with the given error message when encountered.
index c384ec9168ac4428889fd2ea5df4760f3f1ddd65..1cb9799ff3c22562bcdbcf6b23318c725ac17472 100644 (file)
 //! OS-specific functionality.
 
 #![stable(feature = "os", since = "1.0.0")]
-#![allow(missing_docs, bad_style, missing_debug_implementations)]
+#![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
 
 cfg_if! {
-    if #[cfg(dox)] {
+    if #[cfg(rustdoc)] {
 
         // When documenting libstd we want to show unix/windows/linux modules as
         // these are the "main modules" that are used across platforms. This
index f258ff073e2a7fa390b554bf87c18f317e1e9f93..ce54726baee2a43f0bb60e623b22d2fcbd5509cd 100644 (file)
@@ -221,13 +221,9 @@ pub const fn new() -> Once {
     /// [poison]: struct.Mutex.html#poisoning
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn call_once<F>(&self, f: F) where F: FnOnce() {
-        // Fast path, just see if we've completed initialization.
-        // An `Acquire` load is enough because that makes all the initialization
-        // operations visible to us. The cold path uses SeqCst consistently
-        // because the performance difference really does not matter there,
-        // and SeqCst minimizes the chances of something going wrong.
-        if self.state.load(Ordering::Acquire) == COMPLETE {
-            return
+        // Fast path check
+        if self.is_completed() {
+            return;
         }
 
         let mut f = Some(f);
@@ -282,13 +278,9 @@ pub fn call_once<F>(&self, f: F) where F: FnOnce() {
     /// ```
     #[unstable(feature = "once_poison", issue = "33577")]
     pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) {
-        // same as above, just with a different parameter to `call_inner`.
-        // An `Acquire` load is enough because that makes all the initialization
-        // operations visible to us. The cold path uses SeqCst consistently
-        // because the performance difference really does not matter there,
-        // and SeqCst minimizes the chances of something going wrong.
-        if self.state.load(Ordering::Acquire) == COMPLETE {
-            return
+        // Fast path check
+        if self.is_completed() {
+            return;
         }
 
         let mut f = Some(f);
@@ -297,6 +289,55 @@ pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) {
         });
     }
 
+    /// Returns true if some `call_once` call has completed
+    /// successfuly. Specifically, `is_completed` will return false in
+    /// the following situtations:
+    ///   * `call_once` was not called at all,
+    ///   * `call_once` was called, but has not yet completed,
+    ///   * the `Once` instance is poisoned
+    ///
+    /// It is also possible that immediately after `is_completed`
+    /// returns false, some other thread finishes executing
+    /// `call_once`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_is_completed)]
+    /// use std::sync::Once;
+    ///
+    /// static INIT: Once = Once::new();
+    ///
+    /// assert_eq!(INIT.is_completed(), false);
+    /// INIT.call_once(|| {
+    ///     assert_eq!(INIT.is_completed(), false);
+    /// });
+    /// assert_eq!(INIT.is_completed(), true);
+    /// ```
+    ///
+    /// ```
+    /// #![feature(once_is_completed)]
+    /// use std::sync::Once;
+    /// use std::thread;
+    ///
+    /// static INIT: Once = Once::new();
+    ///
+    /// assert_eq!(INIT.is_completed(), false);
+    /// let handle = thread::spawn(|| {
+    ///     INIT.call_once(|| panic!());
+    /// });
+    /// assert!(handle.join().is_err());
+    /// assert_eq!(INIT.is_completed(), false);
+    /// ```
+    #[unstable(feature = "once_is_completed", issue = "42")]
+    pub fn is_completed(&self) -> bool {
+        // An `Acquire` load is enough because that makes all the initialization
+        // operations visible to us, and, this being a fast path, weaker
+        // ordering helps with performance. This `Acquire` synchronizes with
+        // `SeqCst` operations on the slow path.
+        self.state.load(Ordering::Acquire) == COMPLETE
+    }
+
     // This is a non-generic function to reduce the monomorphization cost of
     // using `call_once` (this isn't exactly a trivial or small implementation).
     //
@@ -312,6 +353,10 @@ pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) {
     fn call_inner(&self,
                   ignore_poisoning: bool,
                   init: &mut dyn FnMut(bool)) {
+
+        // This cold path uses SeqCst consistently because the
+        // performance difference really does not matter there, and
+        // SeqCst minimizes the chances of something going wrong.
         let mut state = self.state.load(Ordering::SeqCst);
 
         'outer: loop {
index e3db60cff8474767167eb02e5e6bb56c20f73ae2..ed3a3865a6caee0f2b5d0d49bd4204f479dc10f6 100644 (file)
@@ -597,7 +597,7 @@ fn frob() {
             thread::spawn(move || {
                 let mut rng = rand::thread_rng();
                 for _ in 0..M {
-                    if rng.gen_weighted_bool(N) {
+                    if rng.gen_bool(1.0 / (N as f64)) {
                         drop(r.write().unwrap());
                     } else {
                         drop(r.read().unwrap());
index c05c837ade27498fef4e2d144e8a378535aa789b..ccf848a9be42057bff8cc695a62fb61bd565c04d 100644 (file)
@@ -28,11 +28,13 @@ pub struct Condvar {
 unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
+const NEW: Condvar = Condvar {
+    condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
+};
+
 impl Condvar {
     pub const fn new() -> Condvar {
-        Condvar {
-            condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
-        }
+        NEW
     }
 
     pub unsafe fn init(&mut self) {}
index 8539aec5e2c07a1cb5ae8427701abb35b7ce0115..dc8624ec8a1b82800e2eb0dfa754007bec729635 100644 (file)
@@ -32,11 +32,13 @@ pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
+const NEW: RWLock = RWLock {
+    lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
+};
+
 impl RWLock {
     pub const fn new() -> RWLock {
-        RWLock {
-            lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
-        }
+        NEW
     }
 
     pub unsafe fn try_read(&self) -> bool {
index c44db3b10722494e4e925987dff53a206bd378b8..61e4ce66eec0fe636e911d6a00f10f5aa3d82f9a 100644 (file)
@@ -57,7 +57,7 @@
 // then later used in the `std::os` module when documenting, for example,
 // Windows when we're compiling for Linux.
 
-#[cfg(dox)]
+#[cfg(rustdoc)]
 cfg_if! {
     if #[cfg(any(unix, target_os = "redox"))] {
         // On unix we'll document what's already available
@@ -77,7 +77,7 @@ pub mod unix_ext {}
     }
 }
 
-#[cfg(dox)]
+#[cfg(rustdoc)]
 cfg_if! {
     if #[cfg(windows)] {
         // On windows we'll just be documenting what's already available
index 4352b72c307735b40d55f4d8da879c706f325e89..f943257c687330c368622f087e42bde74c625f45 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code, missing_docs, bad_style)]
+#![allow(dead_code, missing_docs, nonstandard_style)]
 
 use io::{self, ErrorKind};
 
index 4830e38d6a92fd8c4c2b337e54b97c1af0a848cc..12e14734ff515edbcc7ee43d51916e9ea7bb182e 100644 (file)
@@ -282,7 +282,7 @@ fn drop(&mut self) {
         // reason for this is that if an error occurs we don't actually know if
         // the file descriptor was closed or not, and if we retried (for
         // something like EINTR), we might close another valid file descriptor
-        // (opened after we closed ours.
+        // opened after we closed ours.
         let _ = unsafe { libc::close(self.fd) };
     }
 }
index c738003caf1d9b220a980c1006b79f7ce6eeeb5d..17214be5b054957da532e8d555f447bf252b349e 100644 (file)
@@ -8,27 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(missing_docs, bad_style)]
+#![allow(missing_docs, nonstandard_style)]
 
 use io::{self, ErrorKind};
 use libc;
 
-#[cfg(any(dox, target_os = "linux"))] pub use os::linux as platform;
-
-#[cfg(all(not(dox), target_os = "android"))]   pub use os::android as platform;
-#[cfg(all(not(dox), target_os = "bitrig"))]    pub use os::bitrig as platform;
-#[cfg(all(not(dox), target_os = "dragonfly"))] pub use os::dragonfly as platform;
-#[cfg(all(not(dox), target_os = "freebsd"))]   pub use os::freebsd as platform;
-#[cfg(all(not(dox), target_os = "haiku"))]     pub use os::haiku as platform;
-#[cfg(all(not(dox), target_os = "ios"))]       pub use os::ios as platform;
-#[cfg(all(not(dox), target_os = "macos"))]     pub use os::macos as platform;
-#[cfg(all(not(dox), target_os = "netbsd"))]    pub use os::netbsd as platform;
-#[cfg(all(not(dox), target_os = "openbsd"))]   pub use os::openbsd as platform;
-#[cfg(all(not(dox), target_os = "solaris"))]   pub use os::solaris as platform;
-#[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
-#[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;
-#[cfg(all(not(dox), target_os = "hermit"))]    pub use os::hermit as platform;
+#[cfg(any(rustdoc, target_os = "linux"))] pub use os::linux as platform;
+
+#[cfg(all(not(rustdoc), target_os = "android"))]   pub use os::android as platform;
+#[cfg(all(not(rustdoc), target_os = "bitrig"))]    pub use os::bitrig as platform;
+#[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use os::dragonfly as platform;
+#[cfg(all(not(rustdoc), target_os = "freebsd"))]   pub use os::freebsd as platform;
+#[cfg(all(not(rustdoc), target_os = "haiku"))]     pub use os::haiku as platform;
+#[cfg(all(not(rustdoc), target_os = "ios"))]       pub use os::ios as platform;
+#[cfg(all(not(rustdoc), target_os = "macos"))]     pub use os::macos as platform;
+#[cfg(all(not(rustdoc), target_os = "netbsd"))]    pub use os::netbsd as platform;
+#[cfg(all(not(rustdoc), target_os = "openbsd"))]   pub use os::openbsd as platform;
+#[cfg(all(not(rustdoc), target_os = "solaris"))]   pub use os::solaris as platform;
+#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use os::emscripten as platform;
+#[cfg(all(not(rustdoc), target_os = "fuchsia"))]   pub use os::fuchsia as platform;
+#[cfg(all(not(rustdoc), target_os = "l4re"))]      pub use os::linux as platform;
+#[cfg(all(not(rustdoc), target_os = "hermit"))]    pub use os::hermit as platform;
 
 pub use self::rand::hashmap_random_keys;
 pub use libc::strlen;
index 8c73fe8c6129f12813d97abee98e8304b28dd287..2d10541752c83b3ca21b1ab5cfdfebf91d340250 100644 (file)
@@ -395,30 +395,3 @@ fn on_resolver_failure() {
 
 #[cfg(not(target_env = "gnu"))]
 fn on_resolver_failure() {}
-
-#[cfg(all(test, taget_env = "gnu"))]
-mod test {
-    use super::*;
-
-    #[test]
-    fn test_res_init() {
-        // This mostly just tests that the weak linkage doesn't panic wildly...
-        res_init_if_glibc_before_2_26().unwrap();
-    }
-
-    #[test]
-    fn test_parse_glibc_version() {
-        let cases = [
-            ("0.0", Some((0, 0))),
-            ("01.+2", Some((1, 2))),
-            ("3.4.5.six", Some((3, 4))),
-            ("1", None),
-            ("1.-2", None),
-            ("1.foo", None),
-            ("foo.1", None),
-        ];
-        for &(version_str, parsed) in cases.iter() {
-            assert_eq!(parsed, parse_glibc_version(version_str));
-        }
-    }
-}
index f8f0bbd5bc25070cb042394e56ba9ead29009e34..971e6501c2c2a6088beacceee6c22c6f3ae06893 100644 (file)
@@ -569,3 +569,30 @@ fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
         _ => None
     }
 }
+
+#[cfg(all(test, target_env = "gnu"))]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_glibc_version() {
+        // This mostly just tests that the weak linkage doesn't panic wildly...
+        glibc_version();
+    }
+
+    #[test]
+    fn test_parse_glibc_version() {
+        let cases = [
+            ("0.0", Some((0, 0))),
+            ("01.+2", Some((1, 2))),
+            ("3.4.5.six", Some((3, 4))),
+            ("1", None),
+            ("1.-2", None),
+            ("1.foo", None),
+            ("foo.1", None),
+        ];
+        for &(version_str, parsed) in cases.iter() {
+            assert_eq!(parsed, parse_glibc_version(version_str));
+        }
+    }
+}
index 01c0ada4ffbe531f227fbaec9858831bb56b6367..371e58a20c40dd65a2b182e8aece96079ecfd19e 100644 (file)
@@ -29,8 +29,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
 mod imp {
     use fs::File;
     use io::Read;
+    #[cfg(any(target_os = "linux", target_os = "android"))]
     use libc;
-    use sys::os::errno;
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
@@ -40,9 +40,18 @@ fn getrandom(buf: &mut [u8]) -> libc::c_long {
     }
 
     #[cfg(not(any(target_os = "linux", target_os = "android")))]
-    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
+    fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool { false }
 
+    #[cfg(any(target_os = "linux", target_os = "android"))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
+        use sync::atomic::{AtomicBool, Ordering};
+        use sys::os::errno;
+
+        static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
+        if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
+            return false;
+        }
+
         let mut read = 0;
         while read < v.len() {
             let result = getrandom(&mut v[read..]);
@@ -50,8 +59,11 @@ fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
                 let err = errno() as libc::c_int;
                 if err == libc::EINTR {
                     continue;
+                } else if err == libc::ENOSYS {
+                    GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
+                    return false;
                 } else if err == libc::EAGAIN {
-                    return false
+                    return false;
                 } else {
                     panic!("unexpected getrandom error: {}", err);
                 }
@@ -59,52 +71,26 @@ fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
                 read += result as usize;
             }
         }
-
-        return true
+        true
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
-    fn is_getrandom_available() -> bool {
-        use io;
-        use sync::atomic::{AtomicBool, Ordering};
-        use sync::Once;
-
-        static CHECKER: Once = Once::new();
-        static AVAILABLE: AtomicBool = AtomicBool::new(false);
-
-        CHECKER.call_once(|| {
-            let mut buf: [u8; 0] = [];
-            let result = getrandom(&mut buf);
-            let available = if result == -1 {
-                let err = io::Error::last_os_error().raw_os_error();
-                err != Some(libc::ENOSYS)
-            } else {
-                true
-            };
-            AVAILABLE.store(available, Ordering::Relaxed);
-        });
-
-        AVAILABLE.load(Ordering::Relaxed)
-    }
-
-    #[cfg(not(any(target_os = "linux", target_os = "android")))]
-    fn is_getrandom_available() -> bool { false }
-
     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
+        // 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
+        // work around. The PRNG of /dev/urandom will still be used but over a
+        // possibly predictable entropy pool.
+        if getrandom_fill_bytes(v) {
+            return;
         }
 
-        let mut file = File::open("/dev/urandom")
-            .expect("failed to open /dev/urandom");
-        file.read_exact(v).expect("failed to read /dev/urandom");
+        // getrandom failed because it is permanently or temporarily (because
+        // of missing entropy) unavailable. Open /dev/urandom, read from it,
+        // and close it again.
+        let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
+        file.read_exact(v).expect("failed to read /dev/urandom")
     }
 }
 
index e7476ab37f7c86710a2a7959974b6e104203e41c..03a5b2d779e1f633420f0f85e00f8bb29acb0250 100644 (file)
@@ -297,7 +297,7 @@ pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
     unsupported()
 }
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 pub mod netc {
     pub const AF_INET: u8 = 0;
     pub const AF_INET6: u8 = 1;
index e514a56dcc43681dcb3fd8875e0b900402fa3d9f..4c64322a6dce398c1b3d0065597e4a12c57c613c 100644 (file)
@@ -10,7 +10,7 @@
 
 //! C definitions used by libnative that don't belong in liblibc
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 #![cfg_attr(test, allow(dead_code))]
 #![unstable(issue = "0", feature = "windows_c")]
 
@@ -794,7 +794,7 @@ pub struct FLOATING_SAVE_AREA {
 // will not appear in the final documentation. This should be also defined for
 // other architectures supported by Windows such as ARM, and for historical
 // interest, maybe MIPS and PowerPC as well.
-#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
+#[cfg(all(rustdoc, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
 pub enum CONTEXT {}
 
 #[cfg(target_arch = "aarch64")]
index ccf79de909fa9dd4ca6b51ecafa0f53dce4e8918..31ef9fa2bedfd4a4a0091c661a19db158ae75c0c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(missing_docs, bad_style)]
+#![allow(missing_docs, nonstandard_style)]
 
 use ptr;
 use ffi::{OsStr, OsString};
index b94482435597e4be2b8ceea0fc7914ea16cd7d12..29ea82c2053cdb08df0e6f8de9efc5f96787c82e 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Implementation of `std::os` functionality for Windows
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 
 use os::windows::prelude::*;
 
index ab23936358e7872c15eeb793a908aed39880fde4..a96fb19213999cf7affeea0d2029497e4a0e44c1 100644 (file)
@@ -14,7 +14,7 @@
 pub mod test {
     use path::{Path, PathBuf};
     use env;
-    use rand::{self, Rng};
+    use rand::{self, RngCore};
     use fs;
 
     pub struct TempDir(PathBuf);
index 8acb8a46d7bf229ff81105161c44a03fb25b659e..7302a794480aba5d3157ae71e7af8606ff10c600 100644 (file)
 use std::env::*;
 use std::ffi::{OsString, OsStr};
 
-use rand::Rng;
+use rand::{thread_rng, Rng};
+use rand::distributions::Alphanumeric;
 
 fn make_rand_name() -> OsString {
-    let mut rng = rand::thread_rng();
-    let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
+    let mut rng = thread_rng();
+    let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10)
                                  .collect::<String>());
     let n = OsString::from(n);
     assert!(var_os(&n).is_none());
index 61c6084a25023897c4aa27fec6d6745cc4982e6c..a7c7dbb1b402762b9c59fae8304070a51ce823cb 100644 (file)
@@ -1310,11 +1310,17 @@ pub fn thread(&self) -> &Thread {
 
     /// Waits for the associated thread to finish.
     ///
+    /// In terms of [atomic memory orderings],  the completion of the associated
+    /// thread synchronizes with this function returning. In other words, all
+    /// operations performed by that thread are ordered before all
+    /// operations that happen after `join` returns.
+    ///
     /// If the child thread panics, [`Err`] is returned with the parameter given
     /// to [`panic`].
     ///
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`panic`]: ../../std/macro.panic.html
+    /// [atomic memory orderings]: ../../std/sync/atomic/index.html
     ///
     /// # Panics
     ///
index b6084bcf343072aafefdca06983550ac8196ee76..9851749be3765ff0ba8f7e6ba0ef1b9a7b220472 100644 (file)
@@ -28,8 +28,8 @@
 use tokenstream::{ThinTokenStream, TokenStream};
 
 use serialize::{self, Encoder, Decoder};
-use std::collections::HashSet;
 use std::fmt;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use std::u32;
 
@@ -407,7 +407,7 @@ pub struct WhereEqPredicate {
 
 /// The set of MetaItems that define the compilation environment of the crate,
 /// used to drive conditional compilation
-pub type CrateConfig = HashSet<(Name, Option<Symbol>)>;
+pub type CrateConfig = FxHashSet<(Name, Option<Symbol>)>;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
@@ -857,10 +857,15 @@ pub struct Local {
 pub struct Arm {
     pub attrs: Vec<Attribute>,
     pub pats: Vec<P<Pat>>,
-    pub guard: Option<P<Expr>>,
+    pub guard: Option<Guard>,
     pub body: P<Expr>,
 }
 
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum Guard {
+    If(P<Expr>),
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Field {
     pub ident: Ident,
@@ -1582,7 +1587,7 @@ pub fn is_implicit_self(&self) -> bool {
         if let TyKind::ImplicitSelf = *self { true } else { false }
     }
 
-    crate fn is_unit(&self) -> bool {
+    pub fn is_unit(&self) -> bool {
         if let TyKind::Tup(ref tys) = *self { tys.is_empty() } else { false }
     }
 }
index ecd52a62eab2692601254ed5d9b17ce30593b293..3eecdf14a4e50029eb62d7a161e310bcbd71f905 100644 (file)
@@ -107,7 +107,11 @@ pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
     pub rustc_depr: Option<RustcDeprecation>,
-    pub rustc_const_unstable: Option<RustcConstUnstable>,
+    /// `None` means the function is stable but needs to be allowed by the
+    /// `min_const_fn` feature
+    /// `Some` contains the feature gate required to be able to use the function
+    /// as const fn
+    pub const_stability: Option<Symbol>,
 }
 
 /// The available stability levels.
@@ -141,11 +145,6 @@ pub struct RustcDeprecation {
     pub reason: Symbol,
 }
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct RustcConstUnstable {
-    pub feature: Symbol,
-}
-
 /// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
 /// This will not perform any "sanity checks" on the form of the attributes.
 pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
@@ -176,7 +175,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
 
     let mut stab: Option<Stability> = None;
     let mut rustc_depr: Option<RustcDeprecation> = None;
-    let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
+    let mut rustc_const_unstable: Option<Symbol> = None;
 
     'outer: for attr in attrs_iter {
         if ![
@@ -191,6 +190,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         mark_used(attr);
 
         let meta = attr.meta();
+        // attributes with data
         if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
             let meta = meta.as_ref().unwrap();
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
@@ -272,9 +272,7 @@ macro_rules! get_meta {
 
                     get_meta!(feature);
                     if let Some(feature) = feature {
-                        rustc_const_unstable = Some(RustcConstUnstable {
-                            feature
-                        });
+                        rustc_const_unstable = Some(feature);
                     } else {
                         span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
                         continue
@@ -330,7 +328,7 @@ macro_rules! get_meta {
                                 },
                                 feature,
                                 rustc_depr: None,
-                                rustc_const_unstable: None,
+                                const_stability: None,
                             })
                         }
                         (None, _, _) => {
@@ -379,7 +377,7 @@ macro_rules! get_meta {
                                 },
                                 feature,
                                 rustc_depr: None,
-                                rustc_const_unstable: None,
+                                const_stability: None,
                             })
                         }
                         (None, _) => {
@@ -412,9 +410,9 @@ macro_rules! get_meta {
     }
 
     // Merge the const-unstable info into the stability info
-    if let Some(rustc_const_unstable) = rustc_const_unstable {
+    if let Some(feature) = rustc_const_unstable {
         if let Some(ref mut stab) = stab {
-            stab.rustc_const_unstable = Some(rustc_const_unstable);
+            stab.const_stability = Some(feature);
         } else {
             span_err!(diagnostic, item_sp, E0630,
                       "rustc_const_unstable attribute must be paired with \
index cd9d76822106c431cd07254805310e7e8b1e1227..19bbbceff5fc02f3d6ef9d8e5f7d8421efc3b0f5 100644 (file)
@@ -15,7 +15,7 @@
 pub use self::builtin::{
     cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation,
     find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, IntType, ReprAttr,
-    RustcConstUnstable, RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
+    RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
 };
 pub use self::IntType::*;
 pub use self::ReprAttr::*;
index 0e52434ec0170dc0dcd37600b61da7867fe3dfd3..5233267e3a95af043a0fb1165b3b5e3762f5fac8 100644 (file)
 
 /// A folder that strips out items that do not belong in the current configuration.
 pub struct StripUnconfigured<'a> {
-    pub should_test: bool,
     pub sess: &'a ParseSess,
     pub features: Option<&'a Features>,
 }
 
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, edition: Edition)
+pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
                 -> (ast::Crate, Features) {
     let features;
     {
         let mut strip_unconfigured = StripUnconfigured {
-            should_test,
             sess,
             features: None,
         };
@@ -118,11 +116,6 @@ fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
     // Determine if a node with the given attributes should be included in this configuration.
     pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
         attrs.iter().all(|attr| {
-            // When not compiling with --test we should not compile the #[test] functions
-            if !self.should_test && is_test_or_bench(attr) {
-                return false;
-            }
-
             let mis = if !is_cfg(attr) {
                 return true;
             } else if let Some(mis) = attr.meta_item_list() {
@@ -249,7 +242,7 @@ pub fn configure_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
         //
         // NB: This is intentionally not part of the fold_expr() function
         //     in order for fold_opt_expr() to be able to avoid this check
-        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a) || is_test_or_bench(a)) {
+        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
             let msg = "removing an expression is not supported in this position";
             self.sess.span_diagnostic.span_err(attr.span, msg);
         }
@@ -352,7 +345,3 @@ fn fold_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> {
 fn is_cfg(attr: &ast::Attribute) -> bool {
     attr.check_name("cfg")
 }
-
-pub fn is_test_or_bench(attr: &ast::Attribute) -> bool {
-    attr.check_name("test") || attr.check_name("bench")
-}
index 75d24df7b629fc850a697ecf79837df431c48634..0e059bc4a6ce5a7d29395d5fd7398cf259758350 100644 (file)
@@ -26,7 +26,7 @@
 use symbol::{keywords, Ident, Symbol};
 use ThinVec;
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::iter;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -721,6 +721,7 @@ pub trait Resolver {
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                             derives: &[Mark]);
     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
+    fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
 
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
@@ -729,6 +730,7 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: b
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
                                 -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
+
     fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
                           derives_in_scope: &[ast::Path], force: bool)
                           -> Result<Lrc<SyntaxExtension>, Determinacy>;
@@ -759,6 +761,7 @@ fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
     fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
                                             _derives: &[Mark]) {}
     fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
+    fn add_unshadowable_attr(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
 
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
@@ -800,7 +803,7 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut dyn Resolver,
     pub resolve_err_count: usize,
     pub current_expansion: ExpansionData,
-    pub expansions: HashMap<Span, Vec<String>>,
+    pub expansions: FxHashMap<Span, Vec<String>>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -821,7 +824,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
                 directory_ownership: DirectoryOwnership::Owned { relative: None },
                 crate_span: None,
             },
-            expansions: HashMap::new(),
+            expansions: FxHashMap::default(),
         }
     }
 
index 80bbc618932ef7f89613e9ff82e4527a42e96a04..684cee38874630fa7d0f311cd34d1b729c9177d8 100644 (file)
@@ -17,7 +17,7 @@
 use symbol::Symbol;
 use syntax_pos::Span;
 
-use std::collections::HashSet;
+use rustc_data_structures::fx::FxHashSet;
 
 pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
     let mut result = Vec::new();
@@ -48,7 +48,7 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
 pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path], item: T) -> T
     where T: HasAttrs,
 {
-    let (mut names, mut pretty_name) = (HashSet::new(), "derive(".to_owned());
+    let (mut names, mut pretty_name) = (FxHashSet::default(), "derive(".to_owned());
     for (i, path) in traits.iter().enumerate() {
         if i > 0 {
             pretty_name.push_str(", ");
index a2e84b508dc12be3d042e0ba0348358b30a8fb28..3bb19121ee308ad337851cbf2c057e8e9b96a406 100644 (file)
 use ast::{MacStmtStyle, StmtKind, ItemKind};
 use attr::{self, HasAttrs};
 use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
-use config::{is_test_or_bench, StripUnconfigured};
+use config::StripUnconfigured;
 use errors::{Applicability, FatalError};
 use ext::base::*;
-use ext::build::AstBuilder;
 use ext::derive::{add_derived_markers, collect_derives};
 use ext::hygiene::{self, Mark, SyntaxContext};
 use ext::placeholders::{placeholder, PlaceholderExpander};
 use tokenstream::{TokenStream, TokenTree};
 use visit::{self, Visitor};
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 use std::fs::File;
 use std::io::Read;
-use std::iter::FromIterator;
 use std::{iter, mem};
 use std::rc::Rc;
 use std::path::PathBuf;
@@ -319,7 +317,7 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
         // Unresolved macros produce dummy outputs as a recovery measure.
         invocations.reverse();
         let mut expanded_fragments = Vec::new();
-        let mut derives: HashMap<Mark, Vec<_>> = HashMap::new();
+        let mut derives: FxHashMap<Mark, Vec<_>> = FxHashMap::default();
         let mut undetermined_invocations = Vec::new();
         let (mut progress, mut force) = (false, !self.monotonic);
         loop {
@@ -452,14 +450,12 @@ fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
         let (fragment_with_placeholders, invocations) = {
             let mut collector = InvocationCollector {
                 cfg: StripUnconfigured {
-                    should_test: self.cx.ecfg.should_test,
                     sess: self.cx.parse_sess,
                     features: self.cx.ecfg.features,
                 },
                 cx: self.cx,
                 invocations: Vec::new(),
                 monotonic: self.monotonic,
-                tests_nameable: true,
             };
             (fragment.fold_with(&mut collector), collector.invocations)
         };
@@ -477,7 +473,6 @@ fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
 
     fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
         let mut cfg = StripUnconfigured {
-            should_test: self.cx.ecfg.should_test,
             sess: self.cx.parse_sess,
             features: self.cx.ecfg.features,
         };
@@ -1049,11 +1044,6 @@ struct InvocationCollector<'a, 'b: 'a> {
     cfg: StripUnconfigured<'a>,
     invocations: Vec<Invocation>,
     monotonic: bool,
-
-    /// Test functions need to be nameable. Tests inside functions or in other
-    /// unnameable locations need to be ignored. `tests_nameable` tracks whether
-    /// any test functions found in the current context would be nameable.
-    tests_nameable: bool,
 }
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
@@ -1071,20 +1061,6 @@ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> A
         placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
     }
 
-    /// Folds the item allowing tests to be expanded because they are still nameable.
-    /// This should probably only be called with module items
-    fn fold_nameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
-        fold::noop_fold_item(item, self)
-    }
-
-    /// Folds the item but doesn't allow tests to occur within it
-    fn fold_unnameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
-        let was_nameable = mem::replace(&mut self.tests_nameable, false);
-        let items = fold::noop_fold_item(item, self);
-        self.tests_nameable = was_nameable;
-        items
-    }
-
     fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
         self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
     }
@@ -1299,7 +1275,7 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
     fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         let item = configure!(self, item);
 
-        let (attr, traits, mut item) = self.classify_item(item);
+        let (attr, traits, item) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
             let item = Annotatable::Item(item);
             return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
@@ -1321,7 +1297,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
             }
             ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
                 if item.ident == keywords::Invalid.ident() {
-                    return self.fold_nameable(item);
+                    return noop_fold_item(item, self);
                 }
 
                 let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
@@ -1361,58 +1337,13 @@ fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
 
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
-                let result = self.fold_nameable(item);
+                let result = noop_fold_item(item, self);
                 self.cx.current_expansion.module = orig_module;
                 self.cx.current_expansion.directory_ownership = orig_directory_ownership;
                 result
             }
-            // Ensure that test functions are accessible from the test harness.
-            // #[test] fn foo() {}
-            // becomes:
-            // #[test] pub fn foo_gensym(){}
-            // #[allow(unused)]
-            // use foo_gensym as foo;
-            ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
-                if self.tests_nameable && item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
-                    let orig_ident = item.ident;
-                    let orig_vis   = item.vis.clone();
-
-                    // Publicize the item under gensymed name to avoid pollution
-                    item = item.map(|mut item| {
-                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
-                        item.ident = item.ident.gensym();
-                        item
-                    });
-
-                    // Use the gensymed name under the item's original visibility
-                    let mut use_item = self.cx.item_use_simple_(
-                        item.ident.span,
-                        orig_vis,
-                        Some(orig_ident),
-                        self.cx.path(item.ident.span,
-                            vec![keywords::SelfValue.ident(), item.ident]));
-
-                    // #[allow(unused)] because the test function probably isn't being referenced
-                    use_item = use_item.map(|mut ui| {
-                        ui.attrs.push(
-                            self.cx.attribute(DUMMY_SP, attr::mk_list_item(DUMMY_SP,
-                                Ident::from_str("allow"), vec![
-                                    attr::mk_nested_word_item(Ident::from_str("unused"))
-                                ]
-                            ))
-                        );
-
-                        ui
-                    });
 
-                    OneVector::from_iter(
-                        self.fold_unnameable(item).into_iter()
-                            .chain(self.fold_unnameable(use_item)))
-                } else {
-                    self.fold_unnameable(item)
-                }
-            }
-            _ => self.fold_unnameable(item),
+            _ => noop_fold_item(item, self),
         }
     }
 
@@ -1637,6 +1568,7 @@ pub fn default(crate_name: String) -> ExpansionConfig<'static> {
     feature_tests! {
         fn enable_quotes = quote,
         fn enable_asm = asm,
+        fn enable_custom_test_frameworks = custom_test_frameworks,
         fn enable_global_asm = global_asm,
         fn enable_log_syntax = log_syntax,
         fn enable_concat_idents = concat_idents,
index 7a8ccfddf8eb65cda1440ab7969617b8df838323..5906412883ad0c0356091004cbbe261a8a5e63c6 100644 (file)
@@ -21,7 +21,7 @@
 use ThinVec;
 use util::move_map::MoveMap;
 
-use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashMap;
 
 pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
     fn mac_placeholder() -> ast::Mac {
@@ -81,7 +81,7 @@ fn mac_placeholder() -> ast::Mac {
 }
 
 pub struct PlaceholderExpander<'a, 'b: 'a> {
-    expanded_fragments: HashMap<ast::NodeId, AstFragment>,
+    expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
     cx: &'a mut ExtCtxt<'b>,
     monotonic: bool,
 }
@@ -90,7 +90,7 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
     pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
         PlaceholderExpander {
             cx,
-            expanded_fragments: HashMap::new(),
+            expanded_fragments: FxHashMap::default(),
             monotonic,
         }
     }
index dcdeee5c2e700d015f2a4a7861a98f4ff26703c8..c962e7fcbb4cfce003da8e7f43c0b8eae534cfab 100644 (file)
 use symbol::keywords;
 use tokenstream::TokenStream;
 
+use rustc_data_structures::fx::FxHashMap;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::rc::Rc;
-use std::collections::HashMap;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 
 // To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body.
 
@@ -263,7 +263,7 @@ pub enum ParseResult<T> {
 
 /// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es.
 /// This represents the mapping of metavars to the token trees they bind to.
-pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
+pub type NamedParseResult = ParseResult<FxHashMap<Ident, Rc<NamedMatch>>>;
 
 /// Count how many metavars are named in the given matcher `ms`.
 pub fn count_names(ms: &[TokenTree]) -> usize {
@@ -351,7 +351,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
         sess: &ParseSess,
         m: &TokenTree,
         res: &mut I,
-        ret_val: &mut HashMap<Ident, Rc<NamedMatch>>,
+        ret_val: &mut FxHashMap<Ident, Rc<NamedMatch>>,
     ) -> Result<(), (syntax_pos::Span, String)> {
         match *m {
             TokenTree::Sequence(_, ref seq) => for next_m in &seq.tts {
@@ -382,7 +382,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
         Ok(())
     }
 
-    let mut ret_val = HashMap::new();
+    let mut ret_val = FxHashMap::default();
     for m in ms {
         match n_rec(sess, m, res.by_ref(), &mut ret_val) {
             Ok(_) => {}
index 2c738ac2a04cd864db459a93b3e2b4a4ed8a1d87..d09127d6b08b7a303ffd729c22727f21b798ea0f 100644 (file)
@@ -27,8 +27,8 @@
 use symbol::Symbol;
 use tokenstream::{TokenStream, TokenTree};
 
+use rustc_data_structures::fx::FxHashMap;
 use std::borrow::Cow;
-use std::collections::HashMap;
 use std::collections::hash_map::Entry;
 
 use rustc_data_structures::sync::Lrc;
@@ -451,14 +451,14 @@ struct FirstSets {
     // If two sequences have the same span in a matcher, then map that
     // span to None (invalidating the mapping here and forcing the code to
     // use a slow path).
-    first: HashMap<Span, Option<TokenSet>>,
+    first: FxHashMap<Span, Option<TokenSet>>,
 }
 
 impl FirstSets {
     fn new(tts: &[quoted::TokenTree]) -> FirstSets {
         use self::quoted::TokenTree;
 
-        let mut sets = FirstSets { first: HashMap::new() };
+        let mut sets = FirstSets { first: FxHashMap::default() };
         build_recur(&mut sets, tts);
         return sets;
 
index 67a15b149f6d50bd4dff1b02cfc2522c67d2715b..549e5f00dcec4cbe8cc7478f673140fadc4f0aa6 100644 (file)
 use syntax_pos::{Span, DUMMY_SP};
 use tokenstream::{TokenStream, TokenTree, Delimited};
 
-use std::rc::Rc;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use std::mem;
 use std::ops::Add;
-use std::collections::HashMap;
+use std::rc::Rc;
 
 // An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
 enum Frame {
@@ -67,11 +67,11 @@ fn next(&mut self) -> Option<quoted::TokenTree> {
 /// `src` contains no `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can
 /// (and should) be None.
 pub fn transcribe(cx: &ExtCtxt,
-                  interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+                  interp: Option<FxHashMap<Ident, Rc<NamedMatch>>>,
                   src: Vec<quoted::TokenTree>)
                   -> TokenStream {
     let mut stack: OneVector<Frame> = smallvec![Frame::new(src)];
-    let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */
+    let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */
     let mut repeats = Vec::new();
     let mut result: Vec<TokenStream> = Vec::new();
     let mut result_stack = Vec::new();
@@ -187,7 +187,7 @@ pub fn transcribe(cx: &ExtCtxt,
 }
 
 fn lookup_cur_matched(ident: Ident,
-                      interpolations: &HashMap<Ident, Rc<NamedMatch>>,
+                      interpolations: &FxHashMap<Ident, Rc<NamedMatch>>,
                       repeats: &[(usize, usize)])
                       -> Option<Rc<NamedMatch>> {
     interpolations.get(&ident).map(|matched| {
@@ -234,7 +234,7 @@ fn add(self, other: LockstepIterSize) -> LockstepIterSize {
 }
 
 fn lockstep_iter_size(tree: &quoted::TokenTree,
-                      interpolations: &HashMap<Ident, Rc<NamedMatch>>,
+                      interpolations: &FxHashMap<Ident, Rc<NamedMatch>>,
                       repeats: &[(usize, usize)])
                       -> LockstepIterSize {
     use self::quoted::TokenTree;
index bb5d929a3234573493d8158a259c91b1a68ced3d..e3ea3563d853bb6fc6e2b9bc85f1b56fdddaf852 100644 (file)
 use std::{env, path};
 
 macro_rules! set {
+    // The const_fn feature also enables the min_const_fn feature, because `min_const_fn` allows
+    // the declaration `const fn`, but the `const_fn` feature gate enables things inside those
+    // functions that we do not want to expose to the user for now.
+    (const_fn) => {{
+        fn f(features: &mut Features, _: Span) {
+            features.const_fn = true;
+            features.min_const_fn = true;
+        }
+        f as fn(&mut Features, Span)
+    }};
     ($field: ident) => {{
         fn f(features: &mut Features, _: Span) {
             features.$field = true;
@@ -206,25 +216,28 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // #23121. Array patterns have some hazards yet.
     (active, slice_patterns, "1.0.0", Some(23121), None),
 
-    // Allows the definition of `const fn` functions.
+    // Allows the definition of `const fn` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(24111), None),
 
+    // Allows the definition of `const fn` functions.
+    (active, min_const_fn, "1.30.0", Some(53555), None),
+
     // Allows let bindings and destructuring in `const fn` functions and constants.
     (active, const_let, "1.22.1", Some(48821), None),
 
-    // Allows accessing fields of unions inside const fn
+    // Allows accessing fields of unions inside const fn.
     (active, const_fn_union, "1.27.0", Some(51909), None),
 
-    // Allows casting raw pointers to `usize` during const eval
+    // Allows casting raw pointers to `usize` during const eval.
     (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
 
-    // Allows dereferencing raw pointers during const eval
+    // Allows dereferencing raw pointers during const eval.
     (active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
 
-    // Allows reinterpretation of the bits of a value of one type as another type during const eval
+    // Allows reinterpretation of the bits of a value of one type as another type during const eval.
     (active, const_transmute, "1.29.0", Some(53605), None),
 
-    // Allows comparing raw pointers during const eval
+    // Allows comparing raw pointers during const eval.
     (active, const_compare_raw_pointers, "1.27.0", Some(53020), None),
 
     // Allows panicking during const eval (produces compile-time errors)
@@ -502,6 +515,10 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // unsized rvalues at arguments and parameters
     (active, unsized_locals, "1.30.0", Some(48055), None),
+
+    // #![test_runner]
+    // #[test_case]
+    (active, custom_test_frameworks, "1.30.0", Some(50297), None),
 );
 
 declare_features! (
@@ -645,7 +662,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Defining procedural macros in `proc-macro` crates
     (accepted, proc_macro, "1.29.0", Some(38356), None),
     // Allows use of the :vis macro fragment specifier
-    (accepted, macro_vis_matcher, "1.29.0", Some(41022), None),
+    (accepted, macro_vis_matcher, "1.30.0", Some(41022), None),
     // Allows importing and reexporting macros with `use`,
     // enables macro modularization in general.
     (accepted, use_extern_macros, "1.30.0", Some(35896), None),
@@ -752,8 +769,6 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("cfg_attr", Normal, Ungated),
     ("main", Normal, Ungated),
     ("start", Normal, Ungated),
-    ("test", Normal, Ungated),
-    ("bench", Normal, Ungated),
     ("repr", Normal, Ungated),
     ("path", Normal, Ungated),
     ("abi", Normal, Ungated),
@@ -946,6 +961,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                                       attribute is just used for rustc unit \
                                                       tests and will never be stable",
                                                      cfg_fn!(rustc_attrs))),
+    ("rustc_test_marker", Normal, Gated(Stability::Unstable,
+                                     "rustc_attrs",
+                                     "the `#[rustc_test_marker]` attribute \
+                                      is used internally to track tests",
+                                     cfg_fn!(rustc_attrs))),
 
     // RFC #2094
     ("nll", Whitelisted, Gated(Stability::Unstable,
@@ -1143,6 +1163,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("no_builtins", CrateLevel, Ungated),
     ("recursion_limit", CrateLevel, Ungated),
     ("type_length_limit", CrateLevel, Ungated),
+    ("test_runner", CrateLevel, Gated(Stability::Unstable,
+                    "custom_test_frameworks",
+                    EXPLAIN_CUSTOM_TEST_FRAMEWORKS,
+                    cfg_fn!(custom_test_frameworks))),
 ];
 
 // cfg(...)'s that are feature gated
@@ -1151,6 +1175,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
     ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
     ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
+    ("rustdoc", "doc_cfg", cfg_fn!(doc_cfg)),
 ];
 
 #[derive(Debug)]
@@ -1358,6 +1383,9 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue
 pub const EXPLAIN_GLOBAL_ASM: &'static str =
     "`global_asm!` is not stable enough for use and is subject to change";
 
+pub const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &'static str =
+    "custom test frameworks are an unstable feature";
+
 pub const EXPLAIN_LOG_SYNTAX: &'static str =
     "`log_syntax!` is not stable enough for use and is subject to change";
 
@@ -1786,7 +1814,7 @@ fn visit_fn(&mut self,
                     gate_feature_post!(&self, async_await, span, "async fn is unstable");
                 }
                 if header.constness.node == ast::Constness::Const {
-                    gate_feature_post!(&self, const_fn, span, "const fn is unstable");
+                    gate_feature_post!(&self, min_const_fn, span, "const fn is unstable");
                 }
                 // stability of const fn methods are covered in
                 // visit_trait_item and visit_impl_item below; this is
@@ -1844,7 +1872,7 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
         match ii.node {
             ast::ImplItemKind::Method(ref sig, _) => {
                 if sig.header.constness.node == ast::Constness::Const {
-                    gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
+                    gate_feature_post!(&self, min_const_fn, ii.span, "const fn is unstable");
                 }
             }
             ast::ImplItemKind::Existential(..) => {
index 660056e15e06b61f669c6d3fc16a4c1d5c089166..dff408d233977b559c99dce845735fba927c8956 100644 (file)
@@ -118,6 +118,10 @@ fn fold_arm(&mut self, a: Arm) -> Arm {
         noop_fold_arm(a, self)
     }
 
+    fn fold_guard(&mut self, g: Guard) -> Guard {
+        noop_fold_guard(g, self)
+    }
+
     fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
         noop_fold_pat(p, self)
     }
@@ -354,11 +358,17 @@ pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm,
     Arm {
         attrs: fold_attrs(attrs, fld),
         pats: pats.move_map(|x| fld.fold_pat(x)),
-        guard: guard.map(|x| fld.fold_expr(x)),
+        guard: guard.map(|x| fld.fold_guard(x)),
         body: fld.fold_expr(body),
     }
 }
 
+pub fn noop_fold_guard<T: Folder>(g: Guard, fld: &mut T) -> Guard {
+    match g {
+        Guard::If(e) => Guard::If(fld.fold_expr(e)),
+    }
+}
+
 pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
     TypeBinding {
         id: fld.new_id(b.id),
index 448ff9676c927492791e6ac08ec42391fdecfc0f..96584a580f1758d72e5797aee7bb11255362dae1 100644 (file)
@@ -1831,10 +1831,10 @@ mod tests {
     use errors;
     use feature_gate::UnstableFeatures;
     use parse::token;
-    use std::collections::HashSet;
     use std::io;
     use std::path::PathBuf;
     use diagnostics::plugin::ErrorMap;
+    use rustc_data_structures::fx::FxHashSet;
     use rustc_data_structures::sync::Lock;
     use with_globals;
     fn mk_sess(cm: Lrc<SourceMap>) -> ParseSess {
@@ -1845,10 +1845,10 @@ fn mk_sess(cm: Lrc<SourceMap>) -> ParseSess {
         ParseSess {
             span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
             unstable_features: UnstableFeatures::from_environment(),
-            config: CrateConfig::new(),
+            config: CrateConfig::default(),
             included_mod_stack: Lock::new(Vec::new()),
             code_map: cm,
-            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            missing_fragment_specifiers: Lock::new(FxHashSet::default()),
             raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
             non_modrs_mods: Lock::new(vec![]),
index 1136cda5ee3597587c3332eb8cede5982f22c217..28d63399b4461f3c024a30820fb3a43ff2d3b757 100644 (file)
@@ -24,8 +24,8 @@
 use tokenstream::{TokenStream, TokenTree};
 use diagnostics::plugin::ErrorMap;
 
+use rustc_data_structures::fx::FxHashSet;
 use std::borrow::Cow;
-use std::collections::HashSet;
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::str;
@@ -46,7 +46,7 @@ pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
-    pub missing_fragment_specifiers: Lock<HashSet<Span>>,
+    pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
     /// Places where raw identifiers were used. This is used for feature gating
     /// raw identifiers
     pub raw_identifier_spans: Lock<Vec<Span>>,
@@ -75,8 +75,8 @@ pub fn with_span_handler(handler: Handler, code_map: Lrc<SourceMap>) -> ParseSes
         ParseSess {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
-            config: HashSet::new(),
-            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            config: FxHashSet::default(),
+            missing_fragment_specifiers: Lock::new(FxHashSet::default()),
             raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
             included_mod_stack: Lock::new(vec![]),
index 1695d3a8f96b033cb41cbc8ecb70230766356131..5f80af77f494046f0353f2470f39d826edf2cf7d 100644 (file)
@@ -12,7 +12,7 @@
 use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
 use ast::{GenericBound, TraitBoundModifier};
 use ast::Unsafety;
-use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
+use ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
 use ast::Block;
 use ast::{BlockCheckMode, CaptureBy, Movability};
 use ast::{Constness, Crate};
@@ -786,7 +786,12 @@ fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
         } else {
             err.span_label(self.span, "expected identifier");
             if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
-                err.span_suggestion(self.span, "remove this comma", String::new());
+                err.span_suggestion_with_applicability(
+                    self.span,
+                    "remove this comma",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
             }
         }
         err
@@ -1155,9 +1160,7 @@ fn parse_unspanned_seq<T, F>(&mut self,
     {
         self.expect(bra)?;
         let result = self.parse_seq_to_before_end(ket, sep, f)?;
-        if self.token == *ket {
-            self.bump();
-        }
+        self.eat(ket);
         Ok(result)
     }
 
@@ -1353,8 +1356,7 @@ fn parse_trait_item_(&mut self,
             let ident = self.parse_ident()?;
             self.expect(&token::Colon)?;
             let ty = self.parse_ty()?;
-            let default = if self.check(&token::Eq) {
-                self.bump();
+            let default = if self.eat(&token::Eq) {
                 let expr = self.parse_expr()?;
                 self.expect(&token::Semi)?;
                 Some(expr)
@@ -2265,10 +2267,8 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 while self.token != token::CloseDelim(token::Paren) {
                     es.push(self.parse_expr()?);
                     self.expect_one_of(&[], &[token::Comma, token::CloseDelim(token::Paren)])?;
-                    if self.check(&token::Comma) {
+                    if self.eat(&token::Comma) {
                         trailing_comma = true;
-
-                        self.bump();
                     } else {
                         trailing_comma = false;
                         break;
@@ -2294,25 +2294,22 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
 
                 attrs.extend(self.parse_inner_attributes()?);
 
-                if self.check(&token::CloseDelim(token::Bracket)) {
+                if self.eat(&token::CloseDelim(token::Bracket)) {
                     // Empty vector.
-                    self.bump();
                     ex = ExprKind::Array(Vec::new());
                 } else {
                     // Nonempty vector.
                     let first_expr = self.parse_expr()?;
-                    if self.check(&token::Semi) {
+                    if self.eat(&token::Semi) {
                         // Repeating array syntax: [ 0; 512 ]
-                        self.bump();
                         let count = AnonConst {
                             id: ast::DUMMY_NODE_ID,
                             value: self.parse_expr()?,
                         };
                         self.expect(&token::CloseDelim(token::Bracket))?;
                         ex = ExprKind::Repeat(first_expr, count);
-                    } else if self.check(&token::Comma) {
+                    } else if self.eat(&token::Comma) {
                         // Vector with two or more elements.
-                        self.bump();
                         let remaining_exprs = self.parse_seq_to_end(
                             &token::CloseDelim(token::Bracket),
                             SeqSep::trailing_allowed(token::Comma),
@@ -3528,7 +3525,7 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<E
         self.eat(&token::BinOp(token::Or));
         let pats = self.parse_pats()?;
         let guard = if self.eat_keyword(keywords::If) {
-            Some(self.parse_expr()?)
+            Some(Guard::If(self.parse_expr()?))
         } else {
             None
         };
@@ -3619,8 +3616,7 @@ fn parse_expr_res(&mut self, r: Restrictions,
 
     /// Parse the RHS of a local variable declaration (e.g. '= 14;')
     fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
-        if self.check(&token::Eq) {
-            self.bump();
+        if self.eat(&token::Eq) {
             Ok(Some(self.parse_expr()?))
         } else if skip_eq {
             Ok(Some(self.parse_expr()?))
@@ -3646,8 +3642,8 @@ fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> {
                 );
                 err.emit();
                 self.bump();
-            } else if self.check(&token::BinOp(token::Or)) {
-                self.bump();
+            } else if self.eat(&token::BinOp(token::Or)) {
+                // No op.
             } else {
                 return Ok(pats);
             }
@@ -6083,7 +6079,12 @@ fn parse_single_struct_field(&mut self,
                                                                 self.this_token_to_string()));
                 if self.token.is_ident() {
                     // This is likely another field; emit the diagnostic and keep going
-                    err.span_suggestion(sp, "try adding a comma", ",".into());
+                    err.span_suggestion_with_applicability(
+                        sp,
+                        "try adding a comma",
+                        ",".into(),
+                        Applicability::MachineApplicable,
+                    );
                     err.emit();
                 } else {
                     return Err(err)
@@ -6271,7 +6272,6 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
         let (in_cfg, outer_attrs) = {
             let mut strip_unconfigured = ::config::StripUnconfigured {
                 sess: self.sess,
-                should_test: false, // irrelevant
                 features: None, // don't perform gated feature checking
             };
             let outer_attrs = strip_unconfigured.process_cfg_attrs(outer_attrs.to_owned());
@@ -6280,8 +6280,7 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
 
         let id_span = self.span;
         let id = self.parse_ident()?;
-        if self.check(&token::Semi) {
-            self.bump();
+        if self.eat(&token::Semi) {
             if in_cfg && self.recurse_into_file_modules {
                 // This mod is in an external file. Let's go get it!
                 let ModulePathSuccess { path, directory_ownership, warn } =
index e78e1afe3a4025543dff3f2e856abd82d3edcfae..85d29a5be89db03b1e8303e55d3f9907f41a503f 100644 (file)
@@ -2702,10 +2702,14 @@ fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
         self.print_outer_attributes(&arm.attrs)?;
         self.print_pats(&arm.pats)?;
         self.s.space()?;
-        if let Some(ref e) = arm.guard {
-            self.word_space("if")?;
-            self.print_expr(e)?;
-            self.s.space()?;
+        if let Some(ref g) = arm.guard {
+            match g {
+                ast::Guard::If(ref e) => {
+                    self.word_space("if")?;
+                    self.print_expr(e)?;
+                    self.s.space()?;
+                }
+            }
         }
         self.word_space("=>")?;
 
index 8f91db8efa71a66a9096560dd73557040a29f0a3..95839f94b9efea279e3437c1d06d7817a5eee1fe 100644 (file)
@@ -24,7 +24,7 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::sync::{Lrc, Lock, LockGuard};
+use rustc_data_structures::sync::{Lrc, Lock, LockGuard, MappedLockGuard};
 use std::cmp;
 use std::hash::Hash;
 use std::path::{Path, PathBuf};
@@ -194,7 +194,7 @@ pub fn load_file(&self, path: &Path) -> io::Result<Lrc<SourceFile>> {
         Ok(self.new_source_file(filename, src))
     }
 
-    pub fn files(&self) -> LockGuard<Vec<Lrc<SourceFile>>> {
+    pub fn files(&self) -> MappedLockGuard<Vec<Lrc<SourceFile>>> {
         LockGuard::map(self.files.borrow(), |files| &mut files.file_maps)
     }
 
index 49ab0c2256e89674c3e983217f79daad314345bf..ab67736c389c0164f20c1093dac4a73995ffb9dc 100644 (file)
@@ -22,7 +22,7 @@
 use attr::{self, HasAttrs};
 use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos};
 
-use source_map::{self, SourceMap, ExpnInfo, MacroAttribute, dummy_spanned};
+use source_map::{self, SourceMap, ExpnInfo, MacroAttribute, dummy_spanned, respan};
 use errors;
 use config;
 use entry::{self, EntryPointType};
 use ThinVec;
 use rustc_data_structures::small_vec::ExpectOne;
 
-enum ShouldPanic {
-    No,
-    Yes(Option<Symbol>),
-}
-
 struct Test {
     span: Span,
-    path: Vec<Ident> ,
-    bench: bool,
-    ignore: bool,
-    should_panic: ShouldPanic,
-    allow_fail: bool,
+    path: Vec<Ident>,
 }
 
 struct TestCtxt<'a> {
     span_diagnostic: &'a errors::Handler,
     path: Vec<Ident>,
     ext_cx: ExtCtxt<'a>,
-    testfns: Vec<Test>,
+    test_cases: Vec<Test>,
     reexport_test_harness_main: Option<Symbol>,
     is_libtest: bool,
     ctxt: SyntaxContext,
     features: &'a Features,
+    test_runner: Option<ast::Path>,
 
     // top-level re-export submodule, filled out after folding is finished
     toplevel_reexport: Option<Ident>,
@@ -87,9 +79,13 @@ pub fn modify_for_testing(sess: &ParseSess,
         attr::first_attr_value_str_by_name(&krate.attrs,
                                            "reexport_test_harness_main");
 
+    // Do this here so that the test_runner crate attribute gets marked as used
+    // even in non-test builds
+    let test_runner = get_test_runner(span_diagnostic, &krate);
+
     if should_test {
         generate_test_harness(sess, resolver, reexport_test_harness_main,
-                              krate, span_diagnostic, features)
+                              krate, span_diagnostic, features, test_runner)
     } else {
         krate
     }
@@ -107,13 +103,13 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
     fn fold_crate(&mut self, c: ast::Crate) -> ast::Crate {
         let mut folded = fold::noop_fold_crate(c, self);
 
-        // Add a special __test module to the crate that will contain code
-        // generated for the test harness
-        let (mod_, reexport) = mk_test_module(&mut self.cx);
-        if let Some(re) = reexport {
-            folded.module.items.push(re)
-        }
-        folded.module.items.push(mod_);
+        // Create a main function to run our tests
+        let test_main = {
+            let unresolved = mk_main(&mut self.cx);
+            self.cx.ext_cx.monotonic_expander().fold_item(unresolved).pop().unwrap()
+        };
+
+        folded.module.items.push(test_main);
         folded
     }
 
@@ -124,41 +120,18 @@ fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
         }
         debug!("current path: {}", path_name_i(&self.cx.path));
 
-        if is_test_fn(&self.cx, &i) || is_bench_fn(&self.cx, &i) {
-            match i.node {
-                ast::ItemKind::Fn(_, header, _, _) => {
-                    if header.unsafety == ast::Unsafety::Unsafe {
-                        let diag = self.cx.span_diagnostic;
-                        diag.span_fatal(
-                            i.span,
-                            "unsafe functions cannot be used for tests"
-                        ).raise();
-                    }
-                    if header.asyncness.is_async() {
-                        let diag = self.cx.span_diagnostic;
-                        diag.span_fatal(
-                            i.span,
-                            "async functions cannot be used for tests"
-                        ).raise();
-                    }
-                }
-                _ => {},
-            }
+        let mut item = i.into_inner();
+        if is_test_case(&item) {
+            debug!("this is a test item");
 
-            debug!("this is a test function");
             let test = Test {
-                span: i.span,
+                span: item.span,
                 path: self.cx.path.clone(),
-                bench: is_bench_fn(&self.cx, &i),
-                ignore: is_ignored(&i),
-                should_panic: should_panic(&i, &self.cx),
-                allow_fail: is_allowed_fail(&i),
             };
-            self.cx.testfns.push(test);
-            self.tests.push(i.ident);
+            self.cx.test_cases.push(test);
+            self.tests.push(item.ident);
         }
 
-        let mut item = i.into_inner();
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
         if let ast::ItemKind::Mod(module) = item.node {
@@ -190,6 +163,8 @@ fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
 }
 
+/// A folder used to remove any entry points (like fn main) because the harness
+/// generator will provide its own
 struct EntryPointCleaner {
     // Current depth in the ast
     depth: usize,
@@ -242,6 +217,10 @@ fn fold_item(&mut self, i: P<ast::Item>) -> OneVector<P<ast::Item>> {
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
 }
 
+/// Creates an item (specifically a module) that "pub use"s the tests passed in.
+/// Each tested submodule will contain a similar reexport module that we will export
+/// under the name of the original module. That is, `submod::__test_reexports` is
+/// reexported like so `pub use submod::__test_reexports as submod`.
 fn mk_reexport_mod(cx: &mut TestCtxt,
                    parent: ast::NodeId,
                    tests: Vec<Ident>,
@@ -279,12 +258,14 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
     (it, sym)
 }
 
+/// Crawl over the crate, inserting test reexports and the test main function
 fn generate_test_harness(sess: &ParseSess,
                          resolver: &mut dyn Resolver,
                          reexport_test_harness_main: Option<Symbol>,
                          krate: ast::Crate,
                          sd: &errors::Handler,
-                         features: &Features) -> ast::Crate {
+                         features: &Features,
+                         test_runner: Option<ast::Path>) -> ast::Crate {
     // Remove the entry points
     let mut cleaner = EntryPointCleaner { depth: 0 };
     let krate = cleaner.fold_crate(krate);
@@ -298,19 +279,20 @@ fn generate_test_harness(sess: &ParseSess,
         span_diagnostic: sd,
         ext_cx: ExtCtxt::new(sess, econfig, resolver),
         path: Vec::new(),
-        testfns: Vec::new(),
+        test_cases: Vec::new(),
         reexport_test_harness_main,
         // NB: doesn't consider the value of `--crate-name` passed on the command line.
         is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false),
         toplevel_reexport: None,
         ctxt: SyntaxContext::empty().apply_mark(mark),
         features,
+        test_runner
     };
 
     mark.set_expn_info(ExpnInfo {
         call_site: DUMMY_SP,
         def_site: None,
-        format: MacroAttribute(Symbol::intern("test")),
+        format: MacroAttribute(Symbol::intern("test_case")),
         allow_internal_unstable: true,
         allow_internal_unsafe: false,
         local_inner_macros: false,
@@ -344,216 +326,64 @@ enum BadTestSignature {
     ShouldPanicOnlyWithNoArgs,
 }
 
-fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
-    let has_test_attr = attr::contains_name(&i.attrs, "test");
-
-    fn has_test_signature(_cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
-        let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
-        match i.node {
-            ast::ItemKind::Fn(ref decl, _, ref generics, _) => {
-                // If the termination trait is active, the compiler will check that the output
-                // type implements the `Termination` trait as `libtest` enforces that.
-                let has_output = match decl.output {
-                    ast::FunctionRetTy::Default(..) => false,
-                    ast::FunctionRetTy::Ty(ref t) if t.node.is_unit() => false,
-                    _ => true
-                };
-
-                if !decl.inputs.is_empty() {
-                    return No(BadTestSignature::NoArgumentsAllowed);
-                }
-
-                match (has_output, has_should_panic_attr) {
-                    (true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
-                    (true, false) => if !generics.params.is_empty() {
-                        No(BadTestSignature::WrongTypeSignature)
-                    } else {
-                        Yes
-                    },
-                    (false, _) => Yes
-                }
-            }
-            _ => No(BadTestSignature::NotEvenAFunction),
-        }
-    }
-
-    let has_test_signature = if has_test_attr {
-        let diag = cx.span_diagnostic;
-        match has_test_signature(cx, i) {
-            Yes => true,
-            No(cause) => {
-                match cause {
-                    BadTestSignature::NotEvenAFunction =>
-                        diag.span_err(i.span, "only functions may be used as tests"),
-                    BadTestSignature::WrongTypeSignature =>
-                        diag.span_err(i.span,
-                                      "functions used as tests must have signature fn() -> ()"),
-                    BadTestSignature::NoArgumentsAllowed =>
-                        diag.span_err(i.span, "functions used as tests can not have any arguments"),
-                    BadTestSignature::ShouldPanicOnlyWithNoArgs =>
-                        diag.span_err(i.span, "functions using `#[should_panic]` must return `()`"),
-                }
-                false
-            }
-        }
-    } else {
-        false
-    };
-
-    has_test_attr && has_test_signature
-}
-
-fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
-    let has_bench_attr = attr::contains_name(&i.attrs, "bench");
-
-    fn has_bench_signature(_cx: &TestCtxt, i: &ast::Item) -> bool {
-        match i.node {
-            ast::ItemKind::Fn(ref decl, _, _, _) => {
-                // NB: inadequate check, but we're running
-                // well before resolve, can't get too deep.
-                decl.inputs.len() == 1
-            }
-            _ => false
-        }
-    }
-
-    let has_bench_signature = has_bench_signature(cx, i);
-
-    if has_bench_attr && !has_bench_signature {
-        let diag = cx.span_diagnostic;
-
-        diag.span_err(i.span, "functions used as benches must have signature \
-                                   `fn(&mut Bencher) -> impl Termination`");
-    }
-
-    has_bench_attr && has_bench_signature
-}
-
-fn is_ignored(i: &ast::Item) -> bool {
-    attr::contains_name(&i.attrs, "ignore")
-}
-
-fn is_allowed_fail(i: &ast::Item) -> bool {
-    attr::contains_name(&i.attrs, "allow_fail")
-}
-
-fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
-    match attr::find_by_name(&i.attrs, "should_panic") {
-        Some(attr) => {
-            let sd = cx.span_diagnostic;
-            if attr.is_value_str() {
-                sd.struct_span_warn(
-                    attr.span(),
-                    "attribute must be of the form: \
-                     `#[should_panic]` or \
-                     `#[should_panic(expected = \"error message\")]`"
-                ).note("Errors in this attribute were erroneously allowed \
-                        and will become a hard error in a future release.")
-                .emit();
-                return ShouldPanic::Yes(None);
-            }
-            match attr.meta_item_list() {
-                // Handle #[should_panic]
-                None => ShouldPanic::Yes(None),
-                // Handle #[should_panic(expected = "foo")]
-                Some(list) => {
-                    let msg = list.iter()
-                        .find(|mi| mi.check_name("expected"))
-                        .and_then(|mi| mi.meta_item())
-                        .and_then(|mi| mi.value_str());
-                    if list.len() != 1 || msg.is_none() {
-                        sd.struct_span_warn(
-                            attr.span(),
-                            "argument must be of the form: \
-                             `expected = \"error message\"`"
-                        ).note("Errors in this attribute were erroneously \
-                                allowed and will become a hard error in a \
-                                future release.").emit();
-                        ShouldPanic::Yes(None)
-                    } else {
-                        ShouldPanic::Yes(msg)
-                    }
-                },
-            }
-        }
-        None => ShouldPanic::No,
-    }
-}
-
-/*
-
-We're going to be building a module that looks more or less like:
-
-mod __test {
-  extern crate test (name = "test", vers = "...");
-  fn main() {
-    test::test_main_static(&::os::args()[], tests, test::Options::new())
-  }
-
-  static tests : &'static [test::TestDescAndFn] = &[
-    ... the list of tests in the crate ...
-  ];
-}
-
-*/
-
-fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
-    let id_test = Ident::from_str("test");
-    let sp = ignored_span(cx, DUMMY_SP);
-    let (vi, vis, ident) = if cx.is_libtest {
-        (ast::ItemKind::Use(P(ast::UseTree {
-            span: DUMMY_SP,
-            prefix: path_node(vec![id_test]),
-            kind: ast::UseTreeKind::Simple(None, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID),
-        })),
-         ast::VisibilityKind::Public, keywords::Invalid.ident())
-    } else {
-        (ast::ItemKind::ExternCrate(None), ast::VisibilityKind::Inherited, id_test)
-    };
-    P(ast::Item {
-        id: ast::DUMMY_NODE_ID,
-        ident,
-        node: vi,
-        attrs: vec![],
-        vis: dummy_spanned(vis),
-        span: sp,
-        tokens: None,
-    })
-}
-
+/// Creates a function item for use as the main function of a test build.
+/// This function will call the `test_runner` as specified by the crate attribute
 fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
     // Writing this out by hand with 'ignored_span':
     //        pub fn main() {
     //            #![main]
-    //            use std::slice::AsSlice;
-    //            test::test_main_static(::std::os::args().as_slice(), TESTS, test::Options::new());
+    //            test::test_main_static(::std::os::args().as_slice(), &[..tests]);
     //        }
-
     let sp = ignored_span(cx, DUMMY_SP);
     let ecx = &cx.ext_cx;
-
-    // test::test_main_static
-    let test_main_path =
-        ecx.path(sp, vec![Ident::from_str("test"), Ident::from_str("test_main_static")]);
+    let test_id = ecx.ident_of("test").gensym();
 
     // test::test_main_static(...)
-    let test_main_path_expr = ecx.expr_path(test_main_path);
-    let tests_ident_expr = ecx.expr_ident(sp, Ident::from_str("TESTS"));
+    let mut test_runner = cx.test_runner.clone().unwrap_or(
+        ecx.path(sp, vec![
+            test_id, ecx.ident_of("test_main_static")
+        ]));
+
+    test_runner.span = sp;
+
+    let test_main_path_expr = ecx.expr_path(test_runner.clone());
     let call_test_main = ecx.expr_call(sp, test_main_path_expr,
-                                       vec![tests_ident_expr]);
+                                       vec![mk_tests_slice(cx)]);
     let call_test_main = ecx.stmt_expr(call_test_main);
+
     // #![main]
     let main_meta = ecx.meta_word(sp, Symbol::intern("main"));
     let main_attr = ecx.attribute(sp, main_meta);
+
+    // extern crate test as test_gensym
+    let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp,
+        test_id,
+        vec![],
+        ast::ItemKind::ExternCrate(Some(Symbol::intern("test")))
+    ));
+
     // pub fn main() { ... }
     let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
-    let main_body = ecx.block(sp, vec![call_test_main]);
+
+    // If no test runner is provided we need to import the test crate
+    let main_body = if cx.test_runner.is_none() {
+        ecx.block(sp, vec![test_extern_stmt, call_test_main])
+    } else {
+        ecx.block(sp, vec![call_test_main])
+    };
+
     let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)),
                            ast::FnHeader::default(),
                            ast::Generics::default(),
                            main_body);
+
+    // Honor the reexport_test_harness_main attribute
+    let main_id = Ident::new(
+        cx.reexport_test_harness_main.unwrap_or(Symbol::gensym("main")),
+        sp);
+
     P(ast::Item {
-        ident: Ident::from_str("main"),
+        ident: main_id,
         attrs: vec![main_attr],
         id: ast::DUMMY_NODE_ID,
         node: main,
@@ -561,71 +391,7 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
         span: sp,
         tokens: None,
     })
-}
-
-fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
-    // Link to test crate
-    let import = mk_std(cx);
-
-    // A constant vector of test descriptors.
-    let tests = mk_tests(cx);
-
-    // The synthesized main function which will call the console test runner
-    // with our list of tests
-    let mainfn = mk_main(cx);
 
-    let testmod = ast::Mod {
-        inner: DUMMY_SP,
-        items: vec![import, mainfn, tests],
-    };
-    let item_ = ast::ItemKind::Mod(testmod);
-    let mod_ident = Ident::with_empty_ctxt(Symbol::gensym("__test"));
-
-    let mut expander = cx.ext_cx.monotonic_expander();
-    let item = expander.fold_item(P(ast::Item {
-        id: ast::DUMMY_NODE_ID,
-        ident: mod_ident,
-        attrs: vec![],
-        node: item_,
-        vis: dummy_spanned(ast::VisibilityKind::Public),
-        span: DUMMY_SP,
-        tokens: None,
-    })).pop().unwrap();
-    let reexport = cx.reexport_test_harness_main.map(|s| {
-        // building `use __test::main as <ident>;`
-        let rename = Ident::with_empty_ctxt(s);
-
-        let use_path = ast::UseTree {
-            span: DUMMY_SP,
-            prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
-            kind: ast::UseTreeKind::Simple(Some(rename), ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID),
-        };
-
-        expander.fold_item(P(ast::Item {
-            id: ast::DUMMY_NODE_ID,
-            ident: keywords::Invalid.ident(),
-            attrs: vec![],
-            node: ast::ItemKind::Use(P(use_path)),
-            vis: dummy_spanned(ast::VisibilityKind::Inherited),
-            span: DUMMY_SP,
-            tokens: None,
-        })).pop().unwrap()
-    });
-
-    debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item));
-
-    (item, reexport)
-}
-
-fn nospan<T>(t: T) -> source_map::Spanned<T> {
-    source_map::Spanned { node: t, span: DUMMY_SP }
-}
-
-fn path_node(ids: Vec<Ident>) -> ast::Path {
-    ast::Path {
-        span: DUMMY_SP,
-        segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id)).collect(),
-    }
 }
 
 fn path_name_i(idents: &[Ident]) -> String {
@@ -640,184 +406,46 @@ fn path_name_i(idents: &[Ident]) -> String {
     path_name
 }
 
-fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
-    // The vector of test_descs for this crate
-    let test_descs = mk_test_descs(cx);
-
-    // FIXME #15962: should be using quote_item, but that stringifies
-    // __test_reexports, causing it to be reinterned, losing the
-    // gensym information.
-    let sp = ignored_span(cx, DUMMY_SP);
-    let ecx = &cx.ext_cx;
-    let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"),
-                                                    ecx.ident_of("test"),
-                                                    ecx.ident_of("TestDescAndFn")]));
-    let static_lt = ecx.lifetime(sp, keywords::StaticLifetime.ident());
-    // &'static [self::test::TestDescAndFn]
-    let static_type = ecx.ty_rptr(sp,
-                                  ecx.ty(sp, ast::TyKind::Slice(struct_type)),
-                                  Some(static_lt),
-                                  ast::Mutability::Immutable);
-    // static TESTS: $static_type = &[...];
-    ecx.item_const(sp,
-                   ecx.ident_of("TESTS"),
-                   static_type,
-                   test_descs)
+/// Creates a slice containing every test like so:
+/// &[path::to::test1, path::to::test2]
+fn mk_tests_slice(cx: &TestCtxt) -> P<ast::Expr> {
+    debug!("building test vector from {} tests", cx.test_cases.len());
+    let ref ecx = cx.ext_cx;
+
+    ecx.expr_vec_slice(DUMMY_SP,
+        cx.test_cases.iter().map(|test| {
+            ecx.expr_addr_of(test.span,
+                ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path))))
+        }).collect())
 }
 
-fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
-    debug!("building test vector from {} tests", cx.testfns.len());
-
-    P(ast::Expr {
-        id: ast::DUMMY_NODE_ID,
-        node: ast::ExprKind::AddrOf(ast::Mutability::Immutable,
-            P(ast::Expr {
-                id: ast::DUMMY_NODE_ID,
-                node: ast::ExprKind::Array(cx.testfns.iter().map(|test| {
-                    mk_test_desc_and_fn_rec(cx, test)
-                }).collect()),
-                span: DUMMY_SP,
-                attrs: ThinVec::new(),
-            })),
-        span: DUMMY_SP,
-        attrs: ThinVec::new(),
-    })
-}
-
-fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
-    // FIXME #15962: should be using quote_expr, but that stringifies
-    // __test_reexports, causing it to be reinterned, losing the
-    // gensym information.
-
-    let span = ignored_span(cx, test.span);
-    let ecx = &cx.ext_cx;
-    let self_id = ecx.ident_of("self");
-    let test_id = ecx.ident_of("test");
-
-    // creates self::test::$name
-    let test_path = |name| {
-        ecx.path(span, vec![self_id, test_id, ecx.ident_of(name)])
-    };
-    // creates $name: $expr
-    let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
-
-    // path to the #[test] function: "foo::bar::baz"
-    let path_string = path_name_i(&test.path[..]);
-
-    debug!("encoding {}", path_string);
-
-    let name_expr = ecx.expr_str(span, Symbol::intern(&path_string));
-
-    // self::test::StaticTestName($name_expr)
-    let name_expr = ecx.expr_call(span,
-                                  ecx.expr_path(test_path("StaticTestName")),
-                                  vec![name_expr]);
-
-    let ignore_expr = ecx.expr_bool(span, test.ignore);
-    let should_panic_path = |name| {
-        ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldPanic"), ecx.ident_of(name)])
-    };
-    let fail_expr = match test.should_panic {
-        ShouldPanic::No => ecx.expr_path(should_panic_path("No")),
-        ShouldPanic::Yes(msg) => {
-            match msg {
-                Some(msg) => {
-                    let msg = ecx.expr_str(span, msg);
-                    let path = should_panic_path("YesWithMessage");
-                    ecx.expr_call(span, ecx.expr_path(path), vec![msg])
-                }
-                None => ecx.expr_path(should_panic_path("Yes")),
-            }
-        }
-    };
-    let allow_fail_expr = ecx.expr_bool(span, test.allow_fail);
-
-    // self::test::TestDesc { ... }
-    let desc_expr = ecx.expr_struct(
-        span,
-        test_path("TestDesc"),
-        vec![field("name", name_expr),
-             field("ignore", ignore_expr),
-             field("should_panic", fail_expr),
-             field("allow_fail", allow_fail_expr)]);
-
+/// Creates a path from the top-level __test module to the test via __test_reexports
+fn visible_path(cx: &TestCtxt, path: &[Ident]) -> Vec<Ident>{
     let mut visible_path = vec![];
-    if cx.features.extern_absolute_paths {
-        visible_path.push(keywords::Crate.ident());
-    }
     match cx.toplevel_reexport {
         Some(id) => visible_path.push(id),
         None => {
-            let diag = cx.span_diagnostic;
-            diag.bug("expected to find top-level re-export name, but found None");
-        }
-    };
-    visible_path.extend_from_slice(&test.path[..]);
-
-    // Rather than directly give the test function to the test
-    // harness, we create a wrapper like one of the following:
-    //
-    //     || test::assert_test_result(real_function()) // for test
-    //     |b| test::assert_test_result(real_function(b)) // for bench
-    //
-    // this will coerce into a fn pointer that is specialized to the
-    // actual return type of `real_function` (Typically `()`, but not always).
-    let fn_expr = {
-        // construct `real_function()` (this will be inserted into the overall expr)
-        let real_function_expr = ecx.expr_path(ecx.path_global(span, visible_path));
-        // construct path `test::assert_test_result`
-        let assert_test_result = test_path("assert_test_result");
-        if test.bench {
-            // construct `|b| {..}`
-            let b_ident = Ident::with_empty_ctxt(Symbol::gensym("b"));
-            let b_expr = ecx.expr_ident(span, b_ident);
-            ecx.lambda(
-                span,
-                vec![b_ident],
-                // construct `assert_test_result(..)`
-                ecx.expr_call(
-                    span,
-                    ecx.expr_path(assert_test_result),
-                    vec![
-                        // construct `real_function(b)`
-                        ecx.expr_call(
-                            span,
-                            real_function_expr,
-                            vec![b_expr],
-                        )
-                    ],
-                ),
-            )
-        } else {
-            // construct `|| {..}`
-            ecx.lambda(
-                span,
-                vec![],
-                // construct `assert_test_result(..)`
-                ecx.expr_call(
-                    span,
-                    ecx.expr_path(assert_test_result),
-                    vec![
-                        // construct `real_function()`
-                        ecx.expr_call(
-                            span,
-                            real_function_expr,
-                            vec![],
-                        )
-                    ],
-                ),
-            )
+            cx.span_diagnostic.bug("expected to find top-level re-export name, but found None");
         }
-    };
-
-    let variant_name = if test.bench { "StaticBenchFn" } else { "StaticTestFn" };
+    }
+    visible_path.extend_from_slice(path);
+    visible_path
+}
 
-    // self::test::$variant_name($fn_expr)
-    let testfn_expr = ecx.expr_call(span, ecx.expr_path(test_path(variant_name)), vec![fn_expr]);
+fn is_test_case(i: &ast::Item) -> bool {
+    attr::contains_name(&i.attrs, "rustc_test_marker")
+}
 
-    // self::test::TestDescAndFn { ... }
-    ecx.expr_struct(span,
-                    test_path("TestDescAndFn"),
-                    vec![field("desc", desc_expr),
-                         field("testfn", testfn_expr)])
+fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
+    let test_attr = attr::find_by_name(&krate.attrs, "test_runner")?;
+    if let Some(meta_list) = test_attr.meta_item_list() {
+        if meta_list.len() != 1 {
+            sd.span_fatal(test_attr.span(),
+                "#![test_runner(..)] accepts exactly 1 argument").raise()
+        }
+        Some(meta_list[0].word().as_ref().unwrap().ident.clone())
+    } else {
+        sd.span_fatal(test_attr.span(),
+            "test_runner must be of the form #[test_runner(..)]").raise()
+    }
 }
index e57d692faae53de63a428a61c17342beb98459d9..77311bf53fd1e84e5c0b1e5f9fc190993e0ed133 100644 (file)
@@ -819,7 +819,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
 
 pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
     walk_list!(visitor, visit_pat, &arm.pats);
-    walk_list!(visitor, visit_expr, &arm.guard);
+    if let Some(ref g) = &arm.guard {
+        match g {
+            Guard::If(ref e) => visitor.visit_expr(e),
+        }
+    }
     visitor.visit_expr(&arm.body);
     walk_list!(visitor, visit_attribute, &arm.attrs);
 }
index 8dba34583bef3ff25b1d8045a77dfc1a938f8285..5a691bde3ecb3c24886bccc936a7e5acbeaa4633 100644 (file)
@@ -17,3 +17,4 @@ syntax_pos = { path = "../libsyntax_pos" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "0.6.5", features = ["union"] }
+log = "0.4"
index b23c2ec3db1011437ac717d9212794b410fbd8c7..efe9c2cefdebe93b3e1e4f646e2b2093061ae5b3 100644 (file)
@@ -24,9 +24,9 @@
 use syntax_pos::{MultiSpan, Span, DUMMY_SP};
 use errors::Applicability;
 
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
-use std::collections::{HashMap, HashSet};
 
 #[derive(PartialEq)]
 enum ArgumentType {
@@ -65,7 +65,7 @@ struct Context<'a, 'b: 'a> {
     /// Unique format specs seen for each argument.
     arg_unique_types: Vec<Vec<ArgumentType>>,
     /// Map from named arguments to their resolved indices.
-    names: HashMap<String, usize>,
+    names: FxHashMap<String, usize>,
 
     /// The latest consecutive literal strings, or empty if there weren't any.
     literal: String,
@@ -104,7 +104,7 @@ struct Context<'a, 'b: 'a> {
     /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]`
     count_args: Vec<Position>,
     /// Relative slot numbers for count arguments.
-    count_positions: HashMap<usize, usize>,
+    count_positions: FxHashMap<usize, usize>,
     /// Number of count slots assigned.
     count_positions_count: usize,
 
@@ -134,9 +134,9 @@ struct Context<'a, 'b: 'a> {
 fn parse_args(ecx: &mut ExtCtxt,
               sp: Span,
               tts: &[tokenstream::TokenTree])
-              -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, HashMap<String, usize>)> {
+              -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, FxHashMap<String, usize>)> {
     let mut args = Vec::<P<ast::Expr>>::new();
-    let mut names = HashMap::<String, usize>::new();
+    let mut names = FxHashMap::<String, usize>::default();
 
     let mut p = ecx.new_parser_from_tts(tts);
 
@@ -768,7 +768,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
                                     sp: Span,
                                     efmt: P<ast::Expr>,
                                     args: Vec<P<ast::Expr>>,
-                                    names: HashMap<String, usize>,
+                                    names: FxHashMap<String, usize>,
                                     append_newline: bool)
                                     -> P<ast::Expr> {
     // NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
@@ -852,7 +852,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         curpiece: 0,
         arg_index_map: Vec::new(),
         count_args: Vec::new(),
-        count_positions: HashMap::new(),
+        count_positions: FxHashMap::default(),
         count_positions_count: 0,
         count_args_index_offset: 0,
         literal: String::new(),
@@ -952,7 +952,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
 
             // The set of foreign substitutions we've explained.  This prevents spamming the user
             // with `%d should be written as {}` over and over again.
-            let mut explained = HashSet::new();
+            let mut explained = FxHashSet::default();
 
             macro_rules! check_foreign {
                 ($kind:ident) => {{
index 84436b4e4eacf84cfcfc0d2bb8d535abb3a2a558..e16f3b1ccb3f3da4fe4b5b15bf1e4727b11af074 100644 (file)
@@ -19,7 +19,7 @@
 #![cfg_attr(not(stage0), feature(nll))]
 #![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(str_escape)]
-
+#![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 
 extern crate fmt_macros;
@@ -32,6 +32,8 @@
 extern crate rustc_target;
 #[macro_use]
 extern crate smallvec;
+#[macro_use]
+extern crate log;
 
 mod diagnostics;
 
@@ -51,6 +53,8 @@
 mod global_asm;
 mod log_syntax;
 mod trace_macros;
+mod test;
+mod test_case;
 
 pub mod proc_macro_registrar;
 
@@ -59,7 +63,7 @@
 
 use rustc_data_structures::sync::Lrc;
 use syntax::ast;
-use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension};
+use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension, MultiModifier};
 use syntax::ext::hygiene;
 use syntax::symbol::Symbol;
 
@@ -68,6 +72,18 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
                          enable_quotes: bool) {
     deriving::register_builtin_derives(resolver);
 
+    {
+        let mut register_unshadowable = |name, ext| {
+            resolver.add_unshadowable_attr(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
+        };
+
+        register_unshadowable(Symbol::intern("test"),
+            MultiModifier(Box::new(test::expand_test)));
+
+        register_unshadowable(Symbol::intern("bench"),
+            MultiModifier(Box::new(test::expand_bench)));
+    }
+
     let mut register = |name, ext| {
         resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
     };
@@ -130,6 +146,8 @@ macro_rules! register {
         assert: assert::expand_assert,
     }
 
+    register(Symbol::intern("test_case"), MultiModifier(Box::new(test_case::expand)));
+
     // format_args uses `unstable` things internally.
     register(Symbol::intern("format_args"),
              NormalTT {
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
new file mode 100644 (file)
index 0000000..be3485c
--- /dev/null
@@ -0,0 +1,334 @@
+// 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 expansion from a test function to the appropriate test struct for libtest
+/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
+
+use syntax::ext::base::*;
+use syntax::ext::build::AstBuilder;
+use syntax::ext::hygiene::{self, Mark, SyntaxContext};
+use syntax::attr;
+use syntax::ast;
+use syntax::print::pprust;
+use syntax::symbol::Symbol;
+use syntax_pos::{DUMMY_SP, Span};
+use syntax::source_map::{ExpnInfo, MacroAttribute};
+use std::iter;
+
+pub fn expand_test(
+    cx: &mut ExtCtxt,
+    attr_sp: Span,
+    _meta_item: &ast::MetaItem,
+    item: Annotatable,
+) -> Vec<Annotatable> {
+    expand_test_or_bench(cx, attr_sp, item, false)
+}
+
+pub fn expand_bench(
+    cx: &mut ExtCtxt,
+    attr_sp: Span,
+    _meta_item: &ast::MetaItem,
+    item: Annotatable,
+) -> Vec<Annotatable> {
+    expand_test_or_bench(cx, attr_sp, item, true)
+}
+
+pub fn expand_test_or_bench(
+    cx: &mut ExtCtxt,
+    attr_sp: Span,
+    item: Annotatable,
+    is_bench: bool
+) -> Vec<Annotatable> {
+    // If we're not in test configuration, remove the annotated item
+    if !cx.ecfg.should_test { return vec![]; }
+
+    let item =
+        if let Annotatable::Item(i) = item { i }
+        else {
+            cx.parse_sess.span_diagnostic.span_fatal(item.span(),
+                "#[test] attribute is only allowed on fn items").raise();
+        };
+
+    if let ast::ItemKind::Mac(_) = item.node {
+        cx.parse_sess.span_diagnostic.span_warn(item.span,
+            "#[test] attribute should not be used on macros. Use #[cfg(test)] instead.");
+        return vec![Annotatable::Item(item)];
+    }
+
+    // has_*_signature will report any errors in the type so compilation
+    // will fail. We shouldn't try to expand in this case because the errors
+    // would be spurious.
+    if (!is_bench && !has_test_signature(cx, &item)) ||
+        (is_bench && !has_bench_signature(cx, &item)) {
+        return vec![Annotatable::Item(item)];
+    }
+
+    let (sp, attr_sp) = {
+        let mark = Mark::fresh(Mark::root());
+        mark.set_expn_info(ExpnInfo {
+            call_site: DUMMY_SP,
+            def_site: None,
+            format: MacroAttribute(Symbol::intern("test")),
+            allow_internal_unstable: true,
+            allow_internal_unsafe: false,
+            local_inner_macros: false,
+            edition: hygiene::default_edition(),
+        });
+        (item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)),
+         attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
+    };
+
+    // Gensym "test" so we can extern crate without conflicting with any local names
+    let test_id = cx.ident_of("test").gensym();
+
+    // creates test::$name
+    let test_path = |name| {
+        cx.path(sp, vec![test_id, cx.ident_of(name)])
+    };
+
+    // creates test::$name
+    let should_panic_path = |name| {
+        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)])
+    };
+
+    // creates $name: $expr
+    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr);
+
+    let test_fn = if is_bench {
+        // A simple ident for a lambda
+        let b = cx.ident_of("b");
+
+        cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![
+            // |b| self::test::assert_test_result(
+            cx.lambda1(sp,
+                cx.expr_call(sp, cx.expr_path(test_path("assert_test_result")), vec![
+                    // super::$test_fn(b)
+                    cx.expr_call(sp,
+                        cx.expr_path(cx.path(sp, vec![item.ident])),
+                        vec![cx.expr_ident(sp, b)])
+                ]),
+                b
+            )
+            // )
+        ])
+    } else {
+        cx.expr_call(sp, cx.expr_path(test_path("StaticTestFn")), vec![
+            // || {
+            cx.lambda0(sp,
+                // test::assert_test_result(
+                cx.expr_call(sp, cx.expr_path(test_path("assert_test_result")), vec![
+                    // $test_fn()
+                    cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![])
+                // )
+                ])
+            // }
+            )
+        // )
+        ])
+    };
+
+    let mut test_const = cx.item(sp, item.ident.gensym(),
+        vec![
+            // #[cfg(test)]
+            cx.attribute(attr_sp, cx.meta_list(attr_sp, Symbol::intern("cfg"), vec![
+                cx.meta_list_item_word(attr_sp, Symbol::intern("test"))
+            ])),
+            // #[rustc_test_marker]
+            cx.attribute(attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker")))
+        ],
+        // const $ident: test::TestDescAndFn =
+        ast::ItemKind::Const(cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
+            // test::TestDescAndFn {
+            cx.expr_struct(sp, test_path("TestDescAndFn"), vec![
+                // desc: test::TestDesc {
+                field("desc", cx.expr_struct(sp, test_path("TestDesc"), vec![
+                    // name: "path::to::test"
+                    field("name", cx.expr_call(sp, cx.expr_path(test_path("StaticTestName")),
+                        vec![
+                            cx.expr_str(sp, Symbol::intern(&item_path(
+                                // skip the name of the root module
+                                &cx.current_expansion.module.mod_path[1..],
+                                &item.ident
+                            )))
+                        ])),
+                    // ignore: true | false
+                    field("ignore", cx.expr_bool(sp, should_ignore(&item))),
+                    // allow_fail: true | false
+                    field("allow_fail", cx.expr_bool(sp, should_fail(&item))),
+                    // should_panic: ...
+                    field("should_panic", match should_panic(cx, &item) {
+                        // test::ShouldPanic::No
+                        ShouldPanic::No => cx.expr_path(should_panic_path("No")),
+                        // test::ShouldPanic::Yes
+                        ShouldPanic::Yes(None) => cx.expr_path(should_panic_path("Yes")),
+                        // test::ShouldPanic::YesWithMessage("...")
+                        ShouldPanic::Yes(Some(sym)) => cx.expr_call(sp,
+                            cx.expr_path(should_panic_path("YesWithMessage")),
+                            vec![cx.expr_str(sp, sym)]),
+                    }),
+                // },
+                ])),
+                // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...)
+                field("testfn", test_fn)
+            // }
+            ])
+        // }
+        ));
+    test_const = test_const.map(|mut tc| { tc.vis.node = ast::VisibilityKind::Public; tc});
+
+    // extern crate test as test_gensym
+    let test_extern = cx.item(sp,
+        test_id,
+        vec![],
+        ast::ItemKind::ExternCrate(Some(Symbol::intern("test")))
+    );
+
+    debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
+
+    vec![
+        // Access to libtest under a gensymed name
+        Annotatable::Item(test_extern),
+        // The generated test case
+        Annotatable::Item(test_const),
+        // The original item
+        Annotatable::Item(item)
+    ]
+}
+
+fn item_path(mod_path: &[ast::Ident], item_ident: &ast::Ident) -> String {
+    mod_path.iter().chain(iter::once(item_ident))
+        .map(|x| x.to_string()).collect::<Vec<String>>().join("::")
+}
+
+enum ShouldPanic {
+    No,
+    Yes(Option<Symbol>),
+}
+
+fn should_ignore(i: &ast::Item) -> bool {
+    attr::contains_name(&i.attrs, "ignore")
+}
+
+fn should_fail(i: &ast::Item) -> bool {
+    attr::contains_name(&i.attrs, "allow_fail")
+}
+
+fn should_panic(cx: &ExtCtxt, i: &ast::Item) -> ShouldPanic {
+    match attr::find_by_name(&i.attrs, "should_panic") {
+        Some(attr) => {
+            let ref sd = cx.parse_sess.span_diagnostic;
+            if attr.is_value_str() {
+                sd.struct_span_warn(
+                    attr.span(),
+                    "attribute must be of the form: \
+                     `#[should_panic]` or \
+                     `#[should_panic(expected = \"error message\")]`"
+                ).note("Errors in this attribute were erroneously allowed \
+                        and will become a hard error in a future release.")
+                .emit();
+                return ShouldPanic::Yes(None);
+            }
+            match attr.meta_item_list() {
+                // Handle #[should_panic]
+                None => ShouldPanic::Yes(None),
+                // Handle #[should_panic(expected = "foo")]
+                Some(list) => {
+                    let msg = list.iter()
+                        .find(|mi| mi.check_name("expected"))
+                        .and_then(|mi| mi.meta_item())
+                        .and_then(|mi| mi.value_str());
+                    if list.len() != 1 || msg.is_none() {
+                        sd.struct_span_warn(
+                            attr.span(),
+                            "argument must be of the form: \
+                             `expected = \"error message\"`"
+                        ).note("Errors in this attribute were erroneously \
+                                allowed and will become a hard error in a \
+                                future release.").emit();
+                        ShouldPanic::Yes(None)
+                    } else {
+                        ShouldPanic::Yes(msg)
+                    }
+                },
+            }
+        }
+        None => ShouldPanic::No,
+    }
+}
+
+fn has_test_signature(cx: &ExtCtxt, i: &ast::Item) -> bool {
+    let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
+    let ref sd = cx.parse_sess.span_diagnostic;
+    if let ast::ItemKind::Fn(ref decl, ref header, ref generics, _) = i.node {
+        if header.unsafety == ast::Unsafety::Unsafe {
+            sd.span_err(
+                i.span,
+                "unsafe functions cannot be used for tests"
+            );
+            return false
+        }
+        if header.asyncness.is_async() {
+            sd.span_err(
+                i.span,
+                "async functions cannot be used for tests"
+            );
+            return false
+        }
+
+
+        // If the termination trait is active, the compiler will check that the output
+        // type implements the `Termination` trait as `libtest` enforces that.
+        let has_output = match decl.output {
+            ast::FunctionRetTy::Default(..) => false,
+            ast::FunctionRetTy::Ty(ref t) if t.node.is_unit() => false,
+            _ => true
+        };
+
+        if !decl.inputs.is_empty() {
+            sd.span_err(i.span, "functions used as tests can not have any arguments");
+            return false;
+        }
+
+        match (has_output, has_should_panic_attr) {
+            (true, true) => {
+                sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
+                false
+            },
+            (true, false) => if !generics.params.is_empty() {
+                sd.span_err(i.span,
+                                "functions used as tests must have signature fn() -> ()");
+                false
+            } else {
+                true
+            },
+            (false, _) => true
+        }
+    } else {
+        sd.span_err(i.span, "only functions may be used as tests");
+        false
+    }
+}
+
+fn has_bench_signature(cx: &ExtCtxt, i: &ast::Item) -> bool {
+    let has_sig = if let ast::ItemKind::Fn(ref decl, _, _, _) = i.node {
+        // NB: inadequate check, but we're running
+        // well before resolve, can't get too deep.
+        decl.inputs.len() == 1
+    } else {
+        false
+    };
+
+    if !has_sig {
+        cx.parse_sess.span_diagnostic.span_err(i.span, "functions used as benches must have \
+            signature `fn(&mut Bencher) -> impl Termination`");
+    }
+
+    has_sig
+}
diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs
new file mode 100644 (file)
index 0000000..0128db7
--- /dev/null
@@ -0,0 +1,75 @@
+
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// #[test_case] is used by custom test authors to mark tests
+// When building for test, it needs to make the item public and gensym the name
+// Otherwise, we'll omit the item. This behavior means that any item annotated
+// with #[test_case] is never addressable.
+//
+// We mark item with an inert attribute "rustc_test_marker" which the test generation
+// logic will pick up on.
+
+use syntax::ext::base::*;
+use syntax::ext::build::AstBuilder;
+use syntax::ext::hygiene::{self, Mark, SyntaxContext};
+use syntax::ast;
+use syntax::source_map::respan;
+use syntax::symbol::Symbol;
+use syntax_pos::{DUMMY_SP, Span};
+use syntax::source_map::{ExpnInfo, MacroAttribute};
+use syntax::feature_gate;
+
+pub fn expand(
+    ecx: &mut ExtCtxt,
+    attr_sp: Span,
+    _meta_item: &ast::MetaItem,
+    anno_item: Annotatable
+) -> Vec<Annotatable> {
+    if !ecx.ecfg.enable_custom_test_frameworks() {
+        feature_gate::emit_feature_err(&ecx.parse_sess,
+                                       "custom_test_frameworks",
+                                       attr_sp,
+                                       feature_gate::GateIssue::Language,
+                                       feature_gate::EXPLAIN_CUSTOM_TEST_FRAMEWORKS);
+
+        return vec![anno_item];
+    }
+
+    if !ecx.ecfg.should_test { return vec![]; }
+
+    let sp = {
+        let mark = Mark::fresh(Mark::root());
+        mark.set_expn_info(ExpnInfo {
+            call_site: DUMMY_SP,
+            def_site: None,
+            format: MacroAttribute(Symbol::intern("test_case")),
+            allow_internal_unstable: true,
+            allow_internal_unsafe: false,
+            local_inner_macros: false,
+            edition: hygiene::default_edition(),
+        });
+        attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
+    };
+
+    let mut item = anno_item.expect_item();
+
+    item = item.map(|mut item| {
+        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
+        item.ident = item.ident.gensym();
+        item.attrs.push(
+            ecx.attribute(sp,
+                ecx.meta_word(sp, Symbol::intern("rustc_test_marker")))
+        );
+        item
+    });
+
+    return vec![Annotatable::Item(item)]
+}
index 99342f362360b90b048d45a6bd2471f7c3ae1ebc..7e985cf52f550d1aa1f8c95cd5ba9fbdd0dad2b6 100644 (file)
@@ -21,8 +21,7 @@
 use symbol::Symbol;
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
-use std::collections::HashMap;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
@@ -190,7 +189,7 @@ pub fn looks_like_proc_macro_derive(self) -> bool {
 crate struct HygieneData {
     marks: Vec<MarkData>,
     syntax_contexts: Vec<SyntaxContextData>,
-    markings: HashMap<(SyntaxContext, Mark, Transparency), SyntaxContext>,
+    markings: FxHashMap<(SyntaxContext, Mark, Transparency), SyntaxContext>,
     default_edition: Edition,
 }
 
@@ -212,7 +211,7 @@ impl HygieneData {
                 opaque: SyntaxContext(0),
                 opaque_and_semitransparent: SyntaxContext(0),
             }],
-            markings: HashMap::new(),
+            markings: FxHashMap::default(),
             default_edition: Edition::Edition2015,
         }
     }
@@ -231,7 +230,7 @@ pub fn set_default_edition(edition: Edition) {
 }
 
 pub fn clear_markings() {
-    HygieneData::with(|data| data.markings = HashMap::new());
+    HygieneData::with(|data| data.markings = FxHashMap::default());
 }
 
 impl SyntaxContext {
index f7e0788a884c3a60586decd5d7e2d67c4db16344..3c803ad82337f600ada136fbeeeec02ed7e290c4 100644 (file)
@@ -50,7 +50,7 @@ fn write_event(
 impl<T: Write> OutputFormatter for JsonFormatter<T> {
     fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
         self.write_message(&*format!(
-            r#"{{ "type": "suite", "event": "started", "test_count": "{}" }}"#,
+            r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#,
             test_count
         ))
     }
@@ -136,7 +136,7 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
              \"allowed_fail\": {}, \
              \"ignored\": {}, \
              \"measured\": {}, \
-             \"filtered_out\": \"{}\" }}",
+             \"filtered_out\": {} }}",
             if state.failed == 0 { "ok" } else { "failed" },
             state.passed,
             state.failed + state.allowed_fail,
index 29d7cfd2a3a2120c430b47a307e67524643b04bc..bf3cb7c537bd0da9879851e85c5c1d5312c49d94 100644 (file)
@@ -41,6 +41,7 @@
 #![feature(panic_unwind)]
 #![feature(staged_api)]
 #![feature(termination_trait_lib)]
+#![feature(test)]
 
 extern crate getopts;
 #[cfg(any(unix, target_os = "cloudabi"))]
@@ -302,7 +303,7 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Options) {
 // a Vec<TestDescAndFn> is used in order to effect ownership-transfer
 // semantics into parallel test runners, which in turn requires a Vec<>
 // rather than a &[].
-pub fn test_main_static(tests: &[TestDescAndFn]) {
+pub fn test_main_static(tests: &[&TestDescAndFn]) {
     let args = env::args().collect::<Vec<_>>();
     let owned_tests = tests
         .iter()
@@ -1184,7 +1185,7 @@ fn get_concurrency() -> usize {
     };
 
     #[cfg(windows)]
-    #[allow(bad_style)]
+    #[allow(nonstandard_style)]
     fn num_cpus() -> usize {
         #[repr(C)]
         struct SYSTEM_INFO {
index ddb5dcf2a1cd3a2d8ee7acf416542f3d10cf1919..9a8749712c355122f874648dc060eec333100920 100644 (file)
@@ -907,7 +907,8 @@ fn test_sum_f64_between_ints_that_sum_to_0() {
 
 #[cfg(test)]
 mod bench {
-    use Bencher;
+    extern crate test;
+    use self::test::Bencher;
     use stats::Stats;
 
     #[bench]
index 73a259bd4438e90edf46788f7be470412d4e0ec8..43c3e1e7666239568d219c4dd2299e8ae8521132 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style)]
+#![allow(nonstandard_style)]
 
 macro_rules! cfg_if {
     ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) =>
index e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7..2a1cdeadd3ea8e1eba9cc681037b83f07332763b 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7
+Subproject commit 2a1cdeadd3ea8e1eba9cc681037b83f07332763b
index 09befdaae37c5971a331f2c19376876c1d21491c..5c4bb61781ed1367b99cdb91ba42275336a01dd5 100644 (file)
@@ -1123,6 +1123,28 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
   return true;
 }
 
+extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
+                                                      const char*, // importing module name
+                                                      const char*); // imported module name
+
+// Calls `module_name_callback` for each module import done by ThinLTO.
+// The callback is provided with regular null-terminated C strings.
+extern "C" void
+LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *data,
+                                LLVMRustModuleNameCallback module_name_callback,
+                                void* callback_payload) {
+  for (const auto& importing_module : data->ImportLists) {
+    const std::string importing_module_id = importing_module.getKey().str();
+    const auto& imports = importing_module.getValue();
+    for (const auto& imported_module : imports) {
+      const std::string imported_module_id = imported_module.getKey().str();
+      module_name_callback(callback_payload,
+                           importing_module_id.c_str(),
+                           imported_module_id.c_str());
+    }
+  }
+}
+
 // This struct and various functions are sort of a hack right now, but the
 // problem is that we've got in-memory LLVM modules after we generate and
 // optimize all codegen-units for one compilation in rustc. To be compatible
@@ -1288,6 +1310,11 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
   report_fatal_error("ThinLTO not available");
 }
 
+extern "C" LLVMRustThinLTOModuleImports
+LLVMRustGetLLVMRustThinLTOModuleImports(const LLVMRustThinLTOData *Data) {
+  report_fatal_error("ThinLTO not available");
+}
+
 extern "C" void
 LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
   report_fatal_error("ThinLTO not available");
index 7da830e1125bab2f7e2788ab8a4546d7b7584d05..24a384fceb857fe17e5c2553dff5df6a5396d5b9 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-08-02
+2018-08-22
index c2ff846721c5f87584197f6bd1f8b99f88cea85c..14624176436000dbd682ee8d1b1aa564a70a92d9 100644 (file)
@@ -13,7 +13,7 @@
 
 // NB: We do not expect *any* monomorphization to be generated here.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![deny(dead_code)]
 #![crate_type = "rlib"]
 
index 9cabcd9157a6acdb78fcb3b2233aa497477d690e..3ea20aa921e1bf6f6646bf9aa3a7dceae2432da3 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-Clink-dead-code
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![crate_type = "rlib"]
 
 // This test makes sure that, when -Clink-dead-code is specified, we generate
index 8ccb5878c40456d449fb746836dc5697124f083f..082f15a39dd955254c7b94b62ef41ef0eeb9f295 100644 (file)
@@ -49,5 +49,5 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_late_lint_pass(box Pass);
-    reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]);
+    reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]);
 }
index a5ba9ef9bd35dd844d1ea5d1ca2a30cd6b572823..fea81f0cc8fa4c6a48f2600646aa58d7caadd19b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
 // On platforms *without* `#[thread_local]`, use
index 134f114e6accacd30e663420eba8758d53e7866b..7067e7250728fa9aae942e139587e21ab50cfd7e 100644 (file)
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
 
-#![rustc_partition_codegened(module="issue_49595-__test", cfg="cfail2")]
+#![rustc_partition_codegened(module="issue_49595-tests", cfg="cfail2")]
 #![rustc_partition_codegened(module="issue_49595-lit_test", cfg="cfail3")]
 
 mod tests {
-    #[cfg_attr(not(cfail1), ignore)]
-    #[test]
+    #[cfg_attr(not(cfail1), test)]
     fn test() {
     }
 }
index 646c4312fc21f9598197ad5ebf719c735fd11762..1bf740fdec6192beaf4cc5e25ed26d849193f876 100644 (file)
@@ -15,7 +15,7 @@
 
 // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 static TEST_SIGNED: i128 = const_signed(-222);
 static TEST_UNSIGNED: u128 = const_unsigned(200);
index b4b54e13a698ee87d2334ca6a3eae888e1b48ab6..235df8a6785d4d4d100d1d2d3afccaf165e8a845 100644 (file)
@@ -10,9 +10,9 @@
 
 // ignore-emscripten
 
-// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no
+// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 static TEST_SIGNED: i128 = const_signed(-222);
 static TEST_UNSIGNED: u128 = const_unsigned(200);
@@ -63,103 +63,65 @@ fn main() {
 // END RUST SOURCE
 
 // START rustc.const_signed.Lower128Bit.after.mir
-//     _8 = _1;
-//     _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10;
-//     ...
-//     _7 = move (_9.0: i128);
-//     ...
-//     _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11;
-//     ...
-//     _6 = move (_10.0: i128);
-//     ...
-//     _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12;
-//     ...
-//     _5 = move (_11.0: i128);
-//     ...
-//     _12 = Eq(const 4i128, const 0i128);
-//     assert(!move _12, "attempt to divide by zero") -> bb4;
-//     ...
-//     _13 = Eq(const 4i128, const -1i128);
-//     _14 = Eq(_5, const -170141183460469231731687303715884105728i128);
-//     _15 = BitAnd(move _13, move _14);
-//     assert(!move _15, "attempt to divide with overflow") -> bb5;
-//     ...
-//     _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13;
-//     ...
-//     _17 = Eq(const 5i128, const -1i128);
-//     _18 = Eq(_4, const -170141183460469231731687303715884105728i128);
-//     _19 = BitAnd(move _17, move _18);
-//     assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7;
-//     ...
-//     _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15;
-//     ...
-//     _2 = move (_20.0: i128);
-//     ...
-//     _23 = const 7i32 as u128 (Misc);
-//     _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16;
-//     ...
-//     _0 = move (_21.0: i128);
-//     ...
-//     assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
-//     ...
-//     assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
-//     ...
-//     assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
-//     ...
-//     _16 = Eq(const 5i128, const 0i128);
-//     assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6;
-//     ...
-//     assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8;
-//     ...
-//     _22 = const 6i32 as u128 (Misc);
-//     _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14;
-//     ...
-//     assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9;
+// _7 = const compiler_builtins::int::addsub::rust_i128_add(move _8, const 1i128) -> bb7;
+// ...
+// _10 = Eq(const 4i128, const -1i128);
+// _11 = Eq(_5, const -170141183460469231731687303715884105728i128);
+// _12 = BitAnd(move _10, move _11);
+// assert(!move _12, "attempt to divide with overflow") -> bb2;
+// ...
+// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb8;
+// ...
+// _14 = Eq(const 5i128, const -1i128);
+// _15 = Eq(_4, const -170141183460469231731687303715884105728i128);
+// _16 = BitAnd(move _14, move _15);
+// assert(!move _16, "attempt to calculate the remainder with overflow") -> bb4;
+// ...
+// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb11;
+// ...
+// _9 = Eq(const 4i128, const 0i128);
+// assert(!move _9, "attempt to divide by zero") -> bb1;
+// ...
+// _5 = const compiler_builtins::int::mul::rust_i128_mul(move _6, const 3i128) -> bb5;
+// ...
+// _6 = const compiler_builtins::int::addsub::rust_i128_sub(move _7, const 2i128) -> bb6;
+// ...
+// _13 = Eq(const 5i128, const 0i128);
+// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb3;
+// ...
+// _17 = const 7i32 as u32 (Misc);
+// _0 = const compiler_builtins::int::shift::rust_i128_shr(move _2, move _17) -> bb9;
+// ...
+// _18 = const 6i32 as u32 (Misc);
+// _2 = const compiler_builtins::int::shift::rust_i128_shl(move _3, move _18) -> bb10;
 // END rustc.const_signed.Lower128Bit.after.mir
 
 // START rustc.const_unsigned.Lower128Bit.after.mir
-//     _8 = _1;
-//     _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8;
-//     ...
-//     _7 = move (_9.0: u128);
-//     ...
-//     _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9;
-//     ...
-//     _6 = move (_10.0: u128);
-//     ...
-//     _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10;
-//     ...
-//     _5 = move (_11.0: u128);
-//     ...
-//     _12 = Eq(const 4u128, const 0u128);
-//     assert(!move _12, "attempt to divide by zero") -> bb4;
-//     ...
-//     _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11;
-//     ...
-//     _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13;
-//     ...
-//     _2 = move (_14.0: u128);
-//     ...
-//     _17 = const 7i32 as u128 (Misc);
-//     _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14;
-//     ...
-//     _0 = move (_15.0: u128);
-//     ...
-//     assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
-//     ...
-//     assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
-//     ...
-//     assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
-//     ...
-//     _13 = Eq(const 5u128, const 0u128);
-//     assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5;
-//     ...
-//     assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6;
-//     ...
-//     _16 = const 6i32 as u128 (Misc);
-//     _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12;
-//     ...
-//     assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7;
+// _8 = _1;
+// _7 = const compiler_builtins::int::addsub::rust_u128_add(move _8, const 1u128) -> bb5;
+// ...
+// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb6;
+// ...
+// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb9;
+// ...
+// _9 = Eq(const 4u128, const 0u128);
+// assert(!move _9, "attempt to divide by zero") -> bb1;
+// ...
+// _5 = const compiler_builtins::int::mul::rust_u128_mul(move _6, const 3u128) -> bb3;
+// ...
+// _6 = const compiler_builtins::int::addsub::rust_u128_sub(move _7, const 2u128) -> bb4;
+// ...
+// _10 = Eq(const 5u128, const 0u128);
+// assert(!move _10, "attempt to calculate the remainder with a divisor of zero") -> bb2;
+// ...
+// return;
+// ...
+// _11 = const 7i32 as u32 (Misc);
+// _0 = const compiler_builtins::int::shift::rust_u128_shr(move _2, move _11) -> bb7;
+// ...
+// _12 = const 6i32 as u32 (Misc);
+// _2 = const compiler_builtins::int::shift::rust_u128_shl(move _3, move _12) -> bb8;
+
 // END rustc.const_unsigned.Lower128Bit.after.mir
 
 // START rustc.test_signed.Lower128Bit.after.mir
index a77175975f9412ed3d7057f8da719e89e970d7a9..30efe3b9ab2c48cd0fceaf3007e3a83b072f5b31 100644 (file)
@@ -10,7 +10,7 @@
 
 // error-pattern:index out of bounds: the len is 5 but the index is 5
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn test(x: usize) -> i32 {
     [42;5][x]
 }
index 235f8cd7c725744d6f95f89b751ee7847e9e60e5..d8169ece89b38b2d47a9fa2edb18f2629d3ff07f 100644 (file)
@@ -1,4 +1,4 @@
-{ "type": "suite", "event": "started", "test_count": "4" }
+{ "type": "suite", "event": "started", "test_count": 4 }
 { "type": "test", "event": "started", "name": "a" }
 { "type": "test", "name": "a", "event": "ok" }
 { "type": "test", "event": "started", "name": "b" }
@@ -7,4 +7,4 @@
 { "type": "test", "name": "c", "event": "ok" }
 { "type": "test", "event": "started", "name": "d" }
 { "type": "test", "name": "d", "event": "ignored" }
-{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": "0" }
+{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0 }
index be06e8dd5700b19e383e01ec50c36204e4b449b7..6985a6527c874eb51562d2a2da695af198692421 100644 (file)
@@ -11,6 +11,6 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
 #![crate_type="rlib"]
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub const fn foo() -> usize { 22 }
index 832ee1d7c1b456be5e7a6744518041a400b4bc67..5351a40916b7d44df25f6e7c8bec63a0460fd13a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![crate_type = "lib"]
 
 const fn foo(i: i32) -> i32 {
index 77c70fe7f63545567d61ac6e49b0eee0054447bf..3fe27ca200cb00d4b300f932d7b959ced146b0f4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn add(x: usize, y: usize) -> usize {
     x + y
index 7d8d941439cf8c953848bdcd29267c6083cc0c71..bed78f1e8978f6dc3c9304c1853432609cce0bd8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct Foo { value: u32 }
 
index 86f5dedc4d1b1fdc5717999ab855fc1bc5d88d9c..d5959a89e51a5bf597dc7a7d248783e409be3859 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test a call whose argument is the result of another call.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn sub(x: u32, y: u32) -> u32 {
     x - y
diff --git a/src/test/run-pass/const-int-conversion.rs b/src/test/run-pass/const-int-conversion.rs
new file mode 100644 (file)
index 0000000..790c622
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_int_conversion, const_int_ops, reverse_bits, int_to_from_bytes)]
+
+const REVERSE: u32 = 0x12345678_u32.reverse_bits();
+const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
+const FROM_LE_BYTES: i32 = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
+const FROM_NE_BYTES: i32 = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]));
+const TO_BE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_be_bytes();
+const TO_LE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_le_bytes();
+const TO_NE_BYTES: [u8; 4] = i32::min_value().to_be().to_ne_bytes();
+
+fn ident<T>(ident: T) -> T {
+    ident
+}
+
+fn main() {
+    assert_eq!(REVERSE, ident(0x1e6a2c48));
+    assert_eq!(FROM_BE_BYTES, ident(0x12_34_56_78));
+    assert_eq!(FROM_LE_BYTES, ident(0x78_56_34_12));
+    assert_eq!(FROM_NE_BYTES, ident(i32::min_value()));
+    assert_eq!(TO_BE_BYTES, ident([0x12, 0x34, 0x56, 0x78]));
+    assert_eq!(TO_LE_BYTES, ident([0x78, 0x56, 0x34, 0x12]));
+    assert_eq!(TO_NE_BYTES, ident([0x80, 0, 0, 0]));
+}
+
diff --git a/src/test/run-pass/const-int-overflowing.rs b/src/test/run-pass/const-int-overflowing.rs
new file mode 100644 (file)
index 0000000..0f8f230
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_int_overflowing)]
+
+const ADD_A: (u32, bool) = 5u32.overflowing_add(2);
+const ADD_B: (u32, bool) = u32::max_value().overflowing_add(1);
+
+const SUB_A: (u32, bool) = 5u32.overflowing_sub(2);
+const SUB_B: (u32, bool) = 0u32.overflowing_sub(1);
+
+const MUL_A: (u32, bool) = 5u32.overflowing_mul(2);
+const MUL_B: (u32, bool) = 1_000_000_000u32.overflowing_mul(10);
+
+const SHL_A: (u32, bool) = 0x1u32.overflowing_shl(4);
+const SHL_B: (u32, bool) = 0x1u32.overflowing_shl(132);
+
+const SHR_A: (u32, bool) = 0x10u32.overflowing_shr(4);
+const SHR_B: (u32, bool) = 0x10u32.overflowing_shr(132);
+
+fn ident<T>(ident: T) -> T {
+    ident
+}
+
+fn main() {
+    assert_eq!(ADD_A, ident((7, false)));
+    assert_eq!(ADD_B, ident((0, true)));
+
+    assert_eq!(SUB_A, ident((3, false)));
+    assert_eq!(SUB_B, ident((u32::max_value(), true)));
+
+    assert_eq!(MUL_A, ident((10, false)));
+    assert_eq!(MUL_B, ident((1410065408, true)));
+
+    assert_eq!(SHL_A, ident((0x10, false)));
+    assert_eq!(SHL_B, ident((0x10, true)));
+
+    assert_eq!(SHR_A, ident((0x1, false)));
+    assert_eq!(SHR_B, ident((0x1, true)));
+}
diff --git a/src/test/run-pass/const-int-rotate.rs b/src/test/run-pass/const-int-rotate.rs
new file mode 100644 (file)
index 0000000..ee8e0b0
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_int_rotate)]
+
+const LEFT: u32 = 0x10000b3u32.rotate_left(8);
+const RIGHT: u32 = 0xb301u32.rotate_right(8);
+
+fn ident<T>(ident: T) -> T {
+    ident
+}
+
+fn main() {
+    assert_eq!(LEFT, ident(0xb301));
+    assert_eq!(RIGHT, ident(0x10000b3));
+}
diff --git a/src/test/run-pass/const-int-sign.rs b/src/test/run-pass/const-int-sign.rs
new file mode 100644 (file)
index 0000000..e095cfb
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_int_sign)]
+
+const NEGATIVE_A: bool = (-10i32).is_negative();
+const NEGATIVE_B: bool = 10i32.is_negative();
+const POSITIVE_A: bool= (-10i32).is_positive();
+const POSITIVE_B: bool= 10i32.is_positive();
+
+fn main() {
+    assert!(NEGATIVE_A);
+    assert!(!NEGATIVE_B);
+    assert!(!POSITIVE_A);
+    assert!(POSITIVE_B);
+}
diff --git a/src/test/run-pass/const-int-wrapping.rs b/src/test/run-pass/const-int-wrapping.rs
new file mode 100644 (file)
index 0000000..ab7c98f
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_int_wrapping)]
+
+const ADD_A: u32 = 200u32.wrapping_add(55);
+const ADD_B: u32 = 200u32.wrapping_add(u32::max_value());
+
+const SUB_A: u32 = 100u32.wrapping_sub(100);
+const SUB_B: u32 = 100u32.wrapping_sub(u32::max_value());
+
+const MUL_A: u8 = 10u8.wrapping_mul(12);
+const MUL_B: u8 = 25u8.wrapping_mul(12);
+
+const SHL_A: u32 = 1u32.wrapping_shl(7);
+const SHL_B: u32 = 1u32.wrapping_shl(128);
+
+const SHR_A: u32 = 128u32.wrapping_shr(7);
+const SHR_B: u32 = 128u32.wrapping_shr(128);
+
+fn ident<T>(ident: T) -> T {
+    ident
+}
+
+fn main() {
+    assert_eq!(ADD_A, ident(255));
+    assert_eq!(ADD_B, ident(199));
+
+    assert_eq!(SUB_A, ident(0));
+    assert_eq!(SUB_B, ident(101));
+
+    assert_eq!(MUL_A, ident(120));
+    assert_eq!(MUL_B, ident(44));
+
+    assert_eq!(SHL_A, ident(128));
+    assert_eq!(SHL_B, ident(1));
+
+    assert_eq!(SHR_A, ident(1));
+    assert_eq!(SHR_B, ident(128));
+}
index 3b27987f190cdf5c2a808e0ef02de11f981ee6a4..836716051d2132e1bd9b7f197fde1bb96cb21c80 100644 (file)
@@ -7,7 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct A;
 
index 104ab6e19db672db5e51b2bf8001b9a4b821cdf8..689ae19e7d4f4cfa4f09f039ca0bff8052ca5def 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 enum Cake {
index 06fbe9bf4f63958372c055f193e81dd09fe87a97..245dd673b512cff1f465cef0b92f514ecf92de51 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 use std::mem;
 
index 2511cfd042206d1257725f0770985dcc7d0c6d12..b267245b789694770615ba1aa8166c33c047f7ee 100644 (file)
@@ -10,7 +10,7 @@
 
 // A quick test of 'unsafe const fn' functionality
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const unsafe fn dummy(v: u32) -> u32 {
     !v
index eec4c940585c0f75a0e4d2e7c33bd4efb5f05440..574fb29e82c7df08be4371a0019a0ea2e1e64dd1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const FOO: isize = 10;
 const BAR: isize = 3;
index c435e5fdaab4a108cb3e2c4171abc7303756bb70..f59a6810e3a78f76bea3112c1dc0ba2e883df9ec 100644 (file)
@@ -10,7 +10,7 @@
 
 // https://github.com/rust-lang/rust/issues/48279
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 pub struct NonZeroU32 {
index 0bb253d1a6455d94f97e59cf7a738533bf45e81f..352958f4c6a454f82f0d5219432658e6e377f4da 100644 (file)
@@ -10,7 +10,7 @@
 
 // https://github.com/rust-lang/rust/issues/46114
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(Eq, PartialEq)]
 struct A { value: u32 }
index d57d3bcb49aa8d5c7f6de2be81b5865e1fcfc2f9..87fdac4bfb4fe296daa58fd4bc08aa29ededfb79 100644 (file)
@@ -10,7 +10,7 @@
 
 // https://github.com/rust-lang/rust/issues/43754
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn foo(x: usize) -> usize {
     return x;
 }
index 53cb4c4b009e5c870c43f9e13ee76fc30f3dc58c..a18d82fb7a4e7e22c334fe85204ff5b500795ae7 100644 (file)
@@ -11,6 +11,8 @@
 // ignore-wasm32
 // ignore-emscripten
 
+// compile-flags: -C debug_assertions=yes
+
 #![feature(const_fn, libc)]
 #![allow(const_err)]
 
@@ -19,7 +21,7 @@
 use std::env;
 use std::process::{Command, Stdio};
 
-// this will panic in debug mode
+// this will panic in debug mode and overflow in release mode
 const fn bar() -> usize { 0 - 1 }
 
 fn foo() {
index 5a010f2be7a3425168405669205e59714172887b..10482139a978c49297794d919ada6ddc2eb95666 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 fn main() {}
 
index 6d9adbcd57980354095a0acebcfb5ebd84eae510..3079d9de3c23861af323b2e8e3cb40a1635f4441 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 struct A {
     field: usize,
 }
index 24f4c9f590b11341a74997d5e574989e5385aefe..7be79f3a450974bb6c76b6b93e29c8ff1f5813cc 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn foo() -> *const i8 {
     b"foo" as *const _ as *const i8
index 9bdde02d0061ce23b1643b4b34fedc0ef1e0cb83..9b3289e67859a8da0cb2d9c292ba3393b2341227 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn foo() -> i64 {
     3
diff --git a/src/test/run-pass/issue-48006.rs b/src/test/run-pass/issue-48006.rs
new file mode 100644 (file)
index 0000000..d5887bb
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(step_trait)]
+
+use std::iter::Step;
+
+#[cfg(target_pointer_width = "16")]
+fn main() {
+    assert!(Step::steps_between(&0u32, &::std::u32::MAX).is_none());
+}
+
+#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
+fn main() {
+    assert!(Step::steps_between(&0u32, &::std::u32::MAX).is_some());
+}
index 68271accb61a2a5514dfd8728bebb2c6eb2ce89d..488bc6e6927a077561ae9153365407aa07f4c8c1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn f() -> usize {
     5
 }
diff --git a/src/test/run-pass/redundant.rs b/src/test/run-pass/redundant.rs
new file mode 100644 (file)
index 0000000..39bd316
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// edition:2018
+
+#![feature(uniform_paths)]
+
+use std;
+
+mod foo {
+    pub use std as my_std;
+}
+
+mod bar {
+    pub use std::{self};
+}
+
+fn main() {
+    self::std::io::stdout();
+    foo::my_std::io::stdout();
+    bar::std::io::stdout();
+}
index 9d41eca8fe5d2c742d13985aad8240a4e8167068..83fb24cda088cd1bdb7b600a6bcdfde6c9d67391 100644 (file)
@@ -30,4 +30,33 @@ fn main() {
     match enum_unit {
         _ => "no error with only wildcard"
     };
+
+
+    // issue #53549 - check that variant constructors can still be called normally.
+
+    match NonExhaustiveEnum::Unit {
+        NonExhaustiveEnum::Unit => {},
+        _ => {}
+    };
+
+    match NonExhaustiveEnum::Tuple(2) {
+        NonExhaustiveEnum::Tuple(2) => {},
+        _ => {}
+    };
+
+    match (NonExhaustiveEnum::Unit {}) {
+        NonExhaustiveEnum::Unit {} => {},
+        _ => {}
+    };
+
+    match (NonExhaustiveEnum::Tuple { 0: 2 }) {
+        NonExhaustiveEnum::Tuple { 0: 2 } => {},
+        _ => {}
+    };
+
+    match (NonExhaustiveEnum::Struct { field: 2 }) {
+        NonExhaustiveEnum::Struct { field: 2 } => {},
+        _ => {}
+    };
+
 }
index 139da046452646b77c1193c8f18691b3ae084a6d..a7fd9f299c033bdb8c086e310290ed21678e6cfa 100644 (file)
@@ -52,7 +52,7 @@ fn is_sigill(status: ExitStatus) -> bool {
 }
 
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod test {
     // An SSE type
     #[repr(simd)]
diff --git a/src/test/run-pass/try-from-int-error-partial-eq.rs b/src/test/run-pass/try-from-int-error-partial-eq.rs
new file mode 100644 (file)
index 0000000..1122f5a
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(try_from)]
+#![allow(unused_must_use)]
+
+use std::convert::TryFrom;
+use std::num::TryFromIntError;
+
+fn main() {
+    let x: u32 = 125;
+    let y: Result<u8, TryFromIntError> = u8::try_from(x);
+    y == Ok(125);
+}
index 25de698cad10e2308f0b1a5c9f2678d48b35159f..0c1eedc86ccfd83cdcd60d6155fc670566cfa77a 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -Cmetadata=aux
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub const fn foo() {}
 pub const unsafe fn bar() {}
index c323681f60b0a1ac66997faa937c27d22f15721a..dc7a2799b46a911a0c3e92583613ff021e9c0371 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
index 380feb941d6feab4eaaa03f45ff326ba4db8606b..49694e3ae08d1830599ce2d7946d8a8da2e15081 100644 (file)
@@ -10,7 +10,7 @@
 
 #![crate_type="lib"]
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub struct Foo;
 
diff --git a/src/test/rustdoc/extern-html-root-url.rs b/src/test/rustdoc/extern-html-root-url.rs
new file mode 100644 (file)
index 0000000..c8a13be
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// compile-flags:-Z unstable-options --extern-html-root-url core=https://example.com/core/0.1.0
+
+// @has extern_html_root_url/index.html
+// @has - '//a/@href' 'https://example.com/core/0.1.0/core/iter/index.html'
+#[doc(no_inline)]
+pub use std::iter;
index c822d0f8b21b8c480cc7534d98ddd99b5cec309d..81b81a9a141da48292f513365c6445cff77ce4e5 100644 (file)
@@ -75,7 +75,7 @@ pub fn this_function() {}
 
 pub trait SoAmbiguous {}
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 pub fn SoAmbiguous() {}
 
 
index 8ccb5878c40456d449fb746836dc5697124f083f..082f15a39dd955254c7b94b62ef41ef0eeb9f295 100644 (file)
@@ -49,5 +49,5 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_late_lint_pass(box Pass);
-    reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]);
+    reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]);
 }
index d7895bd8781ba02b83fcb3eb45031184e3361373..e184c0919d0ecf333fc94177986d761eeb128bb2 100644 (file)
 use rustc_plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
+declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
 
 struct Pass;
 
 impl LintPass for Pass {
     fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
+        lint_array!(TEST_LINT, TEST_GROUP)
     }
 }
 
@@ -39,10 +40,14 @@ fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
         if it.ident.name == "lintme" {
             cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
         }
+        if it.ident.name == "lintmetoo" {
+            cx.span_lint(TEST_GROUP, it.span, "item is named 'lintmetoo'");
+        }
     }
 }
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_early_lint_pass(box Pass);
+    reg.register_lint_group("clippy::group", Some("clippy_group"), vec![TEST_LINT, TEST_GROUP]);
 }
diff --git a/src/test/ui-fulldeps/lint_tool_cmdline_allow.rs b/src/test/ui-fulldeps/lint_tool_cmdline_allow.rs
new file mode 100644 (file)
index 0000000..74888d3
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// aux-build:lint_tool_test.rs
+// ignore-stage1
+// compile-flags: -A test-lint
+
+#![feature(plugin)]
+#![warn(unused)]
+#![plugin(lint_tool_test)]
+
+fn lintme() { }
+
+pub fn main() {
+}
diff --git a/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr b/src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr
new file mode 100644 (file)
index 0000000..c1a9d81
--- /dev/null
@@ -0,0 +1,25 @@
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
+warning: item is named 'lintme'
+  --> $DIR/lint_tool_cmdline_allow.rs:20:1
+   |
+LL | fn lintme() { }
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(clippy::test_lint)] on by default
+
+warning: function is never used: `lintme`
+  --> $DIR/lint_tool_cmdline_allow.rs:20:1
+   |
+LL | fn lintme() { }
+   | ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint_tool_cmdline_allow.rs:17:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
+
index ccdcd2df31b4f49afd20bd2202f1088986c2afa3..ebe10b3714f20fecf91988379b59d6d24e8f6710 100644 (file)
@@ -8,17 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// run-pass
 // aux-build:lint_tool_test.rs
 // ignore-stage1
+// compile-flags: --cfg foo
 #![feature(plugin)]
 #![feature(tool_lints)]
 #![plugin(lint_tool_test)]
 #![allow(dead_code)]
+#![cfg_attr(foo, warn(test_lint))]
+//~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~^^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+#![deny(clippy_group)]
+//~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
-fn lintme() { } //~ WARNING item is named 'lintme'
+fn lintme() { } //~ ERROR item is named 'lintme'
+
+#[allow(clippy::group)]
+fn lintmetoo() {}
 
 #[allow(clippy::test_lint)]
 pub fn main() {
     fn lintme() { }
+    fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
+}
+
+#[allow(test_group)]
+//~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
+#[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
+fn hello() {
+    fn lintmetoo() { }
 }
index 22d0f458e7d7b487690175a9f3547adc8d99bec5..ab0c317e1cd0f4ef78ab86e203c5a00bd6f3f791 100644 (file)
@@ -1,8 +1,62 @@
-warning: item is named 'lintme'
-  --> $DIR/lint_tool_test.rs:19:1
+warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:18:23
    |
-LL | fn lintme() { } //~ WARNING item is named 'lintme'
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+   |
+   = note: #[warn(renamed_and_removed_lints)] on by default
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:21:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:35:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
+warning: unknown lint: `this_lint_does_not_exist`
+  --> $DIR/lint_tool_test.rs:37:8
+   |
+LL | #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(unknown_lints)] on by default
+
+warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint_tool_test.rs:18:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+error: item is named 'lintme'
+  --> $DIR/lint_tool_test.rs:24:1
+   |
+LL | fn lintme() { } //~ ERROR item is named 'lintme'
    | ^^^^^^^^^^^^^^^
    |
-   = note: #[warn(clippy::test_lint)] on by default
+note: lint level defined here
+  --> $DIR/lint_tool_test.rs:21:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^
+   = note: #[deny(clippy::test_lint)] implied by #[deny(clippy::group)]
+
+error: item is named 'lintmetoo'
+  --> $DIR/lint_tool_test.rs:32:5
+   |
+LL |     fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint_tool_test.rs:21:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^
+   = note: #[deny(clippy::test_group)] implied by #[deny(clippy::group)]
+
+error: aborting due to 2 previous errors
 
index 9b792c46c24b9cf5ee5207e91bf0621c16fb07db..e7885537b06bb38a8dce71ab0d58d328a50dbec4 100644 (file)
@@ -1,10 +1,8 @@
 error: function should have one argument
   --> $DIR/alloc-error-handler-bad-signature-3.rs:20:1
    |
-LL | / fn oom() -> ! { //~ ERROR function should have one argument
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn oom() -> ! { //~ ERROR function should have one argument
+   | ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 5b8223ff292588cc2a61c6e9a04a8e46de5681e3..674d85d95911260ccb9e87fe9a821424733c1bb5 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:12
-   |
-LL |     let z: I::A = if cond { x } else { y };
-   |            ^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:29
    |
index ac758a8926f28e3612ee820dcbc369f587b581b1..b61ea27ebe19b9ab4eb664552397f01723720669 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-contravariant.rs:53:16
-   |
-LL |    let a = bar(foo, y);
-   |                ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-contravariant.rs:54:16
-   |
-LL |    let b = bar(foo, x);
-   |                ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/project-fn-ret-contravariant.rs:53:12
    |
index 75c35d077c4c430a045f3f26c7a813bb83c5cd3d..b5cba945fb11ac6f6afbfbf16a7c2842b338c017 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-contravariant.rs:48:8
-   |
-LL |    bar(foo, x) //[transmute]~ ERROR E0495
-   |        ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/project-fn-ret-contravariant.rs:48:4
    |
index 4b2ba24eb0eb8f289f13cec74567b002bd628af5..971448997e3f62673095043f51488fea2e6e79e5 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-invariant.rs:63:16
-   |
-LL |    let a = bar(foo, y); //[krisskross]~ ERROR E0623
-   |                ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-invariant.rs:64:16
-   |
-LL |    let b = bar(foo, x);
-   |                ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/project-fn-ret-invariant.rs:63:12
    |
index a669c7ac73bc53ec26d67a10b7be1d19b344287c..a9c2bb3763988eed95e9c050aebf68d08962ecbf 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-invariant.rs:47:12
-   |
-LL |    let f = foo; // <-- No consistent type can be inferred for `f` here.
-   |            ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/project-fn-ret-invariant.rs:48:12
    |
index 604974a25008d1c04075d2d5dab30c63eda274af..bb1be40980dad093b86df0ab0cc5dbafb1b4b7d5 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/project-fn-ret-invariant.rs:58:8
-   |
-LL |    bar(foo, x) //[transmute]~ ERROR E0495
-   |        ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/project-fn-ret-invariant.rs:58:4
    |
index b7aad5c2b80dc450127c294ec5bedf6ac35a2939..e3211f83850995bcec44f76564fe98ba503f69e4 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/borrowck-reborrow-from-shorter-lived-andmut.rs:19:18
-   |
-LL |     S { pointer: &mut *p.pointer }
-   |                  ^^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/borrowck-reborrow-from-shorter-lived-andmut.rs:19:5
    |
index 9d62c7dba75ff068efcec146fdd0109b5ed1a1a6..18411b528a3e30d2455b51cbd20587f4ed5d75de 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-45983.rs:36:27
-   |
-LL |     give_any(|y| x = Some(y));
-   |                           ^
-
 error: borrowed data escapes outside of closure
   --> $DIR/issue-45983.rs:36:18
    |
index 5ed425e958a584aa720929f113881be2e91e615b..ec2a2887127ad005e981ada4a83f70e9a24e6cc2 100644 (file)
@@ -36,7 +36,6 @@ fn main() {
     give_any(|y| x = Some(y));
     //[ast]~^ ERROR borrowed data cannot be stored outside of its closure
     //[migrate]~^^ ERROR borrowed data cannot be stored outside of its closure
-    //[nll]~^^^ WARN not reporting region error due to nll
-    //[nll]~| ERROR borrowed data escapes outside of closure
+    //[nll]~^^^ ERROR borrowed data escapes outside of closure
     //[nll]~| ERROR cannot assign to `x`, as it is not declared as mutable
 }
index b0fbcd3ad9f39e53d7c0a36c1b6b60b14f9ebcfc..372df61d78c45bdd511d0a0a0cc1dce8859add49 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-7573.rs:27:31
-   |
-LL |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
-   |                               ^
-
 error: borrowed data escapes outside of closure
   --> $DIR/issue-7573.rs:32:9
    |
index 508e09318ae112a30589496fb54ef626e68afe2d..d71c8462587d06e8e1411930b0791d66255ea65d 100644 (file)
@@ -15,7 +15,7 @@
 // permitted as `Foo` is not copy (even in a static/const
 // initializer).
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct Foo(usize);
 
index 1a18817e943655705c715e1c80a7ca952e5da007..787fc4d872996d66f61ceb57f4b7e52ab259b3b1 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-escape-bound-fn-2.rs:18:27
-   |
-LL |     with_int(|y| x = Some(y));
-   |                           ^
-
 error: borrowed data escapes outside of closure
   --> $DIR/regions-escape-bound-fn-2.rs:18:18
    |
index 62ea9a0854bde9a1de42dd7b6b6289ae7d3e36ab..91f1f00ce30ffc207b954c30711a0a3b06000fae 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-escape-bound-fn.rs:18:22
-   |
-LL |     with_int(|y| x = Some(y));
-   |                      ^^^^^^^
-
 error: borrowed data escapes outside of closure
   --> $DIR/regions-escape-bound-fn.rs:18:18
    |
index 44eead9fb5a987e98f45469acdc8bafd4c5c522c..44e7018fdd76487c84a0411c581d091d507f0097 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-escape-unboxed-closure.rs:16:27
-   |
-LL |     with_int(&mut |y| x = Some(y));
-   |                           ^^^^^^^
-
 error: borrowed data escapes outside of closure
   --> $DIR/regions-escape-unboxed-closure.rs:16:23
    |
index a4b24fa8b4bf6e04decef823fee7a34b08966a62..55eca7f45a5aec0a7814892316c3a1ada6d08ca3 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(stmt_expr_attributes)]
+#![feature(custom_test_frameworks)]
 
 fn main() {
     let _ = #[cfg(unset)] ();
@@ -17,6 +18,4 @@ fn main() {
     //~^ ERROR removing an expression is not supported in this position
     let _ = [1, 2, 3][#[cfg(unset)] 1];
     //~^ ERROR removing an expression is not supported in this position
-    let _ = #[test] ();
-    //~^ ERROR removing an expression is not supported in this position
 }
index 0511c5755462e53cbfb459122fc388d8be38578a..1892cee113ecb93edcb646ccd7a08f68941eb1f5 100644 (file)
@@ -1,26 +1,20 @@
 error: removing an expression is not supported in this position
-  --> $DIR/cfg-non-opt-expr.rs:14:13
+  --> $DIR/cfg-non-opt-expr.rs:15:13
    |
 LL |     let _ = #[cfg(unset)] ();
    |             ^^^^^^^^^^^^^
 
 error: removing an expression is not supported in this position
-  --> $DIR/cfg-non-opt-expr.rs:16:21
+  --> $DIR/cfg-non-opt-expr.rs:17:21
    |
 LL |     let _ = 1 + 2 + #[cfg(unset)] 3;
    |                     ^^^^^^^^^^^^^
 
 error: removing an expression is not supported in this position
-  --> $DIR/cfg-non-opt-expr.rs:18:23
+  --> $DIR/cfg-non-opt-expr.rs:19:23
    |
 LL |     let _ = [1, 2, 3][#[cfg(unset)] 1];
    |                       ^^^^^^^^^^^^^
 
-error: removing an expression is not supported in this position
-  --> $DIR/cfg-non-opt-expr.rs:20:13
-   |
-LL |     let _ = #[test] ();
-   |             ^^^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
index 57e95e39cd9960ee4547344836f0160b0848b706..5305591b8434547402ee4ca0e918403cf9b08e01 100644 (file)
 use std::borrow::Borrow;
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
+trait Foo<'a, 'b, S, T, U>
+where
+    S: Debug,
+    T: Borrow<U>,
+    U: ?Sized,
+    'a: 'b,
+    U: 'b,
+    Vec<T>:, // NOTE(#53696) this checks an empty list of bounds.
+{
     fn s(_: S) -> S;
     fn t(_: T) -> T;
     fn u(_: U) -> U;
index 5ea397d424b63986b885c9c10fb5f5bf7a768611..ad3546da1a25b4e93432af8be214dcce119757c7 100644 (file)
@@ -11,7 +11,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
    = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
    = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b).
+   = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b), WellFormed(std::vec::Vec<T>).
+   = note: WellFormed(std::vec::Vec<T>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
 
 error: aborting due to previous error
 
index fe857001bfaefc35eecfe7c6bf7a99fb002d3482..ae3e3a262b5adc2d803a353ed9d94c42043e1d59 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/expect-fn-supply-fn.rs:24:52
-   |
-LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
-   |                                                    ^^^^^^^^^^^
-
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:40:5
    |
index ca82020a2ccb1c12fb5d7463b54c351b33c06df2..4bc5034f93e4d548777573f9f302329f4ca7b5f0 100644 (file)
@@ -1,13 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:15:9
-   |
-LL |       bar(|| {
-   |  _________^
-LL | |         //~^ ERROR explicit lifetime required in the type of `x` [E0621]
-LL | |         let _ = x;
-LL | |     })
-   | |_____^
-
 error[E0621]: explicit lifetime required in the type of `x`
   --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:15:5
    |
index 8658c618bf24ca6a6b6a31aed66d3e6cc788c7dc..7f842c40ece5af87f01ab3024d0865cd83fee9c3 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/expect-region-supply-region.rs:28:13
-   |
-LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
-   |             ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/expect-region-supply-region.rs:38:13
-   |
-LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
-   |             ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/expect-region-supply-region.rs:47:33
-   |
-LL |     closure_expecting_bound(|x: &'x u32| {
-   |                                 ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/expect-region-supply-region.rs:52:13
-   |
-LL |         f = Some(x);
-   |             ^^^^^^^
-
 error: borrowed data escapes outside of closure
   --> $DIR/expect-region-supply-region.rs:28:9
    |
index b0d5a6b12727b16225778adc037b0943931a7cc2..499227e71a74cc42bf5314b1de9a1ddd2a85b241 100644 (file)
@@ -11,6 +11,6 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
 #![crate_type="rlib"]
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable
diff --git a/src/test/ui/consts/const-eval/auxiliary/stability.rs b/src/test/ui/consts/const-eval/auxiliary/stability.rs
new file mode 100644 (file)
index 0000000..18c6b52
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// Crate that exports a const fn. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#![feature(rustc_const_unstable, const_fn)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+pub const fn foo() -> u32 { 42 }
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
new file mode 100644 (file)
index 0000000..dc84e2a
--- /dev/null
@@ -0,0 +1,110 @@
+// only-x86_64
+
+union Nonsense {
+    u: usize,
+    int_32_ref: &'static i32,
+    uint_8: u8,
+    uint_16: u16,
+    uint_32: u32,
+    uint_64: u64,
+    uint_128: u128,
+    int_8: i8,
+    int_16: i16,
+    int_32: i32,
+    int_64: i64,
+    int_128: i128,
+    float_32: f32,
+    float_64: f64,
+    truthy_falsey: bool,
+    character: char,
+    stringy: &'static str,
+}
+
+fn main() {
+    const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
+    //~^ ERROR this constant cannot be used
+
+    const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
+    //~^ ERROR this constant cannot be used
+
+    const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
+    //~^ ERROR this constant cannot be used
+
+    const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
+    //~^ ERROR this constant likely exhibits undefined behavior
+
+    const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
+    //~^ ERROR this constant cannot be used
+
+    const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
+    //~^ ERROR this constant cannot be used
+}
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
new file mode 100644 (file)
index 0000000..751f411
--- /dev/null
@@ -0,0 +1,233 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:24:5
+   |
+LL |     const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type usize
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:27:5
+   |
+LL |     const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |
+   = note: #[deny(const_err)] on by default
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:30:5
+   |
+LL |     const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:33:5
+   |
+LL |     const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:36:5
+   |
+LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type u64
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:39:5
+   |
+LL |     const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:42:5
+   |
+LL |     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^^^
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:45:5
+   |
+LL |     const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:48:5
+   |
+LL |     const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:51:5
+   |
+LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type i64
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:54:5
+   |
+LL |     const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:57:5
+   |
+LL |     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:60:5
+   |
+LL |     const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type f64
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:63:5
+   |
+LL |     const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------------^^^
+   |                                               |
+   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:66:5
+   |
+LL |     const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+   |                                               |
+   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:69:5
+   |
+LL |     const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------^^^
+   |                                       |
+   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:72:5
+   |
+LL |     const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^^^
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:75:5
+   |
+LL |     const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^^^
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:78:5
+   |
+LL |     const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type u64
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:81:5
+   |
+LL |     const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:84:5
+   |
+LL |     const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------^^^
+   |                                       |
+   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:87:5
+   |
+LL |     const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------^^^
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:90:5
+   |
+LL |     const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------^^^
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:93:5
+   |
+LL |     const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type i64
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:96:5
+   |
+LL |     const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^^^
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:99:5
+   |
+LL |     const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/const-pointer-values-in-various-types.rs:102:5
+   |
+LL |     const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type f64
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:105:5
+   |
+LL |     const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^^^
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: this constant cannot be used
+  --> $DIR/const-pointer-values-in-various-types.rs:108:5
+   |
+LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: aborting due to 29 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 684fa1c997bf100a57c8242fba38039a06a3c531..ed3e38486baf628a045b33d3709c250044c4d5dd 100644 (file)
@@ -11,6 +11,7 @@ error[E0597]: borrowed value does not live long enough
    |
 LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ does not live long enough
 LL | }
    | - temporary value only lives until here
    |
index a590e569947f82caf0fa7c4b6599b63c4c32e996..623e99480a70a752c17d2c26eae70c861b13643c 100644 (file)
@@ -31,4 +31,5 @@ fn a() {
 fn main() {
     let _: &'static u32 = &meh(); //~ ERROR does not live long enough
     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+    //~^ does not live long enough
 }
index 7963cbb4e45691b56db9982621b3c33a9b3b4bf6..b9856d37b0ee1a846a47345f9bec08c6bed2dd07 100644 (file)
@@ -21,12 +21,23 @@ error[E0597]: borrowed value does not live long enough
    |
 LL |     let _: &'static u32 = &meh(); //~ ERROR does not live long enough
    |                            ^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn.rs:33:26
+   |
 LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ does not live long enough
 LL | }
    | - temporary value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr
new file mode 100644 (file)
index 0000000..4c8f2f4
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:19:29
+   |
+LL |     let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+   |                             ^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs
new file mode 100644 (file)
index 0000000..81be5d4
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:stability.rs
+
+extern crate stability;
+
+use stability::foo;
+
+fn main() {
+    let _: &'static u32 = &foo(); //~ ERROR does not live long enough
+    let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
new file mode 100644 (file)
index 0000000..cea36a0
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:18:28
+   |
+LL |     let _: &'static u32 = &foo(); //~ ERROR does not live long enough
+   |                            ^^^^^ temporary value does not live long enough
+LL |     let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:19:29
+   |
+LL |     let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+   |                             ^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
index c0b45f0ba3041a9df2dec53de039f03eea1e3838..200f423f6e39b5de9d5718650fcd299fc3577cbd 100644 (file)
@@ -10,7 +10,7 @@
 
 #![warn(const_err)]
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const fn foo(x: u32) -> u32 {
     x
index f6a2db31d371ad6c86c54296fc12104eb4c6cc38..2bc860e3ef94fb2890dc870a709674a050893032 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-pass
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 struct S(pub &'static u32, pub u32);
 
diff --git a/src/test/ui/consts/const-eval/issue-52475.rs b/src/test/ui/consts/const-eval/issue-52475.rs
new file mode 100644 (file)
index 0000000..1c1e653
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_let)]
+
+fn main() {
+    let _ = [(); {
+        //~^ WARNING Constant evaluating a complex constant, this might take some time
+        //~| ERROR could not evaluate repeat length
+        let mut x = &0;
+        let mut n = 0;
+        while n < 5 { //~ ERROR constant contains unimplemented expression type
+            n = (n + 1) % 5;
+            x = &0; // Materialize a new AllocId
+        }
+        0
+    }];
+}
diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr
new file mode 100644 (file)
index 0000000..f45587f
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/issue-52475.rs:19:9
+   |
+LL | /         while n < 5 { //~ ERROR constant contains unimplemented expression type
+LL | |             n = (n + 1) % 5;
+LL | |             x = &0; // Materialize a new AllocId
+LL | |         }
+   | |_________^
+
+warning: Constant evaluating a complex constant, this might take some time
+  --> $DIR/issue-52475.rs:14:18
+   |
+LL |       let _ = [(); {
+   |  __________________^
+LL | |         //~^ WARNING Constant evaluating a complex constant, this might take some time
+LL | |         //~| ERROR could not evaluate repeat length
+LL | |         let mut x = &0;
+...  |
+LL | |         0
+LL | |     }];
+   | |_____^
+
+error[E0080]: could not evaluate repeat length
+  --> $DIR/issue-52475.rs:14:18
+   |
+LL |       let _ = [(); {
+   |  __________________^
+LL | |         //~^ WARNING Constant evaluating a complex constant, this might take some time
+LL | |         //~| ERROR could not evaluate repeat length
+LL | |         let mut x = &0;
+...  |
+LL | |             n = (n + 1) % 5;
+   | |                 ----------- duplicate interpreter state observed here, const evaluation will never terminate
+...  |
+LL | |         0
+LL | |     }];
+   | |_____^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0019, E0080.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/ref_to_float_transmute.rs b/src/test/ui/consts/const-eval/ref_to_float_transmute.rs
deleted file mode 100644 (file)
index 1758ac7..0000000
+++ /dev/null
@@ -1,30 +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-pass
-
-#![feature(const_fn_union)]
-
-fn main() {}
-
-static FOO: u32 = 42;
-
-union Foo {
-    f: Float,
-    r: &'static u32,
-}
-
-#[cfg(target_pointer_width="64")]
-type Float = f64;
-
-#[cfg(target_pointer_width="32")]
-type Float = f32;
-
-static BAR: Float = unsafe { Foo { r: &FOO }.f };
diff --git a/src/test/ui/consts/const-eval/ub-ptr-in-usize.rs b/src/test/ui/consts/const-eval/ub-ptr-in-usize.rs
deleted file mode 100644 (file)
index b405f76..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-pass
-
-union Foo {
-    a: &'static u8,
-    b: usize,
-}
-
-// a usize's value may be a pointer, that's fine
-const PTR_AS_USIZE: usize = unsafe { Foo { a: &1 }.b};
-
-fn main() {
-}
diff --git a/src/test/ui/consts/const-int-conversion.rs b/src/test/ui/consts/const-int-conversion.rs
new file mode 100644 (file)
index 0000000..0abe6b4
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(reverse_bits, int_to_from_bytes)]
+
+fn main() {
+    let x: &'static i32 = &(5_i32.reverse_bits());
+        //~^ ERROR does not live long enough
+    let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
+        //~^ ERROR does not live long enough
+    let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
+        //~^ ERROR does not live long enough
+    let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
+        //~^ ERROR does not live long enough
+    let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
+        //~^ ERROR does not live long enough
+    let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
+        //~^ ERROR does not live long enough
+    let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
+        //~^ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr
new file mode 100644 (file)
index 0000000..fc2472a
--- /dev/null
@@ -0,0 +1,80 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:14:28
+   |
+LL |     let x: &'static i32 = &(5_i32.reverse_bits());
+   |                            ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:16:28
+   |
+LL |     let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:18:28
+   |
+LL |     let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:20:28
+   |
+LL |     let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:22:29
+   |
+LL |     let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:24:29
+   |
+LL |     let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:26:29
+   |
+LL |     let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |         //~^ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-overflowing.rs b/src/test/ui/consts/const-int-overflowing.rs
new file mode 100644 (file)
index 0000000..7bff6b9
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); //~ ERROR does not live long enough
+    let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); //~ ERROR does not live long enough
+    let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-overflowing.stderr b/src/test/ui/consts/const-int-overflowing.stderr
new file mode 100644 (file)
index 0000000..e06fb6a
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-overflowing.rs:12:36
+   |
+LL |     let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); //~ ERROR does not live long enough
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-overflowing.rs:13:36
+   |
+LL |     let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); //~ ERROR does not live long enough
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-overflowing.rs:14:36
+   |
+LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-rotate.rs b/src/test/ui/consts/const-int-rotate.rs
new file mode 100644 (file)
index 0000000..e6f0533
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x: &'static i32 = &(5_i32.rotate_left(3)); //~ ERROR does not live long enough
+    let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-rotate.stderr b/src/test/ui/consts/const-int-rotate.stderr
new file mode 100644 (file)
index 0000000..fa2f625
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-rotate.rs:12:28
+   |
+LL |     let x: &'static i32 = &(5_i32.rotate_left(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-rotate.rs:13:28
+   |
+LL |     let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-sign.rs b/src/test/ui/consts/const-int-sign.rs
new file mode 100644 (file)
index 0000000..1082c38
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x: &'static bool = &(5_i32.is_negative()); //~ ERROR does not live long enough
+    let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-sign.stderr b/src/test/ui/consts/const-int-sign.stderr
new file mode 100644 (file)
index 0000000..1d45628
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-sign.rs:12:29
+   |
+LL |     let x: &'static bool = &(5_i32.is_negative()); //~ ERROR does not live long enough
+   |                             ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-sign.rs:13:29
+   |
+LL |     let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough
+   |                             ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-wrapping.rs b/src/test/ui/consts/const-int-wrapping.rs
new file mode 100644 (file)
index 0000000..bd11d5d
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x: &'static i32 = &(5_i32.wrapping_add(3)); //~ ERROR does not live long enough
+    let y: &'static i32 = &(5_i32.wrapping_sub(3)); //~ ERROR does not live long enough
+    let z: &'static i32 = &(5_i32.wrapping_mul(3)); //~ ERROR does not live long enough
+    let a: &'static i32 = &(5_i32.wrapping_shl(3)); //~ ERROR does not live long enough
+    let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-wrapping.stderr b/src/test/ui/consts/const-int-wrapping.stderr
new file mode 100644 (file)
index 0000000..94974e0
--- /dev/null
@@ -0,0 +1,57 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:12:28
+   |
+LL |     let x: &'static i32 = &(5_i32.wrapping_add(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:13:28
+   |
+LL |     let y: &'static i32 = &(5_i32.wrapping_sub(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:14:28
+   |
+LL |     let z: &'static i32 = &(5_i32.wrapping_mul(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:15:28
+   |
+LL |     let a: &'static i32 = &(5_i32.wrapping_shl(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:16:28
+   |
+LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
index 87d5e13df6eb30475e10794ebec02436c2d992c7..4f02b1eef3a0fef1a81922bc43a6c3aca273615c 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-pass
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 enum Cake {
index fed8e1885de8a996296b37ce83cb1affc554262f..04c054f8b6db25dfa5ade5642953eb02ed8f73e2 100644 (file)
@@ -10,8 +10,6 @@
 
 // error-pattern: cycle detected
 
-#![feature(const_fn)]
-
 struct Foo {
     bytes: [u8; std::mem::size_of::<Foo>()]
 }
index 16d87f7e31c9bb126b81f7ac4a0580d9fc1ef2c6..ab8b5792e681d58bb7e6c9af3193f77664c00252 100644 (file)
@@ -4,14 +4,14 @@ note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_
 note: ...which requires const-evaluating `Foo::bytes::{{constant}}`...
   --> $SRC_DIR/libcore/mem.rs:LL:COL
    |
-LL |     unsafe { intrinsics::size_of::<T>() }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing layout of `Foo`, completing the cycle
 note: cycle used when const-evaluating `Foo::bytes::{{constant}}`
   --> $SRC_DIR/libcore/mem.rs:LL:COL
    |
-LL |     unsafe { intrinsics::size_of::<T>() }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
new file mode 100644 (file)
index 0000000..b156e5a
--- /dev/null
@@ -0,0 +1,224 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:49:25
+   |
+LL |     const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                         ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:51:5
+   |
+LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:56:28
+   |
+LL |     const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                            ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:58:5
+   |
+LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:63:27
+   |
+LL |     const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+   |                           ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:65:5
+   |
+LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:70:5
+   |
+LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:88:16
+   |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+   |                ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:90:18
+   |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+   |                  ^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:92:33
+   |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+   |                                 ^^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:94:35
+   |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+   |                                   ^^^^^^^
+
+error: only int and `bool` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:96:35
+   |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+   |                                   ^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:98:43
+   |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+   |                                           ^^^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:102:27
+   |
+LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+   |                           ^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:103:36
+   |
+LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+   |                                    ^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:104:42
+   |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:106:42
+   |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:108:38
+   |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:110:29
+   |
+LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+   |                             ^^^^^^^^^^^
+
+error: local variables in const fn are unstable
+  --> $DIR/min_const_fn.rs:111:34
+   |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+   |                                  ^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:112:44
+   |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+   |                                            ^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:114:44
+   |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+   |                                            ^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:116:14
+   |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+   |              ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:121:6
+   |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:126:6
+   |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:131:6
+   |
+LL | impl<T: Sync + Sized> Foo<T> {
+   |      ^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:137:1
+   |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:139:34
+   |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+   |                                  ^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:141:22
+   |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:142:1
+   |
+LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:143:23
+   |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                       ^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:144:1
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/min_const_fn.rs:144:64
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   |                                                                ^^ - temporary value only lives until here
+   |                                                                |
+   |                                                                temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:149:41
+   |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:152:21
+   |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+   |                     ^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:154:1
+   |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 36 previous errors
+
+Some errors occurred: E0493, E0597.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
new file mode 100644 (file)
index 0000000..b861e31
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+// ok
+const fn foo1() {}
+const fn foo2(x: i32) -> i32 { x }
+const fn foo3<T>(x: T) -> T { x }
+const fn foo7() {
+    (
+        foo1(),
+        foo2(420),
+        foo3(69),
+    ).0
+}
+const fn foo12<T: Sized>(t: T) -> T { t }
+const fn foo13<T: ?Sized>(t: &T) -> &T { t }
+const fn foo14<'a, T: 'a>(t: &'a T) -> &'a T { t }
+const fn foo15<T>(t: T) -> T where T: Sized { t }
+const fn foo15_2<T>(t: &T) -> &T where T: ?Sized { t }
+const fn foo16(f: f32) -> f32 { f }
+const fn foo17(f: f32) -> u32 { f as u32 }
+const fn foo18(i: i32) -> i32 { i * 3 }
+const fn foo20(b: bool) -> bool { !b }
+const fn foo21<T, U>(t: T, u: U) -> (T, U) { (t, u) }
+const fn foo22(s: &[u8], i: usize) -> u8 { s[i] }
+const FOO: u32 = 42;
+const fn foo23() -> u32 { FOO }
+const fn foo24() -> &'static u32 { &FOO }
+const fn foo27(x: &u32) -> u32 { *x }
+const fn foo28(x: u32) -> u32 { *&x }
+const fn foo29(x: u32) -> i32 { x as i32 }
+const fn foo31(a: bool, b: bool) -> bool { a & b }
+const fn foo32(a: bool, b: bool) -> bool { a | b }
+const fn foo33(a: bool, b: bool) -> bool { a & b }
+const fn foo34(a: bool, b: bool) -> bool { a | b }
+const fn foo35(a: bool, b: bool) -> bool { a ^ b }
+struct Foo<T: ?Sized>(T);
+impl<T> Foo<T> {
+    const fn new(t: T) -> Self { Foo(t) }
+    const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+    const fn get(&self) -> &T { &self.0 }
+    const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<'a, T> Foo<T> {
+    const fn new_lt(t: T) -> Self { Foo(t) }
+    const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+    const fn get_lt(&'a self) -> &T { &self.0 }
+    const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<T: Sized> Foo<T> {
+    const fn new_s(t: T) -> Self { Foo(t) }
+    const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+    const fn get_s(&self) -> &T { &self.0 }
+    const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<T: ?Sized> Foo<T> {
+    const fn get_sq(&self) -> &T { &self.0 }
+    const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+
+
+const fn char_ops(c: char, d: char) -> bool { c == d }
+const fn char_ops2(c: char, d: char) -> bool { c < d }
+const fn char_ops3(c: char, d: char) -> bool { c != d }
+const fn i32_ops(c: i32, d: i32) -> bool { c == d }
+const fn i32_ops2(c: i32, d: i32) -> bool { c < d }
+const fn i32_ops3(c: i32, d: i32) -> bool { c != d }
+const fn i32_ops4(c: i32, d: i32) -> i32 { c + d }
+const fn char_cast(u: u8) -> char { u as char }
+const unsafe fn foo4() -> i32 { 42 }
+const unsafe fn foo5<T>() -> *const T { 0 as *const T }
+const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
+
+// not ok
+const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo11_2<T: Send>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo19(f: f32) -> f32 { f * 2.0 }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_3(f: f32) -> f32 { -f }
+//~^ ERROR only int and `bool` operations are stable in const fn
+const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+
+static BAR: u32 = 42;
+const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+const fn foo30(x: *const u32) -> usize { x as usize }
+//~^ ERROR casting pointers to int
+const fn foo30_2(x: *mut u32) -> usize { x as usize }
+//~^ ERROR casting pointers to int
+const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+const fn foo36(a: bool, b: bool) -> bool { a && b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo37(a: bool, b: bool) -> bool { a || b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn inc(x: &mut i32) { *x += 1 }
+//~^ ERROR mutable references in const fn are unstable
+
+fn main() {}
+
+impl<T: std::fmt::Debug> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo(&self) {}
+}
+
+impl<T: std::fmt::Debug + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo2(&self) {}
+}
+
+impl<T: Sync + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo3(&self) {}
+}
+
+struct AlanTuring<T>(T);
+const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+//~^ ERROR `impl Trait` in const fn is unstable
+const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+//~^ ERROR trait bounds other than `Sized`
+const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_unsafe() { unsafe {} }
+
+const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_fn_ptrs(_x: fn()) {}
+//~^ ERROR function pointers in const fn are unstable
+const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+//~^ ERROR function pointers in const fn are unstable
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
new file mode 100644 (file)
index 0000000..019948c
--- /dev/null
@@ -0,0 +1,213 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:49:25
+   |
+LL |     const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                         ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:51:5
+   |
+LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:56:28
+   |
+LL |     const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+   |                            ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:58:5
+   |
+LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:63:27
+   |
+LL |     const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+   |                           ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:65:5
+   |
+LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:70:5
+   |
+LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:88:16
+   |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+   |                ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:90:18
+   |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+   |                  ^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:92:33
+   |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+   |                                 ^^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:94:35
+   |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+   |                                   ^^^^^^^
+
+error: only int and `bool` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:96:35
+   |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+   |                                   ^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn.rs:98:43
+   |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+   |                                           ^^^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:102:27
+   |
+LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+   |                           ^^^
+
+error: cannot access `static` items in const fn
+  --> $DIR/min_const_fn.rs:103:36
+   |
+LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+   |                                    ^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:104:42
+   |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:106:42
+   |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:108:38
+   |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:110:29
+   |
+LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+   |                             ^^^^^^^^^^^
+
+error: local variables in const fn are unstable
+  --> $DIR/min_const_fn.rs:111:34
+   |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+   |                                  ^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:112:44
+   |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+   |                                            ^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+  --> $DIR/min_const_fn.rs:114:44
+   |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+   |                                            ^^^^^^
+
+error: mutable references in const fn are unstable
+  --> $DIR/min_const_fn.rs:116:14
+   |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+   |              ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:121:6
+   |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:126:6
+   |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+   |      ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:131:6
+   |
+LL | impl<T: Sync + Sized> Foo<T> {
+   |      ^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:137:1
+   |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:139:34
+   |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+   |                                  ^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:141:22
+   |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error: `impl Trait` in const fn is unstable
+  --> $DIR/min_const_fn.rs:142:1
+   |
+LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:143:23
+   |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+   |                       ^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:144:1
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn.rs:149:41
+   |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:152:21
+   |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+   |                     ^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn.rs:154:1
+   |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 35 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
new file mode 100644 (file)
index 0000000..cfcc799
--- /dev/null
@@ -0,0 +1,25 @@
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:21:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:24:66
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  ^^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/min_const_fn_dyn.rs:24:67
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                   ^    - temporary value only lives until here
+   |                                                                   |
+   |                                                                   temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
new file mode 100644 (file)
index 0000000..38e2825
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+struct HasDyn {
+    field: &'static dyn std::fmt::Debug,
+}
+
+struct Hide(HasDyn);
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+    x.0.field;
+//~^ ERROR trait bounds other than `Sized`
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+//~^ ERROR trait bounds other than `Sized`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
new file mode 100644 (file)
index 0000000..3a1055f
--- /dev/null
@@ -0,0 +1,14 @@
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:21:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+  --> $DIR/min_const_fn_dyn.rs:24:66
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs
new file mode 100644 (file)
index 0000000..100d275
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+struct HasPtr {
+    field: fn(),
+}
+
+struct Hide(HasPtr);
+
+fn field() {}
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+    x.0.field;
+//~^ ERROR function pointers in const fn
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+//~^ ERROR function pointers in const fn
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
new file mode 100644 (file)
index 0000000..c10af3d
--- /dev/null
@@ -0,0 +1,14 @@
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn_fn_ptr.rs:23:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/min_const_fn_fn_ptr.rs:26:59
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+   |                                                           ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
new file mode 100644 (file)
index 0000000..fcc9545
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(integer_atomics, min_const_fn)]
+
+// compile-pass
+
+use std::cell::UnsafeCell;
+use std::sync::atomic::AtomicU32;
+pub struct Condvar {
+    condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+struct NoWait(u32);
+
+const CONDVAR_HAS_NO_WAITERS: NoWait = NoWait(42);
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar {
+            condvar: UnsafeCell::new(AtomicU32::new(CONDVAR_HAS_NO_WAITERS.0)),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
new file mode 100644 (file)
index 0000000..9f5d0ad
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "humans",
+            reason = "who ever let humans program computers,
+            we're apparently really bad at it",
+            issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// conformity is required, even with `const_fn` feature gate
+const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
new file mode 100644 (file)
index 0000000..1ef7ffd
--- /dev/null
@@ -0,0 +1,26 @@
+error: can only call other `min_const_fn` within a `min_const_fn`
+  --> $DIR/min_const_fn_libstd_stability.rs:25:25
+   |
+LL | const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+   |                         ^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+  --> $DIR/min_const_fn_libstd_stability.rs:32:26
+   |
+LL | const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+   |                          ^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+  --> $DIR/min_const_fn_libstd_stability.rs:36:26
+   |
+LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+   |                          ^^^^^^^^^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+  --> $DIR/min_const_fn_libstd_stability.rs:44:32
+   |
+LL | const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+   |                                ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
new file mode 100644 (file)
index 0000000..e7caa4c
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+// ok
+const unsafe fn foo4() -> i32 { 42 }
+const unsafe fn foo5<T>() -> *const T { 0 as *const T }
+const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
+const fn no_unsafe() { unsafe {} }
+
+// not ok
+const fn foo8() -> i32 {
+    unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+}
+const fn foo9() -> *const String {
+    unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+}
+const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
+    unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+}
+const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+//~^ dereferencing raw pointers in constant functions
+
+fn main() {}
+
+const unsafe fn no_union() {
+    union Foo { x: (), y: () }
+    Foo { x: () }.y //~ ERROR not allowed in const fn
+    //~^ unions in const fn
+}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
new file mode 100644 (file)
index 0000000..17cba85
--- /dev/null
@@ -0,0 +1,59 @@
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:29:51
+   |
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+   |                                                   ^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error[E0658]: unions in const fn are unstable (see issue #51909)
+  --> $DIR/min_const_fn_unsafe.rs:36:5
+   |
+LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn_union)] to the crate attributes to enable
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:21:14
+   |
+LL |     unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+   |              ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:24:14
+   |
+LL |     unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+   |              ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:27:14
+   |
+LL |     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:29:51
+   |
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+   |                                                   ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: access to union field is unsafe and unsafe operations are not allowed in const fn
+  --> $DIR/min_const_fn_unsafe.rs:36:5
+   |
+LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+   |     ^^^^^^^^^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/custom-test-frameworks-simple.rs b/src/test/ui/custom-test-frameworks-simple.rs
new file mode 100644 (file)
index 0000000..39a4dc5
--- /dev/null
@@ -0,0 +1,32 @@
+// 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
+// run-pass
+
+#![feature(custom_test_frameworks)]
+#![test_runner(crate::foo_runner)]
+
+#[cfg(test)]
+fn foo_runner(ts: &[&Fn(usize)->()]) {
+    for (i, t) in ts.iter().enumerate() {
+        t(i);
+    }
+}
+
+#[test_case]
+fn test1(i: usize) {
+    println!("Hi #{}", i);
+}
+
+#[test_case]
+fn test2(i: usize) {
+    println!("Hey #{}", i);
+}
diff --git a/src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs b/src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs
new file mode 100644 (file)
index 0000000..c204e69
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::process::exit;
+
+pub trait Testable {
+    // Name of the test
+    fn name(&self) -> String;
+
+    // Tests pass by default
+    fn run(&self) -> bool {
+        true
+    }
+
+    // A test can generate subtests
+    fn subtests(&self) -> Vec<Box<dyn Testable>> {
+        vec![]
+    }
+}
+
+fn run_test(t: &dyn Testable) -> bool {
+    let success = t.subtests().into_iter().all(|sub_t| run_test(&*sub_t)) && t.run();
+    println!("{}...{}", t.name(), if success { "SUCCESS" } else { "FAIL" });
+    success
+}
+
+pub fn runner(tests: &[&dyn Testable]) {
+    let mut failed = false;
+    for t in tests {
+        if !run_test(*t) {
+            failed = true;
+        }
+    }
+
+    if failed {
+        exit(1);
+    }
+}
diff --git a/src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs b/src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs
new file mode 100644 (file)
index 0000000..7b6b5e0
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Testable {
+    fn name(&self) -> String;
+    fn run(&self) -> Option<String>; // None will be success, Some is the error message
+}
+
+pub fn runner(tests: &[&dyn Testable]) {
+    for t in tests {
+        print!("{}........{}", t.name(), t.run().unwrap_or_else(|| "SUCCESS".to_string()));
+    }
+}
diff --git a/src/test/ui/custom_test_frameworks/dynamic.rs b/src/test/ui/custom_test_frameworks/dynamic.rs
new file mode 100644 (file)
index 0000000..f82571b
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// aux-build:dynamic_runner.rs
+// compile-flags:--test
+#![feature(custom_test_frameworks)]
+#![test_runner(dynamic_runner::runner)]
+
+extern crate dynamic_runner;
+
+pub struct AllFoo(&'static str);
+struct IsFoo(String);
+
+impl dynamic_runner::Testable for AllFoo {
+    fn name(&self) -> String {
+        String::from(self.0)
+    }
+
+    fn subtests(&self) -> Vec<Box<dyn dynamic_runner::Testable>> {
+        self.0.split(" ").map(|word|
+            Box::new(IsFoo(word.into())) as Box<dyn dynamic_runner::Testable>
+        ).collect()
+    }
+}
+
+impl dynamic_runner::Testable for IsFoo {
+    fn name(&self) -> String {
+        self.0.clone()
+    }
+
+    fn run(&self) -> bool {
+        self.0 == "foo"
+    }
+}
+
+#[test_case]
+const TEST_2: AllFoo = AllFoo("foo foo");
diff --git a/src/test/ui/custom_test_frameworks/full.rs b/src/test/ui/custom_test_frameworks/full.rs
new file mode 100644 (file)
index 0000000..9fcf76e
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// aux-build:example_runner.rs
+// compile-flags:--test
+
+#![feature(custom_test_frameworks)]
+#![test_runner(example_runner::runner)]
+extern crate example_runner;
+
+pub struct IsFoo(&'static str);
+
+impl example_runner::Testable for IsFoo {
+    fn name(&self) -> String {
+        self.0.to_string()
+    }
+
+    fn run(&self) -> Option<String> {
+        if self.0 != "foo" {
+            return Some(format!("{} != foo", self.0));
+        }
+        None
+    }
+}
+
+#[test_case]
+const TEST_1: IsFoo = IsFoo("hello");
+
+#[test_case]
+const TEST_2: IsFoo = IsFoo("foo");
diff --git a/src/test/ui/custom_test_frameworks/mismatch.rs b/src/test/ui/custom_test_frameworks/mismatch.rs
new file mode 100644 (file)
index 0000000..28753f1
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:example_runner.rs
+// compile-flags:--test
+#![feature(custom_test_frameworks)]
+#![test_runner(example_runner::runner)]
+
+extern crate example_runner;
+
+#[test]
+fn wrong_kind(){}
diff --git a/src/test/ui/custom_test_frameworks/mismatch.stderr b/src/test/ui/custom_test_frameworks/mismatch.stderr
new file mode 100644 (file)
index 0000000..8e2afae
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `test::TestDescAndFn: example_runner::Testable` is not satisfied
+  --> $DIR/mismatch.rs:19:1
+   |
+LL | fn wrong_kind(){}
+   | ^^^^^^^^^^^^^^^^^ the trait `example_runner::Testable` is not implemented for `test::TestDescAndFn`
+   |
+   = note: required for the cast to the object type `dyn example_runner::Testable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 04ba4ab905eb1fb8980f046cbae83a7d9ce26c05..1776a71a6bb472b24e529409141a81f10c529a70 100644 (file)
@@ -15,20 +15,26 @@ macro_rules! borrow {
 fn foo(_: String) {}
 
 fn foo2(s: &String) {
-    foo(s); //~ ERROR mismatched types
+    foo(s);
+    //~^ ERROR mismatched types
 }
 
 fn foo3(_: u32) {}
 fn foo4(u: &u32) {
-    foo3(u); //~ ERROR mismatched types
+    foo3(u);
+    //~^ ERROR mismatched types
 }
 
 fn main() {
     let s = String::new();
     let r_s = &s;
     foo2(r_s);
-    foo(&"aaa".to_owned()); //~ ERROR mismatched types
-    foo(&mut "aaa".to_owned()); //~ ERROR mismatched types
+    foo(&"aaa".to_owned());
+    //~^ ERROR mismatched types
+    foo(&mut "aaa".to_owned());
+    //~^ ERROR mismatched types
     foo3(borrow!(0));
     foo4(&0);
+    assert_eq!(3i32, &3i32);
+    //~^ ERROR mismatched types
 }
index a5f87928924cacf5d464b2463edbc9f08723c050..9811c5969dad69ebc7d00ab10c10603cf02f2249 100644 (file)
@@ -1,7 +1,7 @@
 error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:18:9
    |
-LL |     foo(s); //~ ERROR mismatched types
+LL |     foo(s);
    |         ^
    |         |
    |         expected struct `std::string::String`, found reference
@@ -11,9 +11,9 @@ LL |     foo(s); //~ ERROR mismatched types
               found type `&std::string::String`
 
 error[E0308]: mismatched types
-  --> $DIR/deref-suggestion.rs:23:10
+  --> $DIR/deref-suggestion.rs:24:10
    |
-LL |     foo3(u); //~ ERROR mismatched types
+LL |     foo3(u);
    |          ^
    |          |
    |          expected u32, found &u32
@@ -23,9 +23,9 @@ LL |     foo3(u); //~ ERROR mismatched types
               found type `&u32`
 
 error[E0308]: mismatched types
-  --> $DIR/deref-suggestion.rs:30:9
+  --> $DIR/deref-suggestion.rs:32:9
    |
-LL |     foo(&"aaa".to_owned()); //~ ERROR mismatched types
+LL |     foo(&"aaa".to_owned());
    |         ^^^^^^^^^^^^^^^^^
    |         |
    |         expected struct `std::string::String`, found reference
@@ -35,9 +35,9 @@ LL |     foo(&"aaa".to_owned()); //~ ERROR mismatched types
               found type `&std::string::String`
 
 error[E0308]: mismatched types
-  --> $DIR/deref-suggestion.rs:31:9
+  --> $DIR/deref-suggestion.rs:34:9
    |
-LL |     foo(&mut "aaa".to_owned()); //~ ERROR mismatched types
+LL |     foo(&mut "aaa".to_owned());
    |         ^^^^^^^^^^^^^^^^^^^^^
    |         |
    |         expected struct `std::string::String`, found mutable reference
@@ -58,6 +58,16 @@ LL |     foo3(borrow!(0));
    = note: expected type `u32`
               found type `&{integer}`
 
-error: aborting due to 5 previous errors
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:38:5
+   |
+LL |     assert_eq!(3i32, &3i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32
+   |
+   = note: expected type `i32`
+              found type `&i32`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 767d8a84c041d2abbc78e67e94807d32b67e4999..0aa85d3ed7a3d36f248e6d25c10b99f68c55adbd 100644 (file)
@@ -4,18 +4,18 @@ error[E0161]: cannot move a value of type str: the size of str cannot be statica
 LL |     S[0];
    |     ^^^^
 
-error[E0507]: cannot move out of borrowed content
-  --> $DIR/dst-index.rs:41:5
-   |
-LL |     S[0];
-   |     ^^^^ cannot move out of borrowed content
-
 error[E0161]: cannot move a value of type dyn std::fmt::Debug: the size of dyn std::fmt::Debug cannot be statically determined
   --> $DIR/dst-index.rs:44:5
    |
 LL |     T[0];
    |     ^^^^
 
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-index.rs:41:5
+   |
+LL |     S[0];
+   |     ^^^^ cannot move out of borrowed content
+
 error[E0507]: cannot move out of borrowed content
   --> $DIR/dst-index.rs:44:5
    |
index 5eadcc3def5ff529ce20ad5412306da74f755221..b120da773a24a3448d80882dfaf46fa498d4be5d 100644 (file)
@@ -4,18 +4,18 @@ error[E0161]: cannot move a value of type str: the size of str cannot be statica
 LL |     let _x: Box<str> = box *"hello world";
    |                            ^^^^^^^^^^^^^^
 
-error[E0507]: cannot move out of borrowed content
-  --> $DIR/dst-rvalue.rs:16:28
-   |
-LL |     let _x: Box<str> = box *"hello world";
-   |                            ^^^^^^^^^^^^^^ cannot move out of borrowed content
-
 error[E0161]: cannot move a value of type [isize]: the size of [isize] cannot be statically determined
   --> $DIR/dst-rvalue.rs:21:32
    |
 LL |     let _x: Box<[isize]> = box *array;
    |                                ^^^^^^
 
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-rvalue.rs:16:28
+   |
+LL |     let _x: Box<str> = box *"hello world";
+   |                            ^^^^^^^^^^^^^^ cannot move out of borrowed content
+
 error[E0508]: cannot move out of type `[isize]`, a non-copy slice
   --> $DIR/dst-rvalue.rs:21:32
    |
index 3a243330ad9b06f4b70cb9cc9361b490ca37e3cb..dab22de1b6e58101ae13cfa0a110baa78f739bc1 100644 (file)
@@ -18,3 +18,4 @@ enum Eu64 {
     Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists
 }
 
+fn main() {}
index 3b4ac436898e6e5d48a112ff9ccdc7384750876b..e4419d6285127a5312a94f04b1f3f331ee8547c9 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `enum_discrim_autosizing`
-   |
-   = note: consider adding a `main` function to `$DIR/enum-discrim-autosizing.rs`
-
 error[E0081]: discriminant value `0` already exists
   --> $DIR/enum-discrim-autosizing.rs:18:12
    |
@@ -10,7 +6,6 @@ LL |     Au64 = 0,
 LL |     Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists
    |            ^^^^^^^^^^^^^^^^^^^^^ enum already has `0`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0081, E0601.
-For more information about an error, try `rustc --explain E0081`.
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/error-codes/E0161.ast.stderr b/src/test/ui/error-codes/E0161.ast.stderr
new file mode 100644 (file)
index 0000000..62e8676
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:9
+   |
+LL |     box *x; //~ ERROR E0161
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.astul.stderr b/src/test/ui/error-codes/E0161.astul.stderr
new file mode 100644 (file)
index 0000000..79080fb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:5
+   |
+LL |     box *x; //~ ERROR E0161
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.edition.stderr b/src/test/ui/error-codes/E0161.edition.stderr
new file mode 100644 (file)
index 0000000..62e8676
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:9
+   |
+LL |     box *x; //~ ERROR E0161
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.editionul.stderr b/src/test/ui/error-codes/E0161.editionul.stderr
new file mode 100644 (file)
index 0000000..79080fb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:5
+   |
+LL |     box *x; //~ ERROR E0161
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.nll.stderr b/src/test/ui/error-codes/E0161.nll.stderr
new file mode 100644 (file)
index 0000000..62e8676
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:9
+   |
+LL |     box *x; //~ ERROR E0161
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.nllul.stderr b/src/test/ui/error-codes/E0161.nllul.stderr
new file mode 100644 (file)
index 0000000..79080fb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:5
+   |
+LL |     box *x; //~ ERROR E0161
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
index 81adf9083024d62d4d1f41be911dfc1365ee178e..edc5a84a8436753e35a6757c5618946fb813ae29 100644 (file)
@@ -8,9 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-compare-mode-nll
+
+// Check that E0161 is a hard error in all possible configurations that might
+// affect it.
+
+// revisions: ast nll zflags edition astul nllul zflagsul editionul
+//[zflags]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[edition]edition:2018
+//[zflagsul]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[editionul]edition:2018
+
+#![cfg_attr(nll, feature(nll))]
+#![cfg_attr(nllul, feature(nll))]
+#![cfg_attr(astul, feature(unsized_locals))]
+#![cfg_attr(zflagsul, feature(unsized_locals))]
+#![cfg_attr(nllul, feature(unsized_locals))]
+#![cfg_attr(editionul, feature(unsized_locals))]
+
 #![feature(box_syntax)]
 
-fn main() {
-    let _x: Box<str> = box *"hello"; //~ ERROR E0161
-                                     //~^ ERROR E0507
+fn foo(x: Box<[i32]>) {
+    box *x; //~ ERROR E0161
 }
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0161.zflags.stderr b/src/test/ui/error-codes/E0161.zflags.stderr
new file mode 100644 (file)
index 0000000..62e8676
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:9
+   |
+LL |     box *x; //~ ERROR E0161
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.zflagsul.stderr b/src/test/ui/error-codes/E0161.zflagsul.stderr
new file mode 100644 (file)
index 0000000..79080fb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:32:5
+   |
+LL |     box *x; //~ ERROR E0161
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
index 490a8e0ff0f1d1cfb0217d59aa67c741df9b0c14..438dd50f2bfa80aaca4ed97b47cf152bed233132 100644 (file)
@@ -4,8 +4,8 @@ error[E0308]: intrinsic has wrong type
 LL |     fn size_of<T>(); //~ ERROR E0308
    |     ^^^^^^^^^^^^^^^^ expected (), found usize
    |
-   = note: expected type `unsafe extern "rust-intrinsic" fn()`
-              found type `unsafe extern "rust-intrinsic" fn() -> usize`
+   = note: expected type `extern "rust-intrinsic" fn()`
+              found type `extern "rust-intrinsic" fn() -> usize`
 
 error: aborting due to previous error
 
index caedc79d80732999637095b617c6e7833bed7e28..65008380f9e1771b8c21fd1aa23e3916cd8ded27 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5
-   |
-LL |     invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
-   |     ^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/E0621-does-not-trigger-for-closures.rs:25:45
    |
index 84af8e1dca2b1dbae5f7077b8805d8c0a1d2bce1..a480f54ac187385f7088bea0aab1134f752d97f9 100644 (file)
@@ -7,12 +7,6 @@ LL |     let z: i32 = x; //~ ERROR mismatched types
    = note: expected type `i32`
               found type `WrongGeneric::<&{integer}>`
 
-warning: not reporting region error due to nll
-  --> $DIR/generic_type_does_not_live_long_enough.rs:19:1
-   |
-LL | existential type WrongGeneric<T>: 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/feature-gate-custom_test_frameworks.rs b/src/test/ui/feature-gate-custom_test_frameworks.rs
new file mode 100644 (file)
index 0000000..7c9f7dd
--- /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.
+
+#![test_runner(main)] //~ ERROR custom test frameworks are an unstable feature
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-custom_test_frameworks.stderr b/src/test/ui/feature-gate-custom_test_frameworks.stderr
new file mode 100644 (file)
index 0000000..bfcbab5
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: custom test frameworks are an unstable feature (see issue #50297)
+  --> $DIR/feature-gate-custom_test_frameworks.rs:11:1
+   |
+LL | #![test_runner(main)] //~ ERROR custom test frameworks are an unstable feature
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_test_frameworks)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs
new file mode 100644 (file)
index 0000000..6207d99
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change
+pub struct SomeStruct;
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr b/src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr
new file mode 100644 (file)
index 0000000..be2c263
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: `cfg(rustdoc)` is experimental and subject to change (see issue #43781)
+  --> $DIR/feature-gate-doc_cfg-cfg-rustdoc.rs:11:7
+   |
+LL | #[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change
+   |       ^^^^^^^
+   |
+   = help: add #![feature(doc_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index 1d1dedddaaa3e72099f70dab571a40f976d0359e..f774658975b79d983021d8ee80f4c430704a83a2 100644 (file)
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test use of const fn without feature gate.
+// Test use of const fn without the `const_fn` feature gate.
+// `min_const_fn` is checked in its own file
+#![feature(min_const_fn)]
 
-const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+const fn foo() -> usize { 0 } // ok
 
 trait Foo {
     const fn foo() -> u32; //~ ERROR const fn is unstable
@@ -20,12 +22,11 @@ const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
 }
 
 impl Foo {
-    const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+    const fn baz() -> u32 { 0 } // ok
 }
 
 impl Foo for u32 {
-    const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
-                                //~| ERROR trait fns cannot be declared const
+    const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
 }
 
 static FOO: usize = foo();
index d7c00a3e0cb40e7f6ca568ac48921d33b4a8dcdd..26c0c7877b4ecc6f51b03b1531e65a720dced564 100644 (file)
@@ -1,31 +1,23 @@
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:16:5
+  --> $DIR/feature-gate-const_fn.rs:18:5
    |
 LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    |     ^^^^^ trait fns cannot be const
 
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:18:5
+  --> $DIR/feature-gate-const_fn.rs:20:5
    |
 LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
    |     ^^^^^ trait fns cannot be const
 
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:27:5
+  --> $DIR/feature-gate-const_fn.rs:29:5
    |
-LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+LL |     const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
    |     ^^^^^ trait fns cannot be const
 
 error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:13:1
-   |
-LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:16:5
+  --> $DIR/feature-gate-const_fn.rs:18:5
    |
 LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -33,30 +25,14 @@ LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
 error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:18:5
+  --> $DIR/feature-gate-const_fn.rs:20:5
    |
 LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:23:5
-   |
-LL |     const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error[E0658]: const fn is unstable (see issue #24111)
-  --> $DIR/feature-gate-const_fn.rs:27:5
-   |
-LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error: aborting due to 8 previous errors
+error: aborting due to 5 previous errors
 
 Some errors occurred: E0379, E0658.
 For more information about an error, try `rustc --explain E0379`.
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs
new file mode 100644 (file)
index 0000000..e052ba9
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// Test use of min_const_fn without feature gate.
+
+const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+
+trait Foo {
+    const fn foo() -> u32; //~ ERROR const fn is unstable
+                           //~| ERROR trait fns cannot be declared const
+    const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+                                //~| ERROR trait fns cannot be declared const
+}
+
+impl Foo {
+    const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+}
+
+impl Foo for u32 {
+    const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+                                //~| ERROR trait fns cannot be declared const
+}
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo()
+}
+
+fn main() {
+    let x: [usize; foo()] = [];
+}
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
new file mode 100644 (file)
index 0000000..aa77503
--- /dev/null
@@ -0,0 +1,62 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:16:5
+   |
+LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:18:5
+   |
+LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:27:5
+   |
+LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0658]: const fn is unstable (see issue #53555)
+  --> $DIR/feature-gate-min_const_fn.rs:13:1
+   |
+LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-min_const_fn.rs:16:5
+   |
+LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-min_const_fn.rs:18:5
+   |
+LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #53555)
+  --> $DIR/feature-gate-min_const_fn.rs:23:5
+   |
+LL |     const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #53555)
+  --> $DIR/feature-gate-min_const_fn.rs:27:5
+   |
+LL |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0379, E0658.
+For more information about an error, try `rustc --explain E0379`.
index 5baafd4153159f3f6b27b31c5b0042720c51484e..0d74f9011c3ecdbac0c029c9ad94dd5b667b22cc 100644 (file)
@@ -20,3 +20,5 @@
 #![feature = "foo"] //~ ERROR: malformed feature
 
 #![feature(test_removed_feature)] //~ ERROR: feature has been removed
+
+fn main() {}
index 2bed241d68cabb0d52649105e42d3409ab0d672e..68be49a7277d26bb0b71a78fd4a4b89ed7c4d5a1 100644 (file)
@@ -28,11 +28,7 @@ error[E0557]: feature has been removed
 LL | #![feature(test_removed_feature)] //~ ERROR: feature has been removed
    |            ^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `gated_bad_feature`
-   |
-   = note: consider adding a `main` function to `$DIR/gated-bad-feature.rs`
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors occurred: E0555, E0556, E0557, E0601.
+Some errors occurred: E0555, E0556, E0557.
 For more information about an error, try `rustc --explain E0555`.
index bb4e922fdc0d23cebb585281ecbebdd1583d839e..cadb552697e651f2b657b45f8d1ff69f1eafc780 100644 (file)
@@ -1,23 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/hr-subtype.rs:43:26
-   |
-LL |               gimme::<$t2>(None::<$t1>);
-   |                            ^^^^^^^^^^^
-...
-LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
-LL | |                                     fn(Inv<'y>)) }
-   | |__________________________________________________- in this macro invocation
-
-warning: not reporting region error due to nll
-  --> $DIR/hr-subtype.rs:49:26
-   |
-LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^
-...
-LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
-LL | |                                     fn(Inv<'y>)) }
-   | |__________________________________________________- in this macro invocation
-
 error: unsatisfied lifetime constraints
   --> $DIR/hr-subtype.rs:43:13
    |
index c33e6fbfde72ca9bd87f752b655f7f284ba3b333..c1bcd146b34896f81879143b37d6c202ee089572 100644 (file)
@@ -1,13 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/hr-subtype.rs:49:26
-   |
-LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^
-...
-LL | / check! { free_x_vs_free_y: (fn(&'x u32),
-LL | |                             fn(&'y u32)) }
-   | |__________________________________________- in this macro invocation
-
 error: unsatisfied lifetime constraints
   --> $DIR/hr-subtype.rs:49:13
    |
index 56b77714991ca61e7d5d5ca72684aad75686a1cb..9b25a865f921e1ff806c5efb99a478ece047f0c4 100644 (file)
@@ -1,9 +1,6 @@
 error[E0382]: use of moved value: `foo.x`
   --> $DIR/fields-move.rs:28:9
    |
-LL |    $foo.x
-   |    ------ value moved here
-...
 LL |         $foo.x //~ ERROR use of moved value: `foo.x`
    |         ^^^^^^ value used here after move
 ...
@@ -28,14 +25,9 @@ LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved val
 error[E0382]: use of moved value: `foo.x`
   --> $DIR/fields-move.rs:39:42
    |
-LL |    $foo.x
-   |    ------ value moved here
-...
 LL |         $foo.x //~ ERROR use of moved value: `foo.x`
    |         ------ value moved here
 ...
-LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
-   |                                          ----- value moved here
 LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
    |                                          ^^^^^ value used here after move
    |
index 2b2108558a0f385908c02d0b9b75a3f1afd8badd..efb3696cf851376557fb1f39a118a54422bda97e 100644 (file)
@@ -55,3 +55,5 @@ fn check_legacy() {
     struct FromOutside;
     genmod_legacy!();
 }
+
+fn main() {}
index 0c5905c5acb4fdc9ba2f93595feabfc269f30b66..f86444bae77e817d3a884ae0fb80cb4b416f786e 100644 (file)
@@ -46,11 +46,6 @@ LL |         type Inner = Outer; //~ ERROR cannot find type `Outer` in this scop
 LL |     genmod_legacy!();
    |     ----------------- in this macro invocation
 
-error[E0601]: `main` function not found in crate `generate_mod`
-   |
-   = note: consider adding a `main` function to `$DIR/generate-mod.rs`
-
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors occurred: E0412, E0601.
-For more information about an error, try `rustc --explain E0412`.
+For more information about this error, try `rustc --explain E0412`.
index c90c7b3093c9f0e5d04a15371b082d4cf05dbf38..bf07bc05491cc3752afd543338b08af9a5ff4c09 100644 (file)
@@ -23,3 +23,5 @@ mod bar {
     }
     fn f() { ::foo::m!(); }
 }
+
+fn main() {}
index b3d82e9094ba732ebc6001ee6a355914943984bf..463fdbf00ce54bbc3783b5042395a90c36c82456 100644 (file)
@@ -7,10 +7,6 @@ LL |     fn f() { ::bar::m!(); }
 LL |         Vec::new(); //~ ERROR failed to resolve
    |         ^^^ Use of undeclared type or module `Vec`
 
-error[E0601]: `main` function not found in crate `no_implicit_prelude`
-   |
-   = note: consider adding a `main` function to `$DIR/no_implicit_prelude.rs`
-
 error[E0599]: no method named `clone` found for type `()` in the current scope
   --> $DIR/no_implicit_prelude.rs:22:12
    |
@@ -24,7 +20,7 @@ LL |         ().clone() //~ ERROR no method named `clone` found
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
            `use std::clone::Clone;`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0433, E0599, E0601.
+Some errors occurred: E0433, E0599.
 For more information about an error, try `rustc --explain E0433`.
index f5d98e04ad804009fdef311814c7c8eaaa86076c..45ee808950e25795f71b2f6e7ac92e4274eaa7c9 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/dyn-trait.rs:32:16
-   |
-LL |     static_val(x); //~ ERROR cannot infer
-   |                ^
-
 error: borrowed data escapes outside of function
   --> $DIR/dyn-trait.rs:32:5
    |
index 97cb2cc16e45ec13d8f0ca1099ed9a193cfca237..1e3e997b111ace1bf9505c1552335042eee99f36 100644 (file)
@@ -1,33 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/must_outlive_least_region_or_bound.rs:13:35
-   |
-LL | fn elided(x: &i32) -> impl Copy { x }
-   |                                   ^
-
-warning: not reporting region error due to nll
-  --> $DIR/must_outlive_least_region_or_bound.rs:16:44
-   |
-LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |                                            ^
-
-warning: not reporting region error due to nll
-  --> $DIR/must_outlive_least_region_or_bound.rs:22:69
-   |
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                                                                     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/must_outlive_least_region_or_bound.rs:29:5
-   |
-LL |     move |_| println!("{}", y)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/must_outlive_least_region_or_bound.rs:32:51
-   |
-LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-   |                                                   ^^^^^^^^^^^^^^^^^^^^
-
 error[E0621]: explicit lifetime required in the type of `x`
   --> $DIR/must_outlive_least_region_or_bound.rs:13:35
    |
index c1e12978c5179c057186d2390b66e71cbafab4d3..2568eb2ed3fc154149c727b90d0396c3be01eacb 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/static-return-lifetime-infered.rs:17:16
-   |
-LL |         self.x.iter().map(|a| a.0)
-   |                ^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/static-return-lifetime-infered.rs:21:16
-   |
-LL |         self.x.iter().map(|a| a.0)
-   |                ^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/static-return-lifetime-infered.rs:17:9
    |
index 823ee4467299e5e09764e22f67d8a4fb11dc501f..3c2c86fffded025d18052621061cb0aeb0d9f1dd 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/type_parameters_captured.rs:17:20
-   |
-LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |                    ^^^^^^^^^^^^^^^^^^
-
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/type_parameters_captured.rs:19:5
    |
index d9cc17791ed563bd7ce65ab7d3435a2eb3fe4e47..b2e92fe0e1bf9212c78ce8dc0f4a29dddc5f4af5 100644 (file)
@@ -25,3 +25,5 @@ mod test {
 
     fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope
 }
+
+fn main() {}
index 078a6a3937a47282a727988d7afdf753df2dc460..fdff04cc2414892bb320ab77f6e3336b4e75557d 100644 (file)
@@ -4,11 +4,6 @@ error[E0425]: cannot find function `f1066` in this scope
 LL |     fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope
    |                 ^^^^^ not found in this scope
 
-error[E0601]: `main` function not found in crate `import_glob_circular`
-   |
-   = note: consider adding a `main` function to `$DIR/import-glob-circular.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0425, E0601.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0425`.
index b7bbe11a4dc96b01e5b274d64ef036aa0c75f781..0bc968872db5bcc2a10b249ebaf378957e8f3614 100644 (file)
@@ -19,3 +19,5 @@ mod b {
 
     fn main() { let y = x; }
 }
+
+fn main() {}
index 717f74643ebb40b286194309fd916fdf5bd001a4..09c2e7918f37627fe213297e2b0eef074e1cec34 100644 (file)
@@ -4,16 +4,6 @@ error[E0432]: unresolved import `a::x`
 LL |     pub use a::x;
    |             ^^^^ no `x` in `a`
 
-error[E0601]: `main` function not found in crate `import_loop_2`
-   |
-   = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
-note: here is a function named 'main'
-  --> $DIR/import-loop-2.rs:20:5
-   |
-LL |     fn main() { let y = x; }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0432, E0601.
-For more information about an error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0432`.
index c07921bce2d72cb2eefd72e94c8bb518160fa606..c8b2f849b32a79902279a704d47b78fa5d41aa25 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/mismatched.rs:14:42
-   |
-LL | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y } //~ ERROR explicit lifetime required
-   |                                          ^
-
-warning: not reporting region error due to nll
-  --> $DIR/mismatched.rs:16:46
-   |
-LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatch
-   |                                              ^
-
 error[E0621]: explicit lifetime required in the type of `y`
   --> $DIR/mismatched.rs:14:42
    |
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr
deleted file mode 100644 (file)
index a01f321..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/mismatched_trait.rs:16:9
-   |
-LL |         y //~ ERROR explicit lifetime required
-   |         ^
-
-error[E0621]: explicit lifetime required in the type of `y`
-  --> $DIR/mismatched_trait.rs:16:9
-   |
-LL |     fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 {
-   |                                  ---- help: add explicit lifetime `'a` to the type of `y`: `&'a u32`
-LL |         y //~ ERROR explicit lifetime required
-   |         ^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index ce8eaf590275f63c3e16e522cdcf0d52e847a29a..5b964c1a14b992aa6a41e2d53e6fa4720aa052f4 100644 (file)
@@ -2,7 +2,7 @@ error[E0432]: unresolved import `__test`
   --> $DIR/inaccessible-test-modules.rs:15:5
    |
 LL | use __test as x; //~ ERROR unresolved import `__test`
-   |     ^^^^^^^^^^^ no `__test` in the root. Did you mean to use `__test`?
+   |     ^^^^^^^^^^^ no `__test` in the root. Did you mean to use `test`?
 
 error[E0432]: unresolved import `__test_reexports`
   --> $DIR/inaccessible-test-modules.rs:16:5
index 4f1f67214509e5bb1c8c48f6915a9088ffc1b7b6..63ae18cf9c2fa1d3c0cf735e778afb8aae26c965 100644 (file)
@@ -10,7 +10,7 @@
 
 //https://github.com/rust-lang/rust/issues/31364
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 const fn a() -> usize { b() }
 const fn b() -> usize { a() }
 const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression
index 6d42515704ea117a95e42655de397df4602bcf7c..904a9acf9e53097f41f00996de95307aa4f85f16 100644 (file)
@@ -12,3 +12,5 @@
 #![crate_type(lib)]  //~ ERROR `crate_type` requires a value
 
 fn my_lib_fn() {}
+
+fn main() {}
index b609695b86ee5b92b61f5f5871bdc82e0beb7194..6f02f96faca93e91c7a753c734d42cf037f75669 100644 (file)
@@ -6,10 +6,5 @@ LL | #![crate_type(lib)]  //~ ERROR `crate_type` requires a value
    |
    = note: for example: `#![crate_type="lib"]`
 
-error[E0601]: `main` function not found in crate `invalid_crate_type_syntax`
-   |
-   = note: consider adding a `main` function to `$DIR/invalid_crate_type_syntax.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index 48dad040f9d0cd64c1ea84a737836d9789f4c3bd..d19c4d880c7c84da692612e0c78323513a1c860e 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-10291.rs:13:9
-   |
-LL |         x //~ ERROR E0312
-   |         ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/issue-10291.rs:12:5
    |
index acac2d151fe9ad5ef8008d3caf10f1a5de111bf7..424cbd981c87d9b92c6aeb632377c14cf121a61d 100644 (file)
@@ -10,5 +10,5 @@
 
 fn main() {
     concat!(test!());
-    //~^ ERROR cannot find macro `test!` in this scope
+    //~^ error: cannot find macro `test!` in this scope
 }
index 3030ee4779b4b71cc2fde28e532e526a5017b8b6..853a2a0f1b4f1018f812d7823b14f01d1b9b2d05 100644 (file)
@@ -5,7 +5,7 @@ LL | fn bar(x: isize) { }
    | ^^^^^^^^^^^^^^^^^^^^ expected isize, found mutable reference
    |
    = note: expected type `isize`
-              found type `&mut __test::test::Bencher`
+              found type `&mut test::Bencher`
 
 error: aborting due to previous error
 
index 146385f3de2d82070add89283c4bcbf3c4d34611..33c0eefbfaa289758d5a0a1d81b20e3d5750b64a 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-13058.rs:24:21
-   |
-LL |     let cont_iter = cont.iter();
-   |                     ^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-13058.rs:24:26
-   |
-LL |     let cont_iter = cont.iter();
-   |                          ^^^^
-
 error[E0308]: mismatched types
   --> $DIR/issue-13058.rs:36:11
    |
diff --git a/src/test/ui/issues/issue-14285.nll.stderr b/src/test/ui/issues/issue-14285.nll.stderr
deleted file mode 100644 (file)
index cf3e44f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-14285.rs:22:7
-   |
-LL |     B(a)    //~ ERROR 22:5: 22:9: explicit lifetime required in the type of `a` [E0621]
-   |       ^
-
-error[E0621]: explicit lifetime required in the type of `a`
-  --> $DIR/issue-14285.rs:22:5
-   |
-LL | fn foo<'a>(a: &Foo) -> B<'a> {
-   |               ---- help: add explicit lifetime `'a` to the type of `a`: `&'a (dyn Foo + 'a)`
-LL |     B(a)    //~ ERROR 22:5: 22:9: explicit lifetime required in the type of `a` [E0621]
-   |     ^^^^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index 8dd18fa0cab89c66c6be8d9a85a8d76e2d92bf5f..aa5ceabfb11748648f0f20a1757ac22b8c7a466d 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-15034.rs:27:9
-   |
-LL |         Parser { lexer: lexer }
-   |         ^^^^^^
-
 error[E0621]: explicit lifetime required in the type of `lexer`
   --> $DIR/issue-15034.rs:27:9
    |
index 890bb426441e2182b569952ec8dfcbaa4c1805db..29d9948f61a428fe89dd4d0ec1a1635f12367e8e 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-16683.rs:14:9
-   |
-LL |         self.a(); //~ ERROR cannot infer
-   |         ^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-16683.rs:14:14
-   |
-LL |         self.a(); //~ ERROR cannot infer
-   |              ^
-
 error: borrowed data escapes outside of function
   --> $DIR/issue-16683.rs:14:9
    |
index 1bd26faedaae3000e6ebfe89a50307f57ce9e0ea..3406d534896600aac3fc7ddd15e8047e17577c9d 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-16922.rs:14:14
-   |
-LL |     Box::new(value) as Box<Any>
-   |              ^^^^^
-
 error[E0621]: explicit lifetime required in the type of `value`
   --> $DIR/issue-16922.rs:14:5
    |
index b9931e45bd2381bae7057f90d863e0608080d49c..2cb6f831d85684b6d383f02a7e571f9f5a9fe792 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-17728.rs:23:49
-   |
-LL |         let maybe_room = room.direction_to_room.get(&direction);
-   |                                                 ^^^
-
 error[E0308]: match arms have incompatible types
   --> $DIR/issue-17728.rs:110:5
    |
index c51a72f885d6c83487eab1d2cbb8c07375e06403..87e01ace64a1b5fe2b5b3d52444439536a9b18b5 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-17758.rs:17:9
-   |
-LL |         self.foo();
-   |         ^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-17758.rs:17:14
-   |
-LL |         self.foo();
-   |              ^^^
-
 error: borrowed data escapes outside of function
   --> $DIR/issue-17758.rs:17:9
    |
index 94e3692d53db553936097254d7fa349b1c6e65d5..f28b06540990637895334b7c19c3a4565a8a78ca 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-26217.rs:14:5
-   |
-LL |     foo::<&'a i32>();
-   |     ^^^^^^^^^^^^^^
-
 error[E0131]: `main` function is not allowed to have generic parameters
   --> $DIR/issue-26217.rs:13:8
    |
diff --git a/src/test/ui/issues/issue-3154.nll.stderr b/src/test/ui/issues/issue-3154.nll.stderr
deleted file mode 100644 (file)
index 3cd7ce8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-3154.rs:16:15
-   |
-LL |     thing{ x: x } //~ ERROR 16:5: 16:18: explicit lifetime required in the type of `x` [E0621]
-   |               ^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-3154.rs:16:5
-   |
-LL |     thing{ x: x } //~ ERROR 16:5: 16:18: explicit lifetime required in the type of `x` [E0621]
-   |     ^^^^^
-
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/issue-3154.rs:16:5
-   |
-LL | fn thing<'a,Q>(x: &Q) -> thing<'a,Q> {
-   |                   -- help: add explicit lifetime `'a` to the type of `x`: `&'a Q`
-LL |     thing{ x: x } //~ ERROR 16:5: 16:18: explicit lifetime required in the type of `x` [E0621]
-   |     ^^^^^^^^^^^^^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index 552653c21bad61724113cd2e3d6d38cee8653183..5c745d1fab3b5374a367f8cf2f0af04d9abd753c 100644 (file)
@@ -14,3 +14,5 @@ macro_rules! foo { ($i:ident) => {} }
 #[macro_export]
 macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
                               //~| WARN this was previously accepted
+
+fn main() {}
index a0dbcbd18c67336ab4e81fea35f0f3709554d6a7..67b27cc83cc897e74ea42ea3b41039dd525c8b88 100644 (file)
@@ -13,10 +13,5 @@ note: previous macro export is now shadowed
 LL | macro_rules! foo { ($i:ident) => {} }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `issue_38715`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-38715.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index dcc9e0a8a65a54551e82073e5f44f7873ad3349f..e15e4e86dbcbf460f6a7d755d56595dc6b14d141 100644 (file)
@@ -1,39 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-40288-2.rs:17:20
-   |
-LL |         slice[0] = y;
-   |                    ^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-40288-2.rs:16:20
-   |
-LL |         let slice: &mut [_] = &mut out;
-   |                    ^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-40288-2.rs:14:19
-   |
-LL |     let mut out = [x];
-   |                   ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-40288-2.rs:32:20
-   |
-LL |         dst.head = y;
-   |                    ^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-40288-2.rs:31:18
-   |
-LL |         let dst: &mut Struct<_, [()]> = &mut out;
-   |                  ^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/issue-40288-2.rs:29:19
-   |
-LL |     let mut out = Struct { head: x, _tail: [()] };
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0621]: explicit lifetime required in the type of `y`
   --> $DIR/issue-40288-2.rs:17:9
    |
index dd53a1c71a5bce538a8474502bc15c60457d5957..46c8cb740ded7cfc3b101d87a2039115490963b2 100644 (file)
@@ -15,3 +15,5 @@ macro_rules! foo {
 }
 
 foo!(a);
+
+fn main() {}
index 91439061996162b5f26737e9b8612a30e81906a6..fa736edc47f5bf8207b045f332a00575764ab0d4 100644 (file)
@@ -4,10 +4,5 @@ error: repetition matches empty token tree
 LL |     ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree
    |       ^^^^^^^^
 
-error[E0601]: `main` function not found in crate `issue_42755`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-42755.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index 94b5c0034a76deca5addf72a4af88fe64b2a54aa..1ff1238ec54b83724b806bca0bd5875ed8aeee6f 100644 (file)
@@ -23,3 +23,5 @@ impl<T> Partial<T> for T::Assoc where
 impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
     type Assoc = T;
 }
+
+fn main() {}
index 798d8c660166847d613c291f1ae0d840e91deb9b..18e97e24b733a334315853005787a5d2fdbfa769 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `issue_43784_associated_type`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-43784-associated-type.rs`
-
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/issue-43784-associated-type.rs:23:9
    |
@@ -10,7 +6,6 @@ LL | impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` i
    |
    = help: consider adding a `where T: std::marker::Copy` bound
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0277, E0601.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
index e70df113da33cfcb7e3b2e212e222789052f3602..30132c3be88a7a4f9bc700db7bb1c6c5ecef5b0f 100644 (file)
@@ -16,3 +16,5 @@ pub trait Complete: Partial {
 
 impl<T> Partial for T where T: Complete {}
 impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn main() {}
index 8646b315abdab59160810251d498ee3d59162564..422075f62aa0d086771646a276a8b9e3ae13645a 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `issue_43784_supertrait`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-43784-supertrait.rs`
-
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/issue-43784-supertrait.rs:18:9
    |
@@ -10,7 +6,6 @@ LL | impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0277, E0601.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
index 5d295510844ab277d3ae529d495d9e733f80fb92..bd50f93945c51f00b0dfb18b93c75851bab993c2 100644 (file)
@@ -10,7 +10,7 @@
 
 //~^^^^^^^^^^ ERROR cycle detected when computing layout of
 
-#![feature(const_fn)]
+
 #![feature(core_intrinsics)]
 
 use std::intrinsics;
diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs
new file mode 100644 (file)
index 0000000..54eff22
--- /dev/null
@@ -0,0 +1,8 @@
+// Regression test for https://github.com/rust-lang/rust/issues/52060
+// The compiler shouldn't ICE in this case
+static A: &'static [u32] = &[1];
+static B: [u32; 1] = [0; A.len()];
+//~^ ERROR [E0013]
+//~| ERROR `core::slice::<impl [T]>::len` is not yet stable as a const fn
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
new file mode 100644 (file)
index 0000000..988bfd4
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^
+
+error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^^^^^^^
+   |
+   = help: in Nightly builds, add `#![feature(const_slice_len)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
index 7a04aeb963547a0ff07317866c62ddea5b7d610f..dab3fd866ba64bcef97d51a0413ae50b77ea5442 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-52213.rs:12:11
-   |
-LL |     match (&t,) { //~ ERROR cannot infer an appropriate lifetime
-   |           ^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/issue-52213.rs:13:20
    |
index 7ae01fb7d6012996c1e80ebb82038431117b6aaa..f9191a9fd8229acc496517ffd08bbd07daa5cbaa 100644 (file)
@@ -5,8 +5,10 @@ LL |     let x = |ref x: isize| { x += 1; };
    |                              -^^^^^
    |                              |
    |                              cannot use `+=` on type `&isize`
+help: `+=` can be used on 'isize', you can dereference `x`
    |
-   = help: `+=` can be used on 'isize', you can dereference `x`: `*x`
+LL |     let x = |ref x: isize| { *x += 1; };
+   |                              ^^
 
 error: aborting due to previous error
 
index 2dfa46dc2288e7aeefd3bd465457d2b5ba51a38f..cc5f4df79f8f566dd78fe5060765700c279bd601 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-52533-1.rs:19:18
-   |
-LL |     gimme(|x, y| y)
-   |                  ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/issue-52533-1.rs:19:18
    |
index 17218429822e85832be15163b47f7492cd823199..37ab2a3b84d2f3fafc2f098c950449ba8490e143 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/issue-52533.rs:15:16
-   |
-LL |     foo(|a, b| b)
-   |                ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/issue-52533.rs:15:16
    |
index 8f24baf7fc46fd2b5d160c1e8cd21609e43ea16c..d484632f4c34e336507b4ec832a909f84bbd61db 100644 (file)
@@ -40,12 +40,6 @@ LL |     let a: &Gettable<T> = &t;
    = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
    = note: required for the cast to the object type `dyn Gettable<T>`
 
-warning: not reporting region error due to nll
-  --> $DIR/kindck-impl-type-params.rs:42:13
-   |
-LL |     let a = &t as &Gettable<&'a isize>;
-   |             ^^
-
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:48:13
    |
index 6613a29cd7688cc245eda1c9be315f8037c53262..a45ba157bf9a34913c0c48f169c721def057293c 100644 (file)
@@ -12,12 +12,6 @@ note: required by `assert_send`
 LL | fn assert_send<T:Send+'static>() { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: not reporting region error due to nll
-  --> $DIR/kindck-send-object1.rs:24:5
-   |
-LL |     assert_send::<&'a (Dummy+Sync)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
   --> $DIR/kindck-send-object1.rs:39:5
    |
index ab9bb19563127eb1e6ac4beed9fc9485e463d889..bc15df264cc3b1d895c4d473621e1e17589a1301 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/lifetime-bound-will-change-warning.rs:44:13
-   |
-LL |     ref_obj(x) //~ ERROR mismatched types
-   |             ^
-
-warning: not reporting region error due to nll
-  --> $DIR/lifetime-bound-will-change-warning.rs:49:18
-   |
-LL |     lib::ref_obj(x) //~ ERROR mismatched types
-   |                  ^
-
 error: borrowed data escapes outside of function
   --> $DIR/lifetime-bound-will-change-warning.rs:44:5
    |
diff --git a/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr
deleted file mode 100644 (file)
index 3fb0252..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/42701_one_named_and_one_anonymous.rs:20:9
-   |
-LL |         &*x //~ ERROR explicit lifetime
-   |         ^^^
-
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/42701_one_named_and_one_anonymous.rs:20:9
-   |
-LL | fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
-   |                            ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
-...
-LL |         &*x //~ ERROR explicit lifetime
-   |         ^^^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
deleted file mode 100644 (file)
index 817d7c8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21
-   |
-LL |                     other //~ ERROR explicit lifetime
-   |                     ^^^^^
-
-error[E0621]: explicit lifetime required in the type of `other`
-  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21
-   |
-LL |     fn bar(&self, other: Foo) -> Foo<'a> {
-   |                          --- help: add explicit lifetime `'a` to the type of `other`: `Foo<'a>`
-...
-LL |                     other //~ ERROR explicit lifetime
-   |                     ^^^^^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr
deleted file mode 100644 (file)
index a10c38a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
-   |
-LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
-   |                ^
-
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
-   |
-LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
-   |               ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
-LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
-   |                ^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr
deleted file mode 100644 (file)
index e33b89c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
-   |
-LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
-   |                           ^
-
-error[E0621]: explicit lifetime required in parameter type
-  --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
-   |
-LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
-   |                    --------------- help: add explicit lifetime `'a` to type: `(&'a i32, &'a i32)`
-LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
-   |                           ^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr
deleted file mode 100644 (file)
index a3b2c3f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
-   |
-LL |    if x > y { x } else { y } //~ ERROR explicit lifetime
-   |               ^
-
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
-   |
-LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
-   |               ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
-LL |    if x > y { x } else { y } //~ ERROR explicit lifetime
-   |               ^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr
deleted file mode 100644 (file)
index e13a710..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
-   |
-LL |     if true { &self.field } else { x } //~ ERROR explicit lifetime
-   |                                    ^
-
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
-   |
-LL |   fn foo<'a>(&'a self, x: &i32) -> &i32 {
-   |                           ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
-LL | 
-LL |     if true { &self.field } else { x } //~ ERROR explicit lifetime
-   |                                    ^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index 4ce3a613c315e84ad10bb79584c26957d3c1d870..4e3193ccbfd5cb4632ca466a1505dfb7c1f81c8d 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
-   |
-LL |         if x > y { x } else { y } //~ ERROR lifetime mismatch
-   |                    ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
    |
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr
deleted file mode 100644 (file)
index 5b4b28a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
-   |
-LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
-   |                           ^
-
-error[E0621]: explicit lifetime required in the type of `y`
-  --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
-   |
-LL | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-   |                           ---- help: add explicit lifetime `'a` to the type of `y`: `&'a i32`
-LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
-   |                           ^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index 272ae0b12519af7756bb36f662a0807a0defe2fa..3413203fa7f06291e8fbb15845dcb86a2e14ebc2 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
-   |
-LL |     x //~ ERROR lifetime mismatch
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
    |
index 2106546325b2de30cca7df15b051fafa43416345..239419967f6c1cfa3bf491478a666b00db071dd0 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
-   |
-LL |         if true { x } else { self } //~ ERROR lifetime mismatch
-   |                              ^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
    |
index a5fa83266a3db9d5eada3853bfdb7ea558cf201e..709d9f84db3f9d98a2aadac1d7a75756e2bece7f 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2a-push-one-existing-name-2.rs:16:12
-   |
-LL |     y.push(x); //~ ERROR explicit lifetime
-   |            ^
-
 error[E0621]: explicit lifetime required in the type of `x`
   --> $DIR/ex2a-push-one-existing-name-2.rs:16:5
    |
index c5f3510fa0ed26d3b22ed886e7180f1f26d355d8..1e608fe16e41361965f66ce487220dbc79893f44 100644 (file)
@@ -1,17 +1,12 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:5
    |
+LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+   |                                          -- help: add explicit lifetime `'a` to the type of `y`: `&'a T`
+...
 LL |     x.push(y); //~ ERROR explicit lifetime required
-   |            ^
-
-error[E0282]: type annotations needed
-  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:20:9
-   |
-LL | let x = baz;
-   |     -   ^^^ cannot infer type for `T`
-   |     |
-   |     consider giving `x` a type
+   |     ^^^^^^^^^ lifetime `'a` required
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0621`.
index 18a720f345d7f39511e8020129141efa9fb31358..cad0a3c6ac13df67d8a44c7fc8f8f876f7769ad4 100644 (file)
@@ -17,5 +17,4 @@ fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
     x.push(y); //~ ERROR explicit lifetime required
 }
 fn main() {
-let x = baz;
 }
index 294a9106619a0a1f70f1f72362b915549d423bd0..14194352093954719524b08628e239122ab5a2b3 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2a-push-one-existing-name.rs:16:12
-   |
-LL |     x.push(y); //~ ERROR explicit lifetime
-   |            ^
-
 error[E0621]: explicit lifetime required in the type of `y`
   --> $DIR/ex2a-push-one-existing-name.rs:16:5
    |
index b7c252cac9bc7dbf6b5d2823887719d1d5a1913c..fc5f02fbc721de7e468b38b3c1e50c91d9208351 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2b-push-no-existing-names.rs:16:12
-   |
-LL |     x.push(y); //~ ERROR lifetime mismatch
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex2b-push-no-existing-names.rs:16:5
    |
index c34278b4d9fa1ac90d6c12f49fdf79b2169fb976..a5053244dc1f0fd0bbcf00aac0680bb4501da539 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2c-push-inference-variable.rs:16:13
-   |
-LL |     let z = Ref { data: y.data };
-   |             ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex2c-push-inference-variable.rs:17:5
    |
index 3097d18e86c67feb855df2007a6b58f6aea1d7d8..361fb708d4013b81f6c41c5e6e2e8649347edae7 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2d-push-inference-variable-2.rs:17:13
-   |
-LL |     let b = Ref { data: y.data };
-   |             ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex2d-push-inference-variable-2.rs:18:5
    |
index ce0e9be300698ea2e52a0616256cb42e2516587c..5d0f07054dfed6c965f0cda0d2b3f481147ee187 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex2e-push-inference-variable-3.rs:17:13
-   |
-LL |     let b = Ref { data: y.data };
-   |             ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex2e-push-inference-variable-3.rs:18:5
    |
index c7f1a0ede3c1cf26b8c413a8ac0690430f62c9e0..017c3e977475ccab1b722002090ddf7bcb65d0de 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-2.rs:12:10
-   |
-LL |     *v = x; //~ ERROR lifetime mismatch
-   |          ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-2.rs:12:5
    |
index 09980e44c52d63b3ada0f2a6c59c004acbdff611..e1872dcf777ec9da06272ee75454fed1229fc165 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-3.rs:12:13
-   |
-LL |     z.push((x,y)); //~ ERROR lifetime mismatch
-   |             ^
-
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-3.rs:12:15
-   |
-LL |     z.push((x,y)); //~ ERROR lifetime mismatch
-   |               ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-3.rs:12:5
    |
index 618817fd57b31e9cc76e85c4d9e850f95cbcafc2..b8e1b483081bac4ed047b0cbd72cc73289a76a54 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
-   |
-LL |     x.b = y.b; //~ ERROR lifetime mismatch
-   |           ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:5
    |
index b4767afd4138abadd80eff532f99f614555b50f2..4b7352fe2249134e0ccd3a30b323f8f2aec04a53 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
-   |
-LL |     x.a = x.b; //~ ERROR lifetime mismatch
-   |           ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:5
    |
index e2fcbaa4c3c5507ab1c13a723012850b7dccbb2d..53a2fef4806713e8b46514553b555665b0f85c3c 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:11
-   |
-LL |     x.a = x.b; //~ ERROR lifetime mismatch
-   |           ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:5
    |
index aed0dcc1a67ea14ae48268c447dc09c80533c8f7..7f814b730fff538e83b6f28c0ad55adf72e3072a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:12
-   |
-LL |     x.push(y); //~ ERROR lifetime mismatch
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:5
    |
index 7790d37d1c40dafc2cd76843919e6bc89e0c7d8d..f38dceb331bfb12021f361dc224f3fe9d01b1027 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:12
-   |
-LL |     x.push(y); //~ ERROR lifetime mismatch
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:5
    |
index 79f1a8c0ccf7d559d29b6976123bcc3885abaeeb..39a7154c8e9555e29dcff7563f38c50b5d1bcb3c 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
-   |
-LL |     x.push(y); //~ ERROR lifetime mismatch
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:5
    |
index 459a93813a8cae1a53288821be9557d27640a539..d59480cefcc698a788a42884ce7fa2dd6f4c00e2 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-latebound-regions.rs:12:12
-   |
-LL |     x.push(y); //~ ERROR lifetime mismatch
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-latebound-regions.rs:12:5
    |
index 0bacd894e6e9a6c6e73497aae6b2b50b7d7d80cb..749b576092967e9553dd99172c1fe7a1a7b1fa60 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
-   |
-LL |     y = x.b; //~ ERROR lifetime mismatch
-   |         ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
    |
index f40c67b8d114c282f3186133714364981ae288eb..d098354d98393cb71bd246d6c1f4fee886fb1c48 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
-   |
-LL |     y.b = x; //~ ERROR lifetime mismatch
-   |           ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:5
    |
index f9168dcf5837bf5dd092b213668dbee1a7ab55eb..17a70aa85beeb5aa852692833ed8f5fce5d1a71d 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:11
-   |
-LL |     y.b = x; //~ ERROR lifetime mismatch
-   |           ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:5
    |
index c43f847723240a593b8c4f77f2c5c183b528abc4..2ebdedddc5075c9580af45ff1dd0dcf61699f695 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
-   |
-LL |     x.b = y; //~ ERROR lifetime mismatch
-   |           ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:5
    |
index 9680e8c2f69359a80339b47aac93aa3e8acbe5cb..898f997779d1db29e25074b5f94ebf045788fbf2 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
-   |
-LL |     x //~ ERROR lifetime mismatch
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
    |
index 6fbe8e982093e851aaae1b3e25e7d9218fd0e6cd..bdb9b306cdaea7c5433a6936b019c8cf0f2bb505 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
-   |
-LL |         if true { x } else { self } //~ ERROR lifetime mismatch
-   |                   ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
    |
index 2829ec35000439fbdffb276fdcbb610b57bbd618..2e4df170d6cd5936a2a5e9b0db21db2701746104 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:10
-   |
-LL |   y.push(z); //~ ERROR lifetime mismatch
-   |          ^
-
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3
    |
index 44d68df4b5590ad2e0f916abb16727ece809ed27..8d743608438ba06653ebd5d46d1b2a13d14b5bb6 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
-   |
-LL |         x.push(y); //~ ERROR lifetime mismatch
-   |                ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:9
    |
index 5d3c6f38ad808cb433765b56ca18de0cd4e10203..a2dc0e4bda3b797bdaa85c565a5a6855c8580445 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:10
-   |
-LL |   y.push(z); //~ ERROR lifetime mismatch
-   |          ^
-
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3
    |
index 6460e5d687ff0f752ad514c258cc0c09e9483104..0d674162eea05372e8cc3855f789edb9d554193f 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ex3-both-anon-regions.rs:12:12
-   |
-LL |     x.push(y); //~ ERROR lifetime mismatch
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/ex3-both-anon-regions.rs:12:5
    |
index 9f33f57f48a281aad0297646f125f26480aa68ae..55d6168e6e0085205d0044dca7e8f4ab517d8c7a 100644 (file)
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(bad_style)]
+#![deny(nonstandard_style)]
 #![allow(dead_code)]
 
 fn CamelCase() {} //~ ERROR should have a snake
 
-#[allow(bad_style)]
+#[allow(nonstandard_style)]
 mod test {
     fn CamelCase() {}
 
-    #[forbid(bad_style)]
+    #[forbid(nonstandard_style)]
     mod bad {
         fn CamelCase() {} //~ ERROR should have a snake
 
@@ -25,7 +25,7 @@ fn CamelCase() {} //~ ERROR should have a snake
     }
 
     mod warn {
-        #![warn(bad_style)]
+        #![warn(nonstandard_style)]
 
         fn CamelCase() {} //~ WARN should have a snake
 
index c1b15160bc501c345a9cb032b042363e9bb8c585..6b91ce5b93ca604ab9d28b5b7a816028ea96fe30 100644 (file)
@@ -7,9 +7,9 @@ LL | fn CamelCase() {} //~ ERROR should have a snake
 note: lint level defined here
   --> $DIR/lint-group-style.rs:11:9
    |
-LL | #![deny(bad_style)]
-   |         ^^^^^^^^^
-   = note: #[deny(non_snake_case)] implied by #[deny(bad_style)]
+LL | #![deny(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^
+   = note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)]
 
 error: function `CamelCase` should have a snake case name such as `camel_case`
   --> $DIR/lint-group-style.rs:22:9
@@ -20,9 +20,9 @@ LL |         fn CamelCase() {} //~ ERROR should have a snake
 note: lint level defined here
   --> $DIR/lint-group-style.rs:20:14
    |
-LL |     #[forbid(bad_style)]
-   |              ^^^^^^^^^
-   = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)]
+LL |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)]
 
 error: static variable `bad` should have an upper case name such as `BAD`
   --> $DIR/lint-group-style.rs:24:9
@@ -33,9 +33,9 @@ LL |         static bad: isize = 1; //~ ERROR should have an upper
 note: lint level defined here
   --> $DIR/lint-group-style.rs:20:14
    |
-LL |     #[forbid(bad_style)]
-   |              ^^^^^^^^^
-   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)]
+LL |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)]
 
 warning: function `CamelCase` should have a snake case name such as `camel_case`
   --> $DIR/lint-group-style.rs:30:9
@@ -46,9 +46,9 @@ LL |         fn CamelCase() {} //~ WARN should have a snake
 note: lint level defined here
   --> $DIR/lint-group-style.rs:28:17
    |
-LL |         #![warn(bad_style)]
-   |                 ^^^^^^^^^
-   = note: #[warn(non_snake_case)] implied by #[warn(bad_style)]
+LL |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_snake_case)] implied by #[warn(nonstandard_style)]
 
 warning: type `snake_case` should have a camel case name such as `SnakeCase`
   --> $DIR/lint-group-style.rs:32:9
@@ -59,9 +59,9 @@ LL |         struct snake_case; //~ WARN should have a camel
 note: lint level defined here
   --> $DIR/lint-group-style.rs:28:17
    |
-LL |         #![warn(bad_style)]
-   |                 ^^^^^^^^^
-   = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)]
+LL |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)]
 
 error: aborting due to 3 previous errors
 
index 97a976a493f80c90372d1a4e5602ee77c8812112..1e37ac0dc586c9b00ccbf25bc1463a15d7ba5487 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(bad_style, unused_variables)]
+#![allow(nonstandard_style, unused_variables)]
 #![deny(non_shorthand_field_patterns)]
 
 struct Foo {
index d72f307b46124f00bbebc1e0644e0b30155cbc81..23e98cc22fc3ae725b1ce257a6056edc61895f1f 100644 (file)
@@ -11,7 +11,7 @@
 // Forbidding a group (here, `unused`) overrules subsequent allowance of both
 // the group, and an individual lint in the group (here, `unused_variables`);
 // and, forbidding an individual lint (here, `non_snake_case`) overrules
-// subsequent allowance of a lint group containing it (here, `bad_style`). See
+// subsequent allowance of a lint group containing it (here, `nonstandard_style`). See
 // Issue #42873.
 
 #![forbid(unused, non_snake_case)]
@@ -22,7 +22,7 @@ fn foo() {}
 #[allow(unused)] //~ ERROR overruled
 fn bar() {}
 
-#[allow(bad_style)] //~ ERROR overruled
+#[allow(nonstandard_style)] //~ ERROR overruled
 fn main() {
     println!("hello forbidden world")
 }
index e49dcd4a2d19d0a39f5a795b14f965c063bf3946..c011b49eaee7ded8c8863ca47fdd384f83edba1d 100644 (file)
@@ -16,14 +16,14 @@ LL | #![forbid(unused, non_snake_case)]
 LL | #[allow(unused)] //~ ERROR overruled
    |         ^^^^^^ overruled by previous forbid
 
-error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
   --> $DIR/outer-forbid.rs:25:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
 ...
-LL | #[allow(bad_style)] //~ ERROR overruled
-   |         ^^^^^^^^^ overruled by previous forbid
+LL | #[allow(nonstandard_style)] //~ ERROR overruled
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
 
 error: aborting due to 3 previous errors
 
index 4304c96197f962c5b00289fe0ec7d70a37a7ce0d..a7727c69e4c0cfb2ae2e730d5961e22471996afb 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: --test -D unnameable_test_functions
+// compile-flags: --test -D unnameable_test_items
 
 #[test]
 fn foo() {
-    #[test] //~ ERROR cannot test inner function [unnameable_test_functions]
+    #[test] //~ ERROR cannot test inner items [unnameable_test_items]
     fn bar() {}
     bar();
 }
@@ -20,7 +20,7 @@ fn bar() {}
 mod x {
     #[test]
     fn foo() {
-        #[test] //~ ERROR cannot test inner function [unnameable_test_functions]
+        #[test] //~ ERROR cannot test inner items [unnameable_test_items]
         fn bar() {}
         bar();
     }
index 37f0c161036ee0f287fc25caf96c01ad7740ef33..182fb31a9aa3707853f01412cd25f618e00dc510 100644 (file)
@@ -1,15 +1,15 @@
-error: cannot test inner function
+error: cannot test inner items
   --> $DIR/test-inner-fn.rs:15:5
    |
-LL |     #[test] //~ ERROR cannot test inner function [unnameable_test_functions]
+LL |     #[test] //~ ERROR cannot test inner items [unnameable_test_items]
    |     ^^^^^^^
    |
-   = note: requested on the command line with `-D unnameable-test-functions`
+   = note: requested on the command line with `-D unnameable-test-items`
 
-error: cannot test inner function
+error: cannot test inner items
   --> $DIR/test-inner-fn.rs:23:9
    |
-LL |         #[test] //~ ERROR cannot test inner function [unnameable_test_functions]
+LL |         #[test] //~ ERROR cannot test inner items [unnameable_test_items]
    |         ^^^^^^^
 
 error: aborting due to 2 previous errors
index d3f5cdca1759e47a04642f7a6ff7ef97f3b72f98..2405e30a8cd005db3a69bab6c1b20eedac7bbcc1 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/lub-if.rs:38:9
-   |
-LL |         s  //~ ERROR E0312
-   |         ^
-
-warning: not reporting region error due to nll
-  --> $DIR/lub-if.rs:45:9
-   |
-LL |         s  //~ ERROR E0312
-   |         ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/lub-if.rs:38:9
    |
index bbddcc7d8b36a4b77262658ab4483953c01bb8f8..5a39dd14e4c42f51b94c46605e5a80bd60ea360f 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/lub-match.rs:40:13
-   |
-LL |             s //~ ERROR E0312
-   |             ^
-
-warning: not reporting region error due to nll
-  --> $DIR/lub-match.rs:49:13
-   |
-LL |             s //~ ERROR E0312
-   |             ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/lub-match.rs:40:13
    |
index a07cc834411732da96fd7dc9e87df1bc72ce64e2..fefc6ff6ca615559862dfa7f8188f7d30bd499df 100644 (file)
@@ -13,3 +13,5 @@
 #[allow(unused_extern_crates)]
 #[macro_use(foo(bar))]  //~ ERROR bad macro import
 extern crate std;
+
+fn main() {}
index 19a8c7c0382d13357ccae6e2d294369b06b92faa..308fb6c76e1b9444d9bc862235281e6f7c4bed16 100644 (file)
@@ -4,11 +4,6 @@ error[E0466]: bad macro import
 LL | #[macro_use(foo(bar))]  //~ ERROR bad macro import
    |             ^^^^^^^^
 
-error[E0601]: `main` function not found in crate `macro_use_bad_args_1`
-   |
-   = note: consider adding a `main` function to `$DIR/macro-use-bad-args-1.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0466, E0601.
-For more information about an error, try `rustc --explain E0466`.
+For more information about this error, try `rustc --explain E0466`.
index 89004f16897742944693a75edb034c449fab82bb..81352cf2e427de855c7972fb4cd9adcedf1e08de 100644 (file)
@@ -13,3 +13,5 @@
 #[allow(unused_extern_crates)]
 #[macro_use(foo="bar")]  //~ ERROR bad macro import
 extern crate std;
+
+fn main() {}
index 0ac18201d791e0a49eb02ded907db51071b2339a..62e3c22fab3ec5b2e256dc49a280d233b60fc9c3 100644 (file)
@@ -4,11 +4,6 @@ error[E0466]: bad macro import
 LL | #[macro_use(foo="bar")]  //~ ERROR bad macro import
    |             ^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `macro_use_bad_args_2`
-   |
-   = note: consider adding a `main` function to `$DIR/macro-use-bad-args-2.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0466, E0601.
-For more information about an error, try `rustc --explain E0466`.
+For more information about this error, try `rustc --explain E0466`.
index 40dd9e25a17392c4b19d000c39c656a1ee5c526d..d5167bbaeab07233eae4bc69d1a7b3a04f2b3636 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/match-ref-mut-invariance.rs:20:37
-   |
-LL |         match self.0 { ref mut x => x } //~ ERROR mismatched types
-   |                                     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/match-ref-mut-invariance.rs:20:9
    |
index 5314f37a3f88cad4fb428597b9ebe3986b626411..54915865d8899a0526fa25c98f9b4294659c1286 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/match-ref-mut-let-invariance.rs:21:9
-   |
-LL |         x //~ ERROR mismatched types
-   |         ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/match-ref-mut-let-invariance.rs:21:9
    |
index aac37289bb74952ddce176abc833629fdab68a0b..2378cccf56f76c34e8590116e9755cde779f3adf 100644 (file)
@@ -14,3 +14,5 @@ fn hd<U>(v: Vec<U> ) -> U {
 
     return hd1(v);
 }
+
+fn main() {}
index 93b934f610f8ca65c6ff711e552f1d12a9b60708..58b6cd18989f2171db70f3c272bfac407acdf64b 100644 (file)
@@ -18,11 +18,6 @@ LL |     fn hd1(w: [U]) -> U { return w[0]; }
    |        |
    |        help: try using a local type parameter instead: `hd1<U>`
 
-error[E0601]: `main` function not found in crate `nested_ty_params`
-   |
-   = note: consider adding a `main` function to `$DIR/nested-ty-params.rs`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0401, E0601.
-For more information about an error, try `rustc --explain E0401`.
+For more information about this error, try `rustc --explain E0401`.
index 78208d6d7db7d0c0f7df7bab15af4735dd88333f..3c417493bc5791157f7abb29f4a5d48fa0827a58 100644 (file)
@@ -35,7 +35,6 @@ fn test() {
         let y = 22;
         let mut closure = expect_sig(|p, y| *p = y);
         //~^ ERROR
-        //~| WARNING not reporting region error due to nll
         closure(&mut p, &y);
     }
 
index 862d1f0b179c0e34a9e412ede8be5fe019efc35a..72b60188c4c6c8822405b99a2d022bafe3b53dc4 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/escape-argument-callee.rs:36:50
-   |
-LL |         let mut closure = expect_sig(|p, y| *p = y);
-   |                                                  ^
-
 note: No external requirements
   --> $DIR/escape-argument-callee.rs:36:38
    |
index b879f9a33986d0b8c184a73f28d9378f38fa3aaa..4f2ec80b0d2515c2f1f460822739c52713fc7a90 100644 (file)
@@ -53,7 +53,6 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell
         |_outlives1, _outlives2, _outlives3, x, y| {
             // Only works if 'x: 'y:
             let p = x.get();
-            //~^ WARN not reporting region error due to nll
             demand_y(x, y, p) //~ ERROR
         },
     );
index 72b7104b99dd3c5a3dcb0d4ebc155d8de5adfcb4..892910686433a584d081d4300a81891a86c7e708 100644 (file)
@@ -1,16 +1,9 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
-   |
-LL |             let p = x.get();
-   |                     ^^^^^^^
-
 note: No external requirements
   --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
    |
 LL | /         |_outlives1, _outlives2, _outlives3, x, y| {
 LL | |             // Only works if 'x: 'y:
 LL | |             let p = x.get();
-LL | |             //~^ WARN not reporting region error due to nll
 LL | |             demand_y(x, y, p) //~ ERROR
 LL | |         },
    | |_________^
@@ -21,7 +14,7 @@ LL | |         },
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:56:13
    |
 LL |         |_outlives1, _outlives2, _outlives3, x, y| {
    |          ----------              ---------- has type `std::cell::Cell<&'2 &u32>`
index d79be8b83c61fa6156980341eaeae4f106d41f4a..700c0dffb70115e70d6dfa5969307258414c7c91 100644 (file)
@@ -54,7 +54,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
-        demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+        demand_y(x, y, x.get())
     });
 }
 
index fe67ca0293e06bed86d4dd0d5931afba43c0e948..1ff9374c2126778b887f18f1d9606ea3a0f6ad2f 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-approximated-ref.rs:57:9
-   |
-LL |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
-
 note: External requirements
   --> $DIR/propagate-approximated-ref.rs:53:47
    |
@@ -12,7 +6,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+LL | |         demand_y(x, y, x.get())
 LL | |     });
    | |_____^
    |
@@ -48,7 +42,7 @@ LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+LL | |         demand_y(x, y, x.get())
 LL | |     });
    | |______^ argument requires that `'a` must outlive `'b`
 
index a8ab41cebacced2fd79e17c78990ff081618567a..54f9453797e6d410c35247784e5f86a7a91b1424 100644 (file)
@@ -29,7 +29,6 @@ fn case1() {
     let a = 0;
     let cell = Cell::new(&a);
     foo(cell, |cell_a, cell_x| {
-        //~^ WARNING not reporting region error due to nll
         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
         //~^ ERROR
     })
index 43c39dee2448a1c5793579421402015233dd34b2..c855cee3c606ae9e72326b67bc5f07f59ae734a0 100644 (file)
@@ -1,15 +1,8 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:5
-   |
-LL |     foo(cell, |cell_a, cell_x| {
-   |     ^^^
-
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15
    |
 LL |       foo(cell, |cell_a, cell_x| {
    |  _______________^
-LL | |         //~^ WARNING not reporting region error due to nll
 LL | |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
 LL | |         //~^ ERROR
 LL | |     })
@@ -21,13 +14,12 @@ LL | |     })
            ]
 
 error: borrowed data escapes outside of closure
-  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:32:9
    |
 LL |     foo(cell, |cell_a, cell_x| {
    |                ------  ------ `cell_x` is a reference that is only valid in the closure body
    |                |
    |                `cell_a` is declared here, outside of the closure body
-LL |         //~^ WARNING not reporting region error due to nll
 LL |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
 
@@ -46,7 +38,7 @@ LL | | }
    = note: defining type: DefId(0/0:5 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs []
 
 note: External requirements
-  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:46:15
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:45:15
    |
 LL |       foo(cell, |cell_a, cell_x| {
    |  _______________^
@@ -62,7 +54,7 @@ LL | |     })
    = note: where '_#1r: '_#0r
 
 note: No external requirements
-  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:39:1
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:38:1
    |
 LL | / fn case2() {
 LL | |     let a = 0;
@@ -76,7 +68,7 @@ LL | | }
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs []
 
 error[E0597]: `a` does not live long enough
-  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:41:26
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:40:26
    |
 LL |     let cell = Cell::new(&a);
    |                          ^^ borrowed value does not live long enough
index 26faccdde71aee990210966ee6eba507cc3dcb5c..e32a4395f88e1e317721e9833191cdd5cfbbe85b 100644 (file)
@@ -46,7 +46,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR
 
         // Only works if 'x: 'y:
-        demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+        demand_y(x, y, x.get())
     });
 }
 
index c3bbf1035dbc574081c9d1a7d093606a5c1b54fa..0d4793563048410014301e94fa2aa0c12fe92d89 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:49:9
-   |
-LL |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
-
 note: External requirements
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
    |
@@ -12,7 +6,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+LL | |         demand_y(x, y, x.get())
 LL | |     });
    | |_____^
    |
@@ -46,7 +40,7 @@ LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+LL | |         demand_y(x, y, x.get())
 LL | |     });
    | |______^ `cell_a` escapes the function body here
 
index 703d60371cdfc43f74cd8aab05859b243a6e9c2e..0334f9ffd86fcc67872c26bb2312903e4745b755 100644 (file)
@@ -49,7 +49,6 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ WARNING not reporting region error due to nll
     });
 }
 
index 9f259e2dee5904616ae14b850d277e817d93f8d6..88743169fcbeeb1174c4e31fe56c004ff8c6d879 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:51:9
-   |
-LL |         demand_y(x, y, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
-
 note: External requirements
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
    |
@@ -12,7 +6,6 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
    | |_____^
    |
@@ -30,7 +23,7 @@ LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
 LL | |         //~^ ERROR
 LL | |         // Only works if 'x: 'y:
-...  |
+LL | |         demand_y(x, y, x.get())
 LL | |     });
 LL | | }
    | |_^
@@ -46,7 +39,6 @@ LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
 LL | |         //~^ ERROR
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
    | |______^ `cell_a` escapes the function body here
 
index bf24557398d161d3e696c945249e45503f094f8c..75641943f2fac9bda57f92827d686f46114251a9 100644 (file)
@@ -47,7 +47,7 @@ fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
         //~^ ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
-        demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
+        demand_y(outlives1, outlives2, x.get())
     });
 }
 
index ed1fc6e1a712fe5bcef02c58e7d5657be2c098a3..71dbc412fef4cde59c81dca0e81815a23328a07a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-approximated-val.rs:50:9
-   |
-LL |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 note: External requirements
   --> $DIR/propagate-approximated-val.rs:46:45
    |
@@ -12,7 +6,7 @@ LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y|
 LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
+LL | |         demand_y(outlives1, outlives2, x.get())
 LL | |     });
    | |_____^
    |
@@ -48,7 +42,7 @@ LL | /     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y|
 LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
+LL | |         demand_y(outlives1, outlives2, x.get())
 LL | |     });
    | |______^ argument requires that `'a` must outlive `'b`
 
index 0888b1380e69e79c8f9922e7c58eb74308a146b7..d189385213fa11aee94ee2c50d8379075fd9203e 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-despite-same-free-region.rs:54:21
-   |
-LL |             let p = x.get();
-   |                     ^^^^^^^
-
 note: External requirements
   --> $DIR/propagate-despite-same-free-region.rs:52:9
    |
index 4b1f5231b3e878bb4f49510a2352ff24873c89c1..31f38abf2802230a861aeea0f0c8ee64c6b9a0a6 100644 (file)
@@ -45,8 +45,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ WARN not reporting region error due to nll
-        //~| ERROR
+        //~^ ERROR
     });
 }
 
index cd5e6f29f5f480cc2862f714777b826c80527414..a63c6b1670837ccfc4b48b8ec292eb84fc48b5a6 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
-   |
-LL |         demand_y(x, y, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
-
 note: No external requirements
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47
    |
@@ -11,8 +5,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |  _______________________________________________^
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARN not reporting region error due to nll
-LL | |         //~| ERROR
+LL | |         //~^ ERROR
 LL | |     });
    | |_____^
    |
@@ -39,7 +32,7 @@ LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-...  |
+LL | |         //~^ ERROR
 LL | |     });
 LL | | }
    | |_^
index 62a20c1bfe76ef5893aed0c59338b6e420375fdf..a4ff408b76625cd961854e165576de8cfba0e3ee 100644 (file)
@@ -49,8 +49,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ WARN not reporting region error due to nll
-        //~| ERROR
+        //~^ ERROR
     });
 }
 
index 2176575e0aa128e7067afdad22b870fd0edbcc80..67510a5a81f11f9ffd5fffbd7eccb78860d3873a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
-   |
-LL |         demand_y(x, y, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
-
 note: No external requirements
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47
    |
@@ -11,8 +5,7 @@ LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x,
    |  _______________________________________________^
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARN not reporting region error due to nll
-LL | |         //~| ERROR
+LL | |         //~^ ERROR
 LL | |     });
    | |_____^
    |
@@ -39,7 +32,7 @@ LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-...  |
+LL | |         //~^ ERROR
 LL | |     });
 LL | | }
    | |_^
index 7baf24f88f8fa419b35643e9304b973decd1039e..a6542d73fdb557244474007c16330996c8a4282f 100644 (file)
@@ -53,7 +53,6 @@ fn supply<'a, T>(value: T)
         // The latter does not hold.
 
         require(value);
-        //~^ WARNING not reporting region error due to nll
     });
 }
 
index 8f8a99df5f0529dcef540ee13de8b348d85d654b..fda9743fb6b9beeea309f181b46a5a38c4ad8355 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/propagate-from-trait-match.rs:55:9
-   |
-LL |         require(value);
-   |         ^^^^^^^
-
 note: External requirements
   --> $DIR/propagate-from-trait-match.rs:42:36
    |
@@ -13,7 +7,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |
 LL | |         // This function call requires that
 ...  |
-LL | |         //~^ WARNING not reporting region error due to nll
+LL | |         require(value);
 LL | |     });
    | |_____^
    |
@@ -52,7 +46,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |
 LL | |         // This function call requires that
 ...  |
-LL | |         //~^ WARNING not reporting region error due to nll
+LL | |         require(value);
 LL | |     });
    | |_____^
    |
index a6b2e531ac28fcf9cb0e4d75a41cef1d921aafa5..4382be05f031b8db9a0ff71e8ad1f03c7c2a958e 100644 (file)
@@ -17,8 +17,7 @@
 
 fn foo(x: &u32) -> &'static u32 {
     &*x
-        //~^ WARN not reporting region error due to nll
-        //~| ERROR explicit lifetime required in the type of `x`
+        //~^ ERROR explicit lifetime required in the type of `x`
 }
 
 fn main() { }
index a019a7224c630da316deac9de44ab2b7cd8321f8..9962e801653b3011b13c858aa0310ee8ba3d0974 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
-   |
-LL |     &*x
-   |     ^^^
-
 error[E0621]: explicit lifetime required in the type of `x`
   --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
    |
index b5e8c95bc13b7c0601021185f6da26584222ee29..d2dcfd86ac096641c40023dbf3555ef76a4c99e4 100644 (file)
@@ -17,8 +17,7 @@
 
 fn foo<'a>(x: &'a u32) -> &'static u32 {
     &*x
-        //~^ WARN not reporting region error due to nll
-        //~| ERROR
+        //~^ ERROR
 }
 
 fn main() { }
index 00d79a9ed7e844b0ddf755b0f1d3eeeff221ea0a..ff36017c3d0e581f7b3eade1df69daa4b4635426 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
-   |
-LL |     &*x
-   |     ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
    |
index a883e7b1994737ce4a97dacfd16506ebfd2df73c..d793b0ba0be58fecd0466cef2e8a07e0c1af450f 100644 (file)
@@ -17,8 +17,7 @@
 
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
     &*x
-        //~^ WARN not reporting region error due to nll
-        //~| ERROR unsatisfied lifetime constraints
+        //~^ ERROR unsatisfied lifetime constraints
 }
 
 fn main() { }
index bcdae17c47ce079baf8281dad4123b527e1ed254..2392e75538d37948e05b6d01c39277415604f7d9 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
-   |
-LL |     &*x
-   |     ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
    |
index d88729d04d95bb733c777a33d89af9b8fdc52607..d45b7182305a8a1d944c8d02a67b0c1a1f0c4693 100644 (file)
@@ -19,8 +19,7 @@
 #[rustc_regions]
 fn test() {
     expect_sig(|a, b| b); // ought to return `a`
-    //~^ WARN not reporting region error due to nll
-    //~| ERROR
+    //~^ ERROR
 }
 
 fn expect_sig<F>(f: F) -> F
index 8dc10de702f7aadf52d15bc339e45cda1991db16..d3eb3d46d21e78893d9ba0f8fafa7ab797fbc7f9 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/return-wrong-bound-region.rs:21:23
-   |
-LL |     expect_sig(|a, b| b); // ought to return `a`
-   |                       ^
-
 note: No external requirements
   --> $DIR/return-wrong-bound-region.rs:21:16
    |
@@ -29,8 +23,7 @@ note: No external requirements
    |
 LL | / fn test() {
 LL | |     expect_sig(|a, b| b); // ought to return `a`
-LL | |     //~^ WARN not reporting region error due to nll
-LL | |     //~| ERROR
+LL | |     //~^ ERROR
 LL | | }
    | |_^
    |
index a111699c3f70de36cc4a01faacf2bda4bfb4e833..577fdd7b548645109cee27ce9abaca76670374d5 100644 (file)
@@ -15,8 +15,7 @@
 fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
     let g: fn(_, _) -> _ = |_x, y| y;
     g
-    //~^ WARNING not reporting region error due to nll
-    //~^^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR unsatisfied lifetime constraints
 }
 
 fn main() {}
index 6805dbf6f30550c4dcfc28240967ad129eeeb079..6433668031b9806b7c27758a3f92de67c5d3433b 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/mir_check_cast_closure.rs:17:5
-   |
-LL |     g
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/mir_check_cast_closure.rs:17:5
    |
index 3a530c1e7473df4f19eac614bd36d5566662782e..93f10b96c222097c9ea52ab7fad7551258cb8a25 100644 (file)
@@ -44,7 +44,6 @@ fn bar<'a>(x: &'a u32) -> &'static u32 {
     // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2`
     // as part of checking the `ReifyFnPointer`.
     let f: fn(_) -> _ = foo;
-    //~^ WARNING not reporting region error due to nll
     f(x)
     //~^ ERROR
 }
index c6e5fb397b9e6d09460b922eccf3de90240dd385..fdb71b17287d9a8b57f243dd93310c4cf448cdbc 100644 (file)
@@ -1,11 +1,5 @@
-warning: not reporting region error due to nll
-  --> $DIR/mir_check_cast_reify.rs:46:25
-   |
-LL |     let f: fn(_) -> _ = foo;
-   |                         ^^^
-
 error: unsatisfied lifetime constraints
-  --> $DIR/mir_check_cast_reify.rs:48:5
+  --> $DIR/mir_check_cast_reify.rs:47:5
    |
 LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
index 4a840da028d815b4896d15e12f4d5f27887fd51b..71dcfc8886cc55ee3ad6ece3a7d130abe1ef3181 100644 (file)
@@ -16,7 +16,6 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
     // Here the NLL checker must relate the types in `f` to the types
     // in `g`. These are related via the `UnsafeFnPointer` cast.
     let g: unsafe fn(_) -> _ = f;
-    //~^ WARNING not reporting region error due to nll
     unsafe { g(input) }
     //~^ ERROR
 }
index e8315d341a7f3cce9a4cb2ff89d22c86fb60621d..c14fb93a525e5bd4ef7de01384362c218561fbbb 100644 (file)
@@ -1,11 +1,5 @@
-warning: not reporting region error due to nll
-  --> $DIR/mir_check_cast_unsafe_fn.rs:18:32
-   |
-LL |     let g: unsafe fn(_) -> _ = f;
-   |                                ^
-
 error: unsatisfied lifetime constraints
-  --> $DIR/mir_check_cast_unsafe_fn.rs:20:14
+  --> $DIR/mir_check_cast_unsafe_fn.rs:19:14
    |
 LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
index 7ef6572a5d79973316e20a878a5e3389995e23e2..b1889b8aab2fe979bea8a69163a052ec3cf4edca 100644 (file)
@@ -17,7 +17,6 @@
 fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
     x
     //~^ ERROR unsatisfied lifetime constraints
-    //~| WARNING not reporting region error due to nll
 }
 
 fn main() {}
index a965e611f992a42d5bf00e48b9fe1978dd98a8ac..526dfb6013386b222d020be4eb648aafe7100a97 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/mir_check_cast_unsize.rs:18:5
-   |
-LL |     x
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/mir_check_cast_unsize.rs:18:5
    |
index f21127064d4c2ee1880b2e22300242ea85d55fa8..3d9b194484565b0401b428e04e9b8c46acbac89a 100644 (file)
@@ -19,8 +19,7 @@ impl<'a, T> Foo<'a> for T { }
 
 fn foo<'a, T>(x: &T) -> impl Foo<'a> {
     x
-        //~^ WARNING not reporting region error due to nll
-        //~| ERROR explicit lifetime required in the type of `x` [E0621]
+        //~^ ERROR explicit lifetime required in the type of `x` [E0621]
 }
 
 fn main() {}
index a4f0e53386f9f045016f90b53116a723782ef935..7cf24a1967701b865520e21df594b4933dfaefe8 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/impl-trait-captures.rs:21:5
-   |
-LL |     x
-   |     ^
-
 error[E0621]: explicit lifetime required in the type of `x`
   --> $DIR/impl-trait-captures.rs:21:5
    |
index 182e11da082f8d367afccd1b33a8e7784caf196a..4366636589223fc3808100311e8536f5b59cc5f1 100644 (file)
@@ -15,7 +15,6 @@
 use std::fmt::Debug;
 
 fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ WARNING not reporting region error due to nll
 where
     T: Debug,
 {
@@ -31,7 +30,6 @@ fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
 }
 
 fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ WARNING not reporting region error due to nll
 where
     T: 'b + Debug,
 {
index 50b80282e6241daae24f6a5e1093ab0344359f4f..05b674f8a9db5207a731cd247a25ac46a9966697 100644 (file)
@@ -1,17 +1,5 @@
-warning: not reporting region error due to nll
-  --> $DIR/impl-trait-outlives.rs:17:35
-   |
-LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-   |                                   ^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/impl-trait-outlives.rs:33:42
-   |
-LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-   |                                          ^^^^^^^^^^^^^^^
-
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:22:5
+  --> $DIR/impl-trait-outlives.rs:21:5
    |
 LL |     x
    |     ^
@@ -19,7 +7,7 @@ LL |     x
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:38:5
+  --> $DIR/impl-trait-outlives.rs:36:5
    |
 LL |     x
    |     ^
index d8f077467d9fcfca2bb4f030aa91974c7a8ec8df..1509ac8abd93d153edb942bd451a52e1302ed693 100644 (file)
@@ -43,8 +43,7 @@ fn invoke1<'a, T>(x: Cell<&'a Option<T>>)
 #[rustc_errors]
 fn generic2<T: Iterator>(value: T) {
     twice(value, |value_ref, item| invoke2(value_ref, item));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn invoke2<'a, T, U>(a: &T, b: Cell<&'a Option<U>>)
index 0a2bd3247655ae019783391c7b618567e64ffd21..17de9f79e3231d978932406fc7be993dc25a92f5 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/projection-implied-bounds.rs:45:36
-   |
-LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
-   |                                    ^^^^^^^
-
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/projection-implied-bounds.rs:45:18
    |
index 4767b75d89c1aab8517287f772c082b6e074295c..d61bbf27809dc8b07bcba076805d397cc3dd8583 100644 (file)
@@ -33,8 +33,7 @@ fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
     T: Iterator,
 {
     with_signature(x, |mut y| Box::new(y.next()))
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
 #[rustc_regions]
@@ -51,8 +50,7 @@ fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
     T: 'b + Iterator,
 {
     with_signature(x, |mut y| Box::new(y.next()))
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
 #[rustc_regions]
index 6d2170729ffb9f9db5f8db532bfbdf92710f3819..61e9794b76e2e88fccbbcc49d221283586acf12c 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-closure.rs:35:31
-   |
-LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                               ^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-closure.rs:53:31
-   |
-LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                               ^^^^^^^^^^^^^^^^^^
-
 note: External requirements
   --> $DIR/projection-no-regions-closure.rs:35:23
    |
@@ -32,8 +20,8 @@ LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
 LL | |     T: Iterator,
 LL | | {
-...  |
-LL | |     //~| ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+LL | |     with_signature(x, |mut y| Box::new(y.next()))
+LL | |     //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 LL | | }
    | |_^
    |
@@ -51,7 +39,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:45:23
+  --> $DIR/projection-no-regions-closure.rs:44:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +54,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:41:1
+  --> $DIR/projection-no-regions-closure.rs:40:1
    |
 LL | / fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -82,7 +70,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:53:23
+  --> $DIR/projection-no-regions-closure.rs:52:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -98,14 +86,14 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:49:1
+  --> $DIR/projection-no-regions-closure.rs:48:1
    |
 LL | / fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
 LL | |     T: 'b + Iterator,
 LL | | {
-...  |
-LL | |     //~| ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+LL | |     with_signature(x, |mut y| Box::new(y.next()))
+LL | |     //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 LL | | }
    | |_^
    |
@@ -116,7 +104,7 @@ LL | | }
            ]
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:53:23
+  --> $DIR/projection-no-regions-closure.rs:52:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -124,7 +112,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:64:23
+  --> $DIR/projection-no-regions-closure.rs:62:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +128,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:59:1
+  --> $DIR/projection-no-regions-closure.rs:57:1
    |
 LL | / fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
index dea2daf7e8eeb9f40a9fea46854707c1e1ee9bc5..286aa6ca6e0333f72fcef359afc4b9a9f9374789 100644 (file)
@@ -21,8 +21,7 @@ fn no_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a>
     T: Iterator,
 {
     Box::new(x.next())
-    //~^ WARNING not reporting region error due to nll
-    //~| the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
 fn correct_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a>
@@ -37,8 +36,7 @@ fn wrong_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a>
     T: 'b + Iterator,
 {
     Box::new(x.next())
-    //~^ WARNING not reporting region error due to nll
-    //~| the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
 }
 
 fn outlives_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a>
index 3199ec151335dbc08ea55ab622af0e1def56f3ad..5f365557ae2589a3ef05b3d1529b86ad4fada56d 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-fn.rs:23:5
-   |
-LL |     Box::new(x.next())
-   |     ^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-fn.rs:39:5
-   |
-LL |     Box::new(x.next())
-   |     ^^^^^^^^^^^^^^^^^^
-
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
   --> $DIR/projection-no-regions-fn.rs:23:5
    |
@@ -19,7 +7,7 @@ LL |     Box::new(x.next())
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-fn.rs:39:5
+  --> $DIR/projection-no-regions-fn.rs:38:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
index 0a8801a3c4d6d1ad9c3098d700563059f4ff558a..995c4d6dc8133c398350f55e3e9aa462ce20d1d1 100644 (file)
@@ -53,8 +53,7 @@ fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
     //~| ERROR
 }
 
@@ -65,8 +64,7 @@ fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     'a: 'a,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
     //~| ERROR
 }
 
@@ -87,8 +85,7 @@ fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     // can do better here with a more involved verification step.
 
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
     //~| ERROR
 }
 
index 2b0e682f85161e3c0e90be2f09a44bc8ed597869..918cf53cf36fa6c176b4dd104fc8d9c6246c2898 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:55:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:67:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:89:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:55:29
    |
@@ -69,7 +51,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:67:29
+  --> $DIR/projection-one-region-closure.rs:66:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +68,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:62:1
+  --> $DIR/projection-one-region-closure.rs:61:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -104,7 +86,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:67:5
+  --> $DIR/projection-one-region-closure.rs:66:5
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -115,7 +97,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:67:29
+  --> $DIR/projection-one-region-closure.rs:66:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -123,7 +105,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:89:29
+  --> $DIR/projection-one-region-closure.rs:87:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +122,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:74:1
+  --> $DIR/projection-one-region-closure.rs:72:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -158,7 +140,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:89:5
+  --> $DIR/projection-one-region-closure.rs:87:5
    |
 LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                        --  -- lifetime `'b` defined here
@@ -169,7 +151,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:89:29
+  --> $DIR/projection-one-region-closure.rs:87:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -177,7 +159,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:102:29
+  --> $DIR/projection-one-region-closure.rs:99:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -194,7 +176,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:96:1
+  --> $DIR/projection-one-region-closure.rs:93:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
index 6317d6eca1f1de29a400aa1e0dd17a5a00fe6b85..923faadc29618703cf7da8b8eb415f6e9f685406 100644 (file)
@@ -45,8 +45,7 @@ fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR
+    //~^ ERROR
 }
 
 #[rustc_regions]
@@ -56,8 +55,7 @@ fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     'a: 'a,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR
+    //~^ ERROR
 }
 
 #[rustc_regions]
@@ -77,8 +75,7 @@ fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     // can do better here with a more involved verification step.
 
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR
+    //~^ ERROR
 }
 
 #[rustc_regions]
index 739bde4a481c57b1208252190af701dd207e8a3a..ab1ad42f2a97ee83c9b285e487d22cc8fac751b4 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:58:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:79:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
    |
@@ -38,8 +20,8 @@ LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b>,
 LL | | {
-...  |
-LL | |     //~| ERROR
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | |     //~^ ERROR
 LL | | }
    | |_^
    |
@@ -60,7 +42,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:58:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:57:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,14 +58,14 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:53:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:52:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b>,
 LL | |     'a: 'a,
 ...  |
-LL | |     //~| ERROR
+LL | |     //~^ ERROR
 LL | | }
    | |_^
    |
@@ -94,7 +76,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:58:5
+  --> $DIR/projection-one-region-trait-bound-closure.rs:57:5
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -105,7 +87,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:79:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:77:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -121,14 +103,14 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:64:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:62:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b>,
 LL | |     T::AssocType: 'a,
 ...  |
-LL | |     //~| ERROR
+LL | |     //~^ ERROR
 LL | | }
    | |_^
    |
@@ -139,7 +121,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:79:5
+  --> $DIR/projection-one-region-trait-bound-closure.rs:77:5
    |
 LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                        --  -- lifetime `'b` defined here
@@ -150,7 +132,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:90:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:87:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +148,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:85:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:82:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -184,7 +166,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:102:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:99:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -199,7 +181,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:94:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:91:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
index 4e51a2bedc8c57d00ae0dbb66d2f8b725a5d31d7..72c1a631396be00d66611a10161594a483b571b3 100644 (file)
@@ -46,8 +46,7 @@ fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b, 'c>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
+    //~^ ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
 }
 
 #[rustc_regions]
@@ -57,8 +56,7 @@ fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
     'a: 'a,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
+    //~^ ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
 }
 
 #[rustc_regions]
@@ -78,8 +76,7 @@ fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
     // can do better here with a more involved verification step.
 
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
+    //~^ ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
 }
 
 #[rustc_regions]
@@ -106,8 +103,7 @@ fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
     T: Anything<'b, 'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR
+    //~^ ERROR
 }
 
 #[rustc_regions]
index 6838e0f3b3d01505b3cc6be6855f8382825f0152..9cabd29b12dc4fa86250d62068af071472d81d4a 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:59:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:80:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:108:39
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^
-
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
    |
@@ -45,8 +21,8 @@ LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b, 'c>,
 LL | | {
-...  |
-LL | |     //~| ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | |     //~^ ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
 LL | | }
    | |_^
    |
@@ -65,7 +41,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:58:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,14 +58,14 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:54:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:53:1
    |
 LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b, 'c>,
 LL | |     'a: 'a,
 ...  |
-LL | |     //~| ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
+LL | |     //~^ ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
 LL | | }
    | |_^
    |
@@ -101,7 +77,7 @@ LL | | }
            ]
 
 error[E0309]: the associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:58:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -109,7 +85,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#7r, '_#8r>>::AssocType: ReEarlyBound(0, 'a)`...
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:78:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -126,14 +102,14 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:65:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:63:1
    |
 LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b, 'c>,
 LL | |     T::AssocType: 'a,
 ...  |
-LL | |     //~| ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
+LL | |     //~^ ERROR associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
 LL | | }
    | |_^
    |
@@ -145,7 +121,7 @@ LL | | }
            ]
 
 error[E0309]: the associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:78:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -153,7 +129,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#7r, '_#8r>>::AssocType: ReEarlyBound(0, 'a)`...
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:91:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:88:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -170,7 +146,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:86:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:83:1
    |
 LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -189,7 +165,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:100:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:97:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,7 +182,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:95:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:92:1
    |
 LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -225,7 +201,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:108:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:105:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,14 +216,14 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:104:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:101:1
    |
 LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
 LL | |     T: Anything<'b, 'b>,
 LL | | {
-...  |
-LL | |     //~| ERROR
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | |     //~^ ERROR
 LL | | }
    | |_^
    |
@@ -257,7 +233,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-two-region-trait-bound-closure.rs:108:5
+  --> $DIR/projection-two-region-trait-bound-closure.rs:105:5
    |
 LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                --  -- lifetime `'b` defined here
@@ -268,7 +244,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:119:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:115:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -284,7 +260,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:114:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:110:1
    |
 LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -302,7 +278,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:131:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:127:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -317,7 +293,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:123:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:119:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
index 7ff4b484af17bed565cc30144f14892dbf6a2b57..ec6914f2630b1aa96f5f45eca35f69e4f1ff5b1e 100644 (file)
@@ -32,17 +32,12 @@ fn twice<'a, F, T>(v: Cell<&'a ()>, value: T, mut f: F)
 fn generic<T>(value: T) {
     let cell = Cell::new(&());
     twice(cell, value, |a, b| invoke(a, b));
-    //~^ WARNING not reporting region error
-    //
-    // This error from the old region solver looks bogus.
 }
 
 #[rustc_regions]
 fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
     twice(cell, value, |a, b| invoke(a, b));
-    //~^ WARNING not reporting region error
-    //~| WARNING not reporting region error
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn invoke<'a, 'x, T>(x: Option<Cell<&'x &'a ()>>, y: &T)
index 87f55b4e14d9652caca1fdd974a41026978f9b60..6050e627c71fdb813f3207e71da4a14fb9085294 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:31
-   |
-LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                               ^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31
-   |
-LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                               ^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31
-   |
-LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                               ^^^^^^^^^^^^
-
 note: External requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:24
    |
@@ -36,9 +18,6 @@ note: No external requirements
 LL | / fn generic<T>(value: T) {
 LL | |     let cell = Cell::new(&());
 LL | |     twice(cell, value, |a, b| invoke(a, b));
-LL | |     //~^ WARNING not reporting region error
-LL | |     //
-LL | |     // This error from the old region solver looks bogus.
 LL | | }
    | |_^
    |
@@ -47,7 +26,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:39:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -61,13 +40,11 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: where T: '_#1r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:41:1
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:38:1
    |
 LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
 LL | |     twice(cell, value, |a, b| invoke(a, b));
-LL | |     //~^ WARNING not reporting region error
-LL | |     //~| WARNING not reporting region error
-LL | |     //~| ERROR the parameter type `T` may not live long enough
+LL | |     //~^ ERROR the parameter type `T` may not live long enough
 LL | | }
    | |_^
    |
@@ -76,7 +53,7 @@ LL | | }
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:39:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
index b5cbd07b99c18fb67a34775cabdd3ea693259d99..cd47cc524d4ab2372a2635ff9525f03cbc4b605e 100644 (file)
@@ -34,8 +34,7 @@ fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
     // `'a` (and subsequently reports an error).
 
     with_signature(x, |y| y)
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
@@ -50,8 +49,7 @@ fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
     T: 'b + Debug,
 {
     x
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
index aec0d98c79aa47671f49d165350dbeb87d2838fe..5215f6a52771198b0a8e6a859110bce9f37326f8 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:27
-   |
-LL |     with_signature(x, |y| y)
-   |                           ^
-
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
-   |
-LL |     x
-   |     ^
-
 note: External requirements
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
    |
@@ -33,7 +21,7 @@ LL | | where
 LL | |     T: Debug,
 LL | | {
 ...  |
-LL | |     //~| ERROR the parameter type `T` may not live long enough
+LL | |     //~^ ERROR the parameter type `T` may not live long enough
 LL | | }
    | |_^
    |
@@ -51,7 +39,7 @@ LL |     with_signature(x, |y| y)
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:51:5
    |
 LL |     x
    |     ^
index edaaeac080d4df999d6a34893a2fea66f27f3cc6..aadf56e1fd088b308a7b46c90d118e392dad19d7 100644 (file)
@@ -42,7 +42,6 @@ fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
         // function, there is no where clause *anywhere*, and hence we
         // get an error (but reported by the closure creator).
         require(&x, &y)
-        //~^ WARNING not reporting region error due to nll
     })
 }
 
@@ -76,7 +75,6 @@ fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
         //~^ ERROR the parameter type `T` may not live long enough
         // See `correct_region`
         require(&x, &y)
-        //~^ WARNING not reporting region error due to nll
     })
 }
 
index 67a158860d64c1d7ffcf6705472c5bb65499c852..7129ec397de75c3d3476391b099e22bb44e756d3 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:44:9
-   |
-LL |         require(&x, &y)
-   |         ^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:78:9
-   |
-LL |         require(&x, &y)
-   |         ^^^^^^^
-
 note: External requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
    |
@@ -19,7 +7,7 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         //
 LL | |         // See `correct_region`, which explains the point of this
 ...  |
-LL | |         //~^ WARNING not reporting region error due to nll
+LL | |         require(&x, &y)
 LL | |     })
    | |_____^
    |
@@ -56,14 +44,14 @@ LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         //
 LL | |         // See `correct_region`, which explains the point of this
 ...  |
-LL | |         //~^ WARNING not reporting region error due to nll
+LL | |         require(&x, &y)
 LL | |     })
    | |_____^
    |
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:54:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:53:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -85,7 +73,7 @@ LL | |     })
    = note: where T: '_#2r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:50:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:49:1
    |
 LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -102,14 +90,13 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:74:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
 LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         // See `correct_region`
 LL | |         require(&x, &y)
-LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     })
    | |_____^
    |
@@ -123,7 +110,7 @@ LL | |     })
    = note: where T: '_#2r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:70:1
    |
 LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -140,21 +127,20 @@ LL | | }
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:74:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
 LL | |         //~^ ERROR the parameter type `T` may not live long enough
 LL | |         // See `correct_region`
 LL | |         require(&x, &y)
-LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     })
    | |_____^
    |
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:89:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:87:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -174,7 +160,7 @@ LL | |     })
    = note: where T: '_#3r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:84:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:82:1
    |
 LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
index 6226108ef196f1e0a7fc809868d7275305020044..10709327684cd2d8dac7f7cc9910ad63985ebf8e 100644 (file)
@@ -27,8 +27,7 @@ fn region_within_body<T>(t: T) {
 // Error here, because T: 'a is not satisfied.
 fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
     outlives(cell, t)
-    //~^ WARNING not reporting region error due to nll
-    //~| ERROR the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
index 537f12234708e2ccc174f398f388276adb553990..d6caae090a4b537aa1f395c0cfb792a5339d52f8 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn-body.rs:29:5
-   |
-LL |     outlives(cell, t)
-   |     ^^^^^^^^
-
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-fn-body.rs:29:5
    |
index 258d77eb2b078eef79f3deb837e090a86bdaaa78..1e49f7e5b19a366d78f05584a3212f6bfe53d496 100644 (file)
@@ -19,8 +19,7 @@ fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
     T: Debug,
 {
     x
-    //~^ WARNING not reporting region error due to nll
-    //~| the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
@@ -35,8 +34,7 @@ fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
     T: 'b + Debug,
 {
     x
-    //~^ WARNING not reporting region error due to nll
-    //~| the parameter type `T` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
index 5ce50d8118578f0b6bcbd50fd5a5a02327dbae53..7f137dcf05c81b4f6823de9740a2fc2866e5fab6 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn.rs:21:5
-   |
-LL |     x
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn.rs:37:5
-   |
-LL |     x
-   |     ^
-
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-fn.rs:21:5
    |
@@ -19,7 +7,7 @@ LL |     x
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn.rs:37:5
+  --> $DIR/ty-param-fn.rs:36:5
    |
 LL |     x
    |     ^
index 0efdd19df3c884e4def262a3f6047630e0a79b51..0cadc802d06e7dd6b1578b968b08a8d265c73d3e 100644 (file)
@@ -22,7 +22,6 @@ fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32)
 fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
     foo(x, y)
     //~^ ERROR unsatisfied lifetime constraints
-    //~| WARNING not reporting region error due to nll
 }
 
 fn main() {}
index 3d5dd4beb04f62f9d740eee8f4f211d213e7fce5..0c6913911ed5c995bcbba94c710566b86c353a33 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/where_clauses_in_functions.rs:23:5
-   |
-LL |     foo(x, y)
-   |     ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/where_clauses_in_functions.rs:23:5
    |
index 92e7db861734432398c73f28dd6b07091608b479..4b5a49dfae7073cb469d971a27a9c6108c290716 100644 (file)
@@ -22,7 +22,6 @@ struct Foo<'a: 'b, 'b> {
 fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
     Foo { x, y };
     //~^ ERROR unsatisfied lifetime constraints
-    //~| WARNING not reporting region error due to nll
 }
 
 fn main() {}
index c7ad9879b29cf6c640cfd5e49d2809c6ee95d149..636498eae927c63ee33b3da8ca2662905bab3fde 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/where_clauses_in_structs.rs:23:5
-   |
-LL |     Foo { x, y };
-   |     ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/where_clauses_in_structs.rs:23:11
    |
index 2dc0a10f425ae0c370ed18c8436c140cec60a544..e132ec67b9632d4acfe3b868d01d18c911e4b93a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-elision.rs:81:5
-   |
-LL |     ss
-   |     ^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/object-lifetime-default-elision.rs:81:5
    |
index 19279b53c1c8b5650f18b19dd0dda3dc38c5498e..e0c291928283ce3fc9468acce53f5afc37000372 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-from-box-error.rs:28:5
-   |
-LL |     ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
-   |     ^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-from-box-error.rs:41:12
-   |
-LL |     ss.r = b; //~ ERROR 41:12: 41:13: explicit lifetime required in the type of `ss` [E0621]
-   |            ^
-
 error[E0621]: explicit lifetime required in the type of `ss`
   --> $DIR/object-lifetime-default-from-box-error.rs:28:5
    |
index 42bcdf2bd8c55c93ef769689260c35869ce8d6d6..e62b9b070213df6e5cf20d2a728d29ee7b47ab5f 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-from-rptr-box-error.rs:25:12
-   |
-LL |     ss.t = t; //~ ERROR mismatched types
-   |            ^
-
 error: borrowed data escapes outside of function
   --> $DIR/object-lifetime-default-from-rptr-box-error.rs:25:5
    |
index 73b419d51134317c40250a8df36d02da3675450b..803f9d3fd7e5c27086209211b57ced335843c26c 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:31:12
-   |
-LL |     ss.t = t; //~ ERROR mismatched types
-   |            ^
-
 error: borrowed data escapes outside of function
   --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:31:5
    |
index 14a3cbf9e2948f2f3ef03166eca2b60aebd77e9d..41988b31e9745bd37157ac3a602222af284641a4 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-mybox.rs:37:5
-   |
-LL |     a //~ ERROR lifetime mismatch
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/object-lifetime-default-mybox.rs:41:11
-   |
-LL |     load0(ss) //~ ERROR mismatched types
-   |           ^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/object-lifetime-default-mybox.rs:37:5
    |
index 0eb0d4e10004b9a783afc0acf42dade3f24900b1..5d0395e17f54df32c2c77ed628d1a5eb6c324496 100644 (file)
@@ -1,10 +1,8 @@
 error: function should have one argument
   --> $DIR/panic-handler-bad-signature-3.rs:20:1
    |
-LL | / fn panic() -> ! { //~ ERROR function should have one argument
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn panic() -> ! { //~ ERROR function should have one argument
+   | ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 9fc12ae05b44f066d0860e18cc09e019453005a2..c9714de1f097509e9038f1797b037d14b7e78072 100644 (file)
@@ -1,14 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-invariant-static-error-reporting.rs:24:15
-   |
-LL |       let bad = if x.is_some() {
-   |  _______________^
-LL | |         x.unwrap()
-LL | |     } else {
-LL | |         mk_static()
-LL | |     };
-   | |_____^
-
 error: borrowed data escapes outside of function
   --> $DIR/region-invariant-static-error-reporting.rs:25:9
    |
index 9124347831344bb1799a819bb132d8d8cf67d06d..01bc022acb1cb24b6a05aa5af2a5c871ca80ce75 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:18:10
-   |
-LL |     *x = *y; //~ ERROR E0623
-   |          ^^
-
-warning: not reporting region error due to nll
-  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:24:5
-   |
-LL |     a(x, y); //~ ERROR 24:7: 24:8: lifetime mismatch [E0623]
-   |     ^
-
 error[E0308]: mismatched types
   --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:30:43
    |
index 655b199fc65a858e36e795bad5577c1615814d97..44f8f9e46f3fe39651669104afcd27b8bcd72678 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:19:10
-   |
-LL |     *x = *y; //~ ERROR E0623
-   |          ^^
-
-warning: not reporting region error due to nll
-  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:20:10
-   |
-LL |     *z = *y; //~ ERROR E0623
-   |          ^^
-
-warning: not reporting region error due to nll
-  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:26:5
-   |
-LL |     a(x, y, z); //~ ERROR 26:7: 26:8: lifetime mismatch [E0623]
-   |     ^
-
 error[E0308]: mismatched types
   --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:32:56
    |
index 135a115cecfa5d9e2e641150d76a8a70403a674e..4e1b8b7e1a076d2650f23d2f0ad1200cb86d3c68 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-object-lifetime-2.rs:20:7
-   |
-LL |     x.borrowed() //~ ERROR cannot infer
-   |       ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/region-object-lifetime-2.rs:20:5
    |
index 7bae6ccb37c92de9d395e524dd00ef414704fec5..5f1f70dfe1935b1cd63295b22aac1f304a4e0e80 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-object-lifetime-4.rs:22:7
-   |
-LL |     x.borrowed() //~ ERROR cannot infer
-   |       ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/region-object-lifetime-4.rs:22:5
    |
index f0def1888b9cdcfc8bcf870966d530aa44bfd382..e8c1d7e74a038a9477acfcac8bc8d962397cdfae 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/region-object-lifetime-in-coercion.rs:18:42
-   |
-LL |     let x: Box<Foo + 'static> = Box::new(v);
-   |                                          ^
-
-warning: not reporting region error due to nll
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:14
-   |
-LL |     Box::new(v)
-   |              ^
-
-warning: not reporting region error due to nll
-  --> $DIR/region-object-lifetime-in-coercion.rs:31:14
-   |
-LL |     Box::new(v)
-   |              ^
-
-warning: not reporting region error due to nll
-  --> $DIR/region-object-lifetime-in-coercion.rs:36:14
-   |
-LL |     Box::new(v)
-   |              ^
-
 error[E0621]: explicit lifetime required in the type of `v`
   --> $DIR/region-object-lifetime-in-coercion.rs:18:33
    |
index cad1384f198f709e4832651dd96a4a84ae5f4a3f..18578a1813445c8f3abb7ecb013fd13c53c7e2a7 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-addr-of-self.rs:17:37
-   |
-LL |         let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-addr-of-self.rs:17:37
    |
index 0ee86172368cfc769c193690f119d5ff1855a31a..d20cf12f4161a170c3d6772925c75f7a45b3f75e 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-addr-of-upvar-self.rs:20:41
-   |
-LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
-   |                                         ^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-addr-of-upvar-self.rs:20:41
    |
index 553eedec398ce4000742f5b4de59a3c7cc18736c..a292bacc674bf5e1a70279741d84255a4f9bec54 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:30:7
-   |
-LL |     a.bigger_region(b) //~ ERROR 30:7: 30:20: lifetime mismatch [E0623]
-   |       ^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:30:5
    |
index adcf4921e539d49035f4742f52b456974a558604..99c31783acdcc405a8f901528c4f7d479b81cb4f 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:30:7
-   |
-LL |     f.method(b); //~ ERROR 30:7: 30:13: lifetime mismatch [E0623]
-   |       ^^^^^^
-
 error: borrowed data escapes outside of function
   --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:30:5
    |
index a59a485f444cab821823919716bbc257d15b1f05..e50e806da12a30b361e7465f8b4baccceeadf7e0 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-bounds.rs:19:12
-   |
-LL |     return e; //~ ERROR mismatched types
-   |            ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-bounds.rs:23:12
-   |
-LL |     return e; //~ ERROR mismatched types
-   |            ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-bounds.rs:19:12
    |
index 5bec650a41d111f0140cbf4b5d66f6faba7767d1..90d38a49c4a8259f0ff407abee329bf8812c5532 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-associated-type-into-object.rs:25:5
-   |
-LL |     Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
-   |     ^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-associated-type-into-object.rs:32:5
-   |
-LL |     Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
-   |     ^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-associated-type-into-object.rs:38:5
-   |
-LL |     Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
-   |     ^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-associated-type-into-object.rs:45:5
-   |
-LL |     Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
-   |     ^^^^^^^^^^^^^^
-
 error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:25:5
    |
index 85724cfabd814f8ddf0afcb5764b65c0b9118825..c073e3728e70571c7febf98ccfdf2e5160a6a311 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-2.rs:20:11
-   |
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |           ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-close-object-into-object-2.rs:20:5
    |
index 3dc8df3608f06a108d163e056aea13c026cc3862..4b47b951d77173fcaba3511fd4e900fb0a38fb40 100644 (file)
@@ -1,33 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-4.rs:20:5
-   |
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-4.rs:20:11
-   |
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |           ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-4.rs:20:9
-   |
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |         ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-4.rs:20:9
-   |
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |         ^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-4.rs:20:5
-   |
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |     ^^^^^^^^^^
-
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:20:5
    |
index d7f9253d0b4d2bb7fa56a7f1f9b817847c0d11ce..8ef80fd775bfa765178e00ad0e4e48c107c31bc7 100644 (file)
@@ -1,33 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-5.rs:27:5
-   |
-LL |     box B(&*v) as Box<X>
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-5.rs:27:11
-   |
-LL |     box B(&*v) as Box<X>
-   |           ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-5.rs:27:9
-   |
-LL |     box B(&*v) as Box<X>
-   |         ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-5.rs:27:9
-   |
-LL |     box B(&*v) as Box<X>
-   |         ^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-object-into-object-5.rs:27:5
-   |
-LL |     box B(&*v) as Box<X>
-   |     ^^^^^^^^^^
-
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:27:5
    |
index ff74d46b011ffd1c7f5142d0d19915e13ecde074..6b8406cdb6e5e68831052f8976f8292f6ab77b89 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-over-type-parameter-1.rs:20:5
-   |
-LL |     box v as Box<SomeTrait+'static>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-over-type-parameter-1.rs:20:5
-   |
-LL |     box v as Box<SomeTrait+'static>
-   |     ^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-over-type-parameter-1.rs:30:5
-   |
-LL |     box v as Box<SomeTrait+'b>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-over-type-parameter-1.rs:30:5
-   |
-LL |     box v as Box<SomeTrait+'b>
-   |     ^^^^^
-
 error[E0310]: the parameter type `A` may not live long enough
   --> $DIR/regions-close-over-type-parameter-1.rs:20:5
    |
index 9e0dd9da0e4bf925806d509219fae946e2b6227b..017e912688849f6ee8f9df8ed2eab4d974914bc6 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-over-type-parameter-multiple.rs:30:5
-   |
-LL |     box v as Box<SomeTrait+'a> //~ ERROR cannot infer an appropriate lifetime
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-close-over-type-parameter-multiple.rs:30:5
    |
index 260a4067e100d6c88fb10e14d27670cd4c121779..c1c7e1b71c98681526befc367b067417d75a05e3 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-param-into-object.rs:16:5
-   |
-LL |     Box::new(v) //~ ERROR parameter type `T` may not live long enough
-   |     ^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-param-into-object.rs:22:5
-   |
-LL |     Box::new(v) //~ ERROR parameter type `T` may not live long enough
-   |     ^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-param-into-object.rs:28:5
-   |
-LL |     Box::new(v) //~ ERROR parameter type `T` may not live long enough
-   |     ^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-close-param-into-object.rs:34:5
-   |
-LL |     Box::new(v) //~ ERROR parameter type `T` may not live long enough
-   |     ^^^^^^^^^^^
-
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:16:5
    |
index 462e4152ce3bad74137544ad29a9c464c7fb34d0..aeb4fc67f55ed4b19276b3c4f75b99d3ec9466b9 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-creating-enums3.rs:17:5
-   |
-LL |     ast::add(x, y) //~ ERROR 17:5: 17:19: lifetime mismatch [E0623]
-   |     ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-creating-enums3.rs:17:5
    |
index b82fdfd5c65c41e6b6255a6dbc9deb5fe230931a..9c68c9bca49f28a7f2ee7045da9dfdab530bc417 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-creating-enums4.rs:17:5
-   |
-LL |     ast::add(x, y) //~ ERROR cannot infer
-   |     ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-creating-enums4.rs:17:5
    |
index cd2da8f3c6e72a2cb3f8a4ba1bad55c37d0a914e..e6c60b301a041667b3cbe542dc36dbe87a18ac6a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-early-bound-error-method.rs:30:9
-   |
-LL |         g2.get()
-   |         ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-early-bound-error-method.rs:30:9
    |
index 7ba615117353038445fea4812c2bec417d4f00b9..3c95e977fb366512e438ca71046981b5519a9342 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-early-bound-error.rs:29:5
-   |
-LL |     g1.get()
-   |     ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-early-bound-error.rs:29:5
    |
index 4603d1516e0f79fdda51c9948214fdd8ab51b619..ffcd1b6bd7b33beb87f17a76543ab61811dff981 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-escape-method.rs:25:13
-   |
-LL |     s.f(|p| p) //~ ERROR cannot infer
-   |             ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-escape-method.rs:25:13
    |
index 381f46286478026524162c16b91109af723065fa..36a79d52fd0022218b8eb2ad04447c14e9a20593 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-escape-via-trait-or-not.rs:28:14
-   |
-LL |     with(|o| o) //~ ERROR cannot infer
-   |              ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-escape-via-trait-or-not.rs:28:14
    |
index 3ef1be10f0fdc02f6a393f3d665f0bbb4ed4de78..98a4dc29ae7e707f3a91d30e0350070edb8638af 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-free-region-ordering-callee.rs:23:5
-   |
-LL |     &*y //~ ERROR 23:5: 23:8: lifetime mismatch [E0623]
-   |     ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-free-region-ordering-callee.rs:28:24
-   |
-LL |     let z: &'b usize = &*x;
-   |                        ^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-free-region-ordering-callee.rs:23:5
    |
index 0bc4bf4a951e8c6bdf811ecbafd2d0210fa6ada6..10259ccf270e8b496e9cfd1bd13a3a0863763c23 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-free-region-ordering-incorrect.rs:27:15
-   |
-LL |       None => &self.val //~ ERROR cannot infer
-   |               ^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-free-region-ordering-incorrect.rs:25:5
    |
diff --git a/src/test/ui/regions/regions-glb-free-free.nll.stderr b/src/test/ui/regions/regions-glb-free-free.nll.stderr
deleted file mode 100644 (file)
index a82ce96..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-glb-free-free.rs:25:13
-   |
-LL |             Flag { //~ ERROR 25:13: 30:14: explicit lifetime required in the type of `s` [E0621]
-   |             ^^^^
-
-error[E0621]: explicit lifetime required in the type of `s`
-  --> $DIR/regions-glb-free-free.rs:25:13
-   |
-LL |           pub fn set_desc(self, s: &str) -> Flag<'a> {
-   |                                    ---- help: add explicit lifetime `'a` to the type of `s`: `&'a str`
-LL | /             Flag { //~ ERROR 25:13: 30:14: explicit lifetime required in the type of `s` [E0621]
-LL | |                 name: self.name,
-LL | |                 desc: s,
-LL | |                 max_count: self.max_count,
-LL | |                 value: self.value
-LL | |             }
-   | |_____________^ lifetime `'a` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-infer-at-fn-not-param.nll.stderr b/src/test/ui/regions/regions-infer-at-fn-not-param.nll.stderr
deleted file mode 100644 (file)
index 6bc3daf..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-at-fn-not-param.rs:23:57
-   |
-LL | fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
-   |                                                         ^
-
-error[E0621]: explicit lifetime required in the type of `p`
-  --> $DIR/regions-infer-at-fn-not-param.rs:23:57
-   |
-LL | fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
-   |                 --------------                          ^ lifetime `'a` required
-   |                 |
-   |                 help: add explicit lifetime `'a` to the type of `p`: `parameterized1<'a>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index c71bd17ac783952fef98e5ebd6eb49c9e2eef465..9fc58273c941ea05062d3296f6af3b5754e933a3 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-bound-from-trait-self.rs:56:9
-   |
-LL |         check_bound(x, self)
-   |         ^^^^^^^^^^^
-
 error[E0309]: the parameter type `Self` may not live long enough
   --> $DIR/regions-infer-bound-from-trait-self.rs:56:9
    |
index 25f69031507ec8f72376a0c9b4329dc5d33ea1b0..ace8f14c734a09605aac11d0987b7d0cda16501d 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-bound-from-trait.rs:43:5
-   |
-LL |     check_bound(x, a) //~ ERROR parameter type `A` may not live long enough
-   |     ^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-bound-from-trait.rs:47:5
-   |
-LL |     check_bound(x, a) //~ ERROR parameter type `A` may not live long enough
-   |     ^^^^^^^^^^^
-
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-infer-bound-from-trait.rs:43:5
    |
index 6069aca62ec5e5d2c195d20e7df5cf898b53b079..30b892d3710f224f02a95fd34224eeff15d84177 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-call-3.rs:18:24
-   |
-LL |     let z = with(|y| { select(x, y) });
-   |                        ^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-infer-call-3.rs:18:24
    |
index cf754167b53ec0fa5120d9851af94af594980649..23a719e5503a1fe1df9bf182e45382a0b9a8730a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-invariance-due-to-decl.rs:22:5
-   |
-LL |     b_isize //~ ERROR mismatched types
-   |     ^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-infer-invariance-due-to-decl.rs:22:5
    |
index 6cd76f26ebec74d67a46c45392f2d1ad69ee2a0d..ff0a6adec049da7d523116bf02ae45579c414be8 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:21:5
-   |
-LL |     b_isize //~ ERROR mismatched types
-   |     ^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:21:5
    |
index 1e1daa59019bd828caa7e8ff855a586c2fe5e924..c296397954a766437f352a9eb36910d50bf3af17 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:21:5
-   |
-LL |     b_isize //~ ERROR mismatched types
-   |     ^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:21:5
    |
index 072be9b5a994ec42902a93d5e4dc487d99c18909..faeaa5eda02c6dc533c23d4cf1a0bc4f177080a0 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-not-param.rs:25:54
-   |
-LL | fn take_direct<'a,'b>(p: direct<'a>) -> direct<'b> { p } //~ ERROR mismatched types
-   |                                                      ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-not-param.rs:29:63
-   |
-LL | fn take_indirect2<'a,'b>(p: indirect2<'a>) -> indirect2<'b> { p } //~ ERROR mismatched types
-   |                                                               ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-infer-not-param.rs:25:54
    |
index 01ae2910bd5911e86f71e7b478f679d819ffd035..8e29e77713ba566838679247a43980011a9c285f 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-infer-paramd-indirect.rs:33:18
-   |
-LL |         self.f = b;
-   |                  ^
-
 error: borrowed data escapes outside of function
   --> $DIR/regions-infer-paramd-indirect.rs:33:9
    |
index 01f0cfa4a7186957abfef28d945f4d341b5ca4cd..d1d98a26a41fac246dc46f2e9d77b553f878913d 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-lifetime-bounds-on-fns.rs:18:10
-   |
-LL |     *x = *y; //~ ERROR E0623
-   |          ^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-lifetime-bounds-on-fns.rs:24:5
-   |
-LL |     a(x, y); //~ ERROR 24:7: 24:8: lifetime mismatch [E0623]
-   |     ^
-
 error[E0308]: mismatched types
   --> $DIR/regions-lifetime-bounds-on-fns.rs:30:43
    |
index d90015b1b2157ef280a98381da7356257fefb3e0..9e6c57f67332a6dc2b8e6e1163eff52080804d1d 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-nested-fns.rs:24:27
-   |
-LL |         if false { return x; } //~ ERROR E0312
-   |                           ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-nested-fns.rs:15:18
-   |
-LL |     let mut ay = &y; //~ ERROR E0495
-   |                  ^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-nested-fns.rs:20:9
    |
index db1508a8c8b14b16373689c894b7862a3ae7010d..6db1f6f4e78a4cf23aa011b4a0f9f0ab4622d3fc 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:42:12
-   |
-LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:63:12
-   |
-LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: compilation successful
   --> $DIR/regions-outlives-projection-container-hrtb.rs:68:1
    |
diff --git a/src/test/ui/regions/regions-proc-bound-capture.nll.stderr b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
deleted file mode 100644 (file)
index f19feed..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-proc-bound-capture.rs:19:14
-   |
-LL |     Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
-   |              ^^^^^^^^^^^^^
-
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/regions-proc-bound-capture.rs:19:5
-   |
-LL | fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
-   |                   ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
-LL |     // This is illegal, because the region bound on `proc` is 'static.
-LL |     Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0621`.
index 89575ca9bc809097171f44e5f56fb55826b0497b..48cd2d5a60bc1de874b8f77e656ec6e32c65abd6 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:14:5
-   |
-LL |     &mut ***p //~ ERROR 14:5: 14:14: lifetime mismatch [E0623]
-   |     ^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:14:5
    |
index 9c57813f26be6a67069a93c669bb70bada1c8283..02c7ce33aabac5d8b3cc215891a45aafa21bb3b5 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:16:5
-   |
-LL |     &mut **p //~ ERROR 16:5: 16:13: lifetime mismatch [E0623]
-   |     ^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:16:5
    |
index 29810f5128c9f0092e4c39cd22bcbe01111a32f1..5df6bca72fa0aa4278526f8f2dc4cd2744f142e1 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-ret-borrowed-1.rs:20:14
-   |
-LL |     with(|o| o)
-   |              ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-ret-borrowed-1.rs:20:14
    |
index ab70e6a663039ef46570e85bf227481e917a44f7..b36191ada61c773d2809ded5019d32e14e38e4bb 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-ret-borrowed.rs:23:14
-   |
-LL |     with(|o| o)
-   |              ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-ret-borrowed.rs:23:14
    |
index 850226f60cf7014ec1a003aea4f70d8d029cfcc7..35c1da61ae28fba30b4e3297d90cdaf73fd75853 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:17:24
-   |
-LL |         let mut f = || &mut x; //~ ERROR cannot infer
-   |                        ^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:17:24
    |
index 326111aab7ef0730be0a8aaaf7ca06d7edee05d2..462fbe8ee19bd19585653f6400157c16c330b8c3 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-static-bound.rs:19:5
-   |
-LL |     t //[ll]~ ERROR E0312
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-static-bound.rs:25:5
-   |
-LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
-   |     ^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-static-bound.rs:28:5
-   |
-LL |     static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
-   |     ^^^^^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-static-bound.rs:19:5
    |
@@ -25,7 +7,7 @@ LL |     t //[ll]~ ERROR E0312
    |     ^ returning this value requires that `'a` must outlive `'static`
 
 error[E0621]: explicit lifetime required in the type of `u`
-  --> $DIR/regions-static-bound.rs:25:5
+  --> $DIR/regions-static-bound.rs:24:5
    |
 LL | fn error(u: &(), v: &()) {
    |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
@@ -33,7 +15,7 @@ LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of
    |     ^^^^^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/regions-static-bound.rs:28:5
+  --> $DIR/regions-static-bound.rs:26:5
    |
 LL | fn error(u: &(), v: &()) {
    |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
index 4a11677765d14f460142eba04e98110b6257ec59..cf291279210c9e6c829ee149170df50f65a22f35 100644 (file)
@@ -12,7 +12,7 @@ LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
    |                        ^^
 
 error[E0621]: explicit lifetime required in the type of `u`
-  --> $DIR/regions-static-bound.rs:25:5
+  --> $DIR/regions-static-bound.rs:24:5
    |
 LL | fn error(u: &(), v: &()) {
    |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
@@ -20,7 +20,7 @@ LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of
    |     ^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/regions-static-bound.rs:28:5
+  --> $DIR/regions-static-bound.rs:26:5
    |
 LL | fn error(u: &(), v: &()) {
    |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
index 326111aab7ef0730be0a8aaaf7ca06d7edee05d2..462fbe8ee19bd19585653f6400157c16c330b8c3 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-static-bound.rs:19:5
-   |
-LL |     t //[ll]~ ERROR E0312
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-static-bound.rs:25:5
-   |
-LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
-   |     ^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-static-bound.rs:28:5
-   |
-LL |     static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
-   |     ^^^^^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-static-bound.rs:19:5
    |
@@ -25,7 +7,7 @@ LL |     t //[ll]~ ERROR E0312
    |     ^ returning this value requires that `'a` must outlive `'static`
 
 error[E0621]: explicit lifetime required in the type of `u`
-  --> $DIR/regions-static-bound.rs:25:5
+  --> $DIR/regions-static-bound.rs:24:5
    |
 LL | fn error(u: &(), v: &()) {
    |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
@@ -33,7 +15,7 @@ LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of
    |     ^^^^^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/regions-static-bound.rs:28:5
+  --> $DIR/regions-static-bound.rs:26:5
    |
 LL | fn error(u: &(), v: &()) {
    |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
index 0a37df4f0c788d11bc04249a830ed71bb96af32c..c5dc6000e839c270172a53a56472e9a3cb3165a6 100644 (file)
@@ -17,17 +17,14 @@ fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
     where 'a: 'b, 'b: 'static { t }
 fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
     t //[ll]~ ERROR E0312
-        //[nll]~^ WARNING not reporting region error due to nll
-        //[nll]~| ERROR unsatisfied lifetime constraints
+        //[nll]~^ ERROR unsatisfied lifetime constraints
 }
 
 fn error(u: &(), v: &()) {
     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
-    //[nll]~^ WARNING not reporting region error due to nll
-    //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621]
+    //[nll]~^ ERROR explicit lifetime required in the type of `u` [E0621]
     static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
-    //[nll]~^ WARNING not reporting region error due to nll
-    //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621]
+    //[nll]~^ ERROR explicit lifetime required in the type of `v` [E0621]
 }
 
 fn main() {}
index 01db25a07f76e6bf7634411ef83ac37490005f27..d4140242c01de773bf102d0655bb74d6b4c0c9b9 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/regions-trait-object-subtyping.rs:25:5
-   |
-LL |     x //~ ERROR lifetime bound not satisfied
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/regions-trait-object-subtyping.rs:32:5
-   |
-LL |     x //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/regions-trait-object-subtyping.rs:25:5
    |
index 685d62dc3a9c836ca9ff97b3d997def2715dc910..be6f3cf9eb205e96af215e105084299595dc8019 100644 (file)
@@ -36,3 +36,5 @@ fn cant_repr_this() {}
 
 #[repr(transparent)] //~ ERROR should be applied to struct
 static CANT_REPR_THIS: u32 = 0;
+
+fn main() {}
index e5889cf53e58ab2a638bc91ec9ac2856d02705ad..5a1978991480e62041e155fc916f556063301710 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `repr_transparent_other_items`
-   |
-   = note: consider adding a `main` function to `$DIR/repr-transparent-other-items.rs`
-
 error[E0517]: attribute should be applied to struct
   --> $DIR/repr-transparent-other-items.rs:13:8
    |
@@ -67,7 +63,7 @@ LL | #[repr(transparent)] //~ ERROR unsupported representation for zero-variant
 LL | enum Void {}         //~| ERROR should be applied to struct
    | ------------ zero-variant enum
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
-Some errors occurred: E0084, E0517, E0601.
+Some errors occurred: E0084, E0517.
 For more information about an error, try `rustc --explain E0084`.
index fa5f1a2f7fb80f1614f7d84c86d24265a058aa5c..aed8a69f66ef81e6518799a3fa58b31fdcfd1a12 100644 (file)
@@ -26,3 +26,5 @@ struct TransparentPlusC {
 #[repr(transparent)] //~ ERROR cannot have other repr
 #[repr(C)]
 struct SeparateAttributes(*mut u8);
+
+fn main() {}
index 40f41c474dbdaa328656c2a138c87e74bc120ba4..c8f5dea3c1242e60b1d5cd4193ea089d8d954239 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `repr_transparent_other_reprs`
-   |
-   = note: consider adding a `main` function to `$DIR/repr-transparent-other-reprs.rs`
-
 error[E0692]: transparent struct cannot have other repr hints
   --> $DIR/repr-transparent-other-reprs.rs:15:8
    |
@@ -28,7 +24,6 @@ LL | #[repr(transparent)] //~ ERROR cannot have other repr
 LL | #[repr(C)]
    |        ^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0601, E0692.
-For more information about an error, try `rustc --explain E0601`.
+For more information about this error, try `rustc --explain E0692`.
index 230573247316edeee5186d10bdf80ea8923b5874..f5b99af156ee0567d3c7547aba9a143f21ba0f00 100644 (file)
@@ -48,3 +48,5 @@
 
 #[repr(transparent)]
 struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
+
+fn main() {}
index 0f620880fa9d32a18f6ef90d1d0bfcb75c1c6216..f7bfdbdc625bbd70e4db39276416365adec948a8 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `repr_transparent`
-   |
-   = note: consider adding a `main` function to `$DIR/repr-transparent.rs`
-
 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
   --> $DIR/repr-transparent.rs:21:1
    |
@@ -70,7 +66,7 @@ error[E0691]: zero-sized field in transparent struct has alignment larger than 1
 LL | struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
    |                        ^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
-Some errors occurred: E0601, E0690, E0691.
-For more information about an error, try `rustc --explain E0601`.
+Some errors occurred: E0690, E0691.
+For more information about an error, try `rustc --explain E0690`.
index 9432e727fa5b7f1d1bade9a267babdd4a47b6b59..05bf4b928b7251abc421ec09afb31e8bc3a0c8a0 100644 (file)
@@ -17,3 +17,5 @@ impl SomeNonExistentTrait for isize {}
 
 fn f<T:SomeNonExistentTrait>() {}
 //~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope
+
+fn main() {}
index 8a2d791654d2f58c5d1be6be5f28d6aa1ff3f342..74b190f86845fcd23369cd7c83a970efc03b4d7a 100644 (file)
@@ -16,11 +16,6 @@ error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope
 LL | fn f<T:SomeNonExistentTrait>() {}
    |        ^^^^^^^^^^^^^^^^^^^^ not found in this scope
 
-error[E0601]: `main` function not found in crate `resolve_unknown_trait`
-   |
-   = note: consider adding a `main` function to `$DIR/resolve-unknown-trait.rs`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors occurred: E0405, E0601.
-For more information about an error, try `rustc --explain E0405`.
+For more information about this error, try `rustc --explain E0405`.
index a89fd802baf0c11f936c9672da05c4be557ad6b3..c5dd367c0ab88e21fd4f25e87b51e9869d207a93 100644 (file)
@@ -32,3 +32,5 @@ mod d {
         }
     }
 }
+
+fn main() {}
index 8538da06baf64aac433b9114edd67de346d49682..40b2a4bf9684254a705c763c258e139b15200124 100644 (file)
@@ -22,11 +22,6 @@ error[E0432]: unresolved import `alloc`
 LL |                 use alloc::HashMap;
    |                     ^^^^^ Did you mean `a::alloc`?
 
-error[E0601]: `main` function not found in crate `resolve_self_super_hint`
-   |
-   = note: consider adding a `main` function to `$DIR/resolve_self_super_hint.rs`
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0432, E0601.
-For more information about an error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0432`.
index 0972a0994fc0d38261b8abf776066f5e0f47399f..0e95c053ce4cfa46c7d57139380f061c21000643 100644 (file)
@@ -7,7 +7,7 @@ LL | | }
    | |_^ `main` can only return types that implement `std::process::Termination`
    |
    = help: the trait `std::process::Termination` is not implemented for `std::result::Result<f32, std::num::ParseIntError>`
-   = note: required by `__test::test::assert_test_result`
+   = note: required by `test::assert_test_result`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.rs b/src/test/ui/rust-2018/uniform-paths/redundant.rs
deleted file mode 100644 (file)
index 8f384b7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-#![feature(uniform_paths)]
-
-use std;
-
-fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.stderr b/src/test/ui/rust-2018/uniform-paths/redundant.stderr
deleted file mode 100644 (file)
index dd38407..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: `std` import is redundant
-  --> $DIR/redundant.rs:15:5
-   |
-LL | use std;
-   |     ^^^
-   |     |
-   |     refers to external crate `::std`
-   |     defines `self::std`, shadowing itself
-   |
-   = help: remove or write `::std` explicitly instead
-   = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
-
-error: aborting due to previous error
-
index 26b8b737f340d7a7e418adef7853977a0e8cf442..068eb7a448556cc02d3e639cb14dbcb3b1993c36 100644 (file)
@@ -21,3 +21,5 @@
 
 trait Tr {}
 default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
+
+fn main() {}
index 54b92da7b2192c53f6732e6db320f6d608e35233..c25c428eb4e9403d9a3138cdbd1b86577150cdc7 100644 (file)
@@ -6,10 +6,6 @@ LL | default impl S {} //~ ERROR inherent impls cannot be default
    |
    = note: only trait implementations may be annotated with default
 
-error[E0601]: `main` function not found in crate `validation`
-   |
-   = note: consider adding a `main` function to `$DIR/validation.rs`
-
 error: impls of auto traits cannot be default
   --> $DIR/validation.rs:19:1
    |
@@ -28,7 +24,6 @@ error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and
 LL | default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0192, E0601.
-For more information about an error, try `rustc --explain E0192`.
+For more information about this error, try `rustc --explain E0192`.
diff --git a/src/test/ui/test-on-macro.rs b/src/test/ui/test-on-macro.rs
new file mode 100644 (file)
index 0000000..a153e63
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// compile-flags:--test
+
+#![deny(warnings)]
+
+macro_rules! foo {
+    () => (fn foo(){})
+}
+
+#[test]
+foo!();
+
+fn main(){}
diff --git a/src/test/ui/test-on-macro.stderr b/src/test/ui/test-on-macro.stderr
new file mode 100644 (file)
index 0000000..a45bb25
--- /dev/null
@@ -0,0 +1,6 @@
+warning: #[test] attribute should not be used on macros. Use #[cfg(test)] instead.
+  --> $DIR/test-on-macro.rs:21:1
+   |
+LL | foo!();
+   | ^^^^^^^
+
diff --git a/src/test/ui/test-shadowing/auxiliary/test_macro.rs b/src/test/ui/test-shadowing/auxiliary/test_macro.rs
new file mode 100644 (file)
index 0000000..2e9d2dc
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_export]
+macro_rules! test {
+    () => {};
+}
diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs
new file mode 100644 (file)
index 0000000..4b1a437
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// aux-build:test_macro.rs
+// compile-flags:--test
+
+#[macro_use] extern crate test_macro;
+
+#[test]
+fn foo(){}
index 22d54a3834073d4f205701f49847732f13183c45..c8b77bfabdb9568733a0c085818b7fd3e2ea38d7 100644 (file)
@@ -15,3 +15,5 @@ mod foo {
     //~^ ERROR expected one of `)` or `,`, found `(`
     //~| ERROR cannot find type `foo` in this scope
 }
+
+fn main() {}
index 59228ea8c14d2ca41e9bb8d5f5474d90b33ff92b..f83e9dd5458fbad6d370fa68d4f36ea0684dfe80 100644 (file)
@@ -10,11 +10,6 @@ error[E0412]: cannot find type `foo` in this scope
 LL |     struct S2(pub((foo)) ());
    |                    ^^^ not found in this scope
 
-error[E0601]: `main` function not found in crate `test`
-   |
-   = note: consider adding a `main` function to `$DIR/test.rs`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0412, E0601.
-For more information about an error, try `rustc --explain E0412`.
+For more information about this error, try `rustc --explain E0412`.
index a113c1ae27fb4c16bc9873ee701ff385e39e0d12..a3501290cd607d5b0df07aa7ca343560d45e7a50 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:27:15
-   |
-LL |         x.set(y); //~ ERROR E0312
-   |               ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:27:9
    |
index 58939b0f64f5a99603fabb5d02f1c1dd1544eb6e..7adb195b7d0225d68304b023191927b6d3b760e6 100644 (file)
@@ -1,27 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:18:14
-   |
-LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
-   |              ^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:18:20
-   |
-LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
-   |                    ^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:18:5
-   |
-LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
-   |     ^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:18:5
-   |
-LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/dyn-trait-underscore.rs:18:5
    |
index eef04cbf35177e7bb6e659613607b6e8debf2053..eedbfbf5f61a7ab6005b76f4a2c752fcdd59364a 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/underscore-lifetime-elison-mismatch.rs:11:49
-   |
-LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } //~ ERROR lifetime mismatch
-   |                                                 ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/underscore-lifetime-elison-mismatch.rs:11:42
    |
index a3eeb6de96bda1f9867a1d6d9c13510571f76bdb..efa7494647691a28ed57e277e0cdfce0e398bbac 100644 (file)
@@ -55,3 +55,5 @@ enum Enum {
 
     fn item() {}
 }
+
+fn main() {}
index 1e663cde48a65d94bf24e3b11b66da4ff439c7ec..9bcebb0011a75d9336ae2c4a362bb99b395597ca 100644 (file)
@@ -34,11 +34,6 @@ error[E0432]: unresolved import `Enum`
 LL |     use Enum::*; //~ ERROR unresolved import `Enum` [E0432]
    |         ^^^^ Did you mean `self::Enum`?
 
-error[E0601]: `main` function not found in crate `unresolved_import`
-   |
-   = note: consider adding a `main` function to `$DIR/unresolved-import.rs`
-
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors occurred: E0432, E0601.
-For more information about an error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0432`.
index 765e2059a4b5efbc629b0197091b9718ac16decc..fe0bb7533a86f316f53ed19a548d763ea4a136bc 100644 (file)
@@ -10,7 +10,7 @@
 
 // A quick test of 'unsafe const fn' functionality
 
-#![feature(const_fn)]
+#![feature(min_const_fn)]
 
 const unsafe fn dummy(v: u32) -> u32 {
     !v
index 02e1a585fa89d054d267c206ca636f4ff4f5c093..fe76d58f1ef76d26444eaf809ba38e4df62d77a7 100644 (file)
@@ -11,3 +11,5 @@
 #![allow(unused_macros)]
 
 macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
+
+fn main() {}
index 3359aa4bcd720ed249e1a9add4d46cbcbf606fb9..1f8b18166c9c96124461bc2fc5eb14522e2f5113 100644 (file)
@@ -4,10 +4,5 @@ error: user-defined macros may not be named `macro_rules`
 LL | macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `user_defined_macro_rules`
-   |
-   = note: consider adding a `main` function to `$DIR/user-defined-macro-rules.rs`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
index 877036530ed19c57e6f132ada81390fe93a637f4..f09dcdf25dac96a125848dacbf3a7aebe3d6cc38 100644 (file)
@@ -1,75 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:16:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:19:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:22:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:25:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:30:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:34:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:38:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:42:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:47:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:51:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:55:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-btree-invariant-types.rs:59:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-btree-invariant-types.rs:16:5
    |
index 67d43dd5070054ba1364b09270d88b1d2eb92947..4ef45edc24246f4151405a735bcb739c08999946 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-contravariant-arg-object.rs:24:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-contravariant-arg-object.rs:32:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-contravariant-arg-object.rs:24:5
    |
index 55413e57a949374cd6720439b0c841978bf1f706..3105ebaf03117d1025fcab00f5c75a58ad3aa5e2 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-covariant-arg-object.rs:25:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-covariant-arg-object.rs:32:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-covariant-arg-object.rs:25:5
    |
index f90975192460b060e89b43209c9266e730a211dc..54ad4f4c5fbe63f97483d8b15fc643b80c336641 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-invariant-arg-object.rs:21:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-invariant-arg-object.rs:28:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-invariant-arg-object.rs:21:5
    |
index baf75b73463a5f1c4e13515d280436c2fe56fa87..14b42585d6e2afd408fbdc832e2d988f6f5d4337 100644 (file)
@@ -1,21 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-trait-matching.rs:34:10
-   |
-LL |     pick(get, &22) //~ ERROR 34:5: 34:9: explicit lifetime required in the type of `get` [E0621]
-   |          ^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-trait-matching.rs:34:5
-   |
-LL |     pick(get, &22) //~ ERROR 34:5: 34:9: explicit lifetime required in the type of `get` [E0621]
-   |     ^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-trait-matching.rs:34:5
-   |
-LL |     pick(get, &22) //~ ERROR 34:5: 34:9: explicit lifetime required in the type of `get` [E0621]
-   |     ^^^^
-
 error[E0621]: explicit lifetime required in the type of `get`
   --> $DIR/variance-trait-matching.rs:34:5
    |
index 643b8587bea94595ea842c36d38d325b984cd1c5..37604af5063224774309fd55ac24e06bd45f9236 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-use-contravariant-struct-1.rs:22:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-use-contravariant-struct-1.rs:22:5
    |
index f0c9c44794df2807b49b23cc8da55c72768c995b..c7fd60301c834a798c8c9bf1b4295b68501f7c04 100644 (file)
@@ -1,9 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-use-covariant-struct-1.rs:20:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-use-covariant-struct-1.rs:20:5
    |
index 8b6d6100af48e8a046e82edadc51ab1d36c60cd1..1638d5ec4fb7a53d9bd8af805cd2553c15b858d0 100644 (file)
@@ -1,15 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/variance-use-invariant-struct-1.rs:22:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
-warning: not reporting region error due to nll
-  --> $DIR/variance-use-invariant-struct-1.rs:29:5
-   |
-LL |     v //~ ERROR mismatched types
-   |     ^
-
 error: unsatisfied lifetime constraints
   --> $DIR/variance-use-invariant-struct-1.rs:22:5
    |
index 5631a70192afd0962bbb6548a0d79278d1bca52a..9f431e78061391e98e473977a799faea28ab4c4a 100644 (file)
@@ -21,3 +21,5 @@
 
 #[link_section = "test"]
 pub static D: &usize = &C; //~ ERROR: no extra levels of indirection
+
+fn main() {}
index 9b96b99e02ae4ebb78c8de511c2dffbbfb8c6b16..cea6e5c41923a1013a1d5e754d7c5ee29829172c 100644 (file)
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `wasm_custom_section_relocations`
-   |
-   = note: consider adding a `main` function to `$DIR/wasm-custom-section-relocations.rs`
-
 error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references
   --> $DIR/wasm-custom-section-relocations.rs:14:1
    |
@@ -14,6 +10,5 @@ error: statics with a custom `#[link_section]` must be a simple list of bytes on
 LL | pub static D: &usize = &C; //~ ERROR: no extra levels of indirection
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0601`.
index 3ed9e5d9f1eb58123a5551b9bb75a29cbad3dfa7..59bb8326ddbf5ba07fe69d3785d38fff5f95e5e1 100644 (file)
@@ -10,7 +10,6 @@
 
 // Test that we check where-clauses on fn items.
 
-#![feature(associated_type_defaults)]
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
@@ -20,5 +19,9 @@ fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
 {
 }
 
+fn bar() where Vec<dyn Copy>:, {}
+//~^ ERROR E0277
+//~| ERROR E0038
+
 #[rustc_error]
 fn main() { }
index 5f0f982577ee55bff7d5049f1620b055d2df17ac..21591419ec856becec482c916c136eecbfceebb3 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
-  --> $DIR/wf-fn-where-clause.rs:19:1
+  --> $DIR/wf-fn-where-clause.rs:18:1
    |
 LL | / fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
 LL | | {
@@ -8,11 +8,30 @@ LL | | }
    |
    = help: consider adding a `where U: std::marker::Copy` bound
 note: required by `ExtraCopy`
-  --> $DIR/wf-fn-where-clause.rs:17:1
+  --> $DIR/wf-fn-where-clause.rs:16:1
    |
 LL | trait ExtraCopy<T:Copy> { }
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time
+  --> $DIR/wf-fn-where-clause.rs:22:1
+   |
+LL | fn bar() where Vec<dyn Copy>:, {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::marker::Copy + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec`
+
+error[E0038]: the trait `std::marker::Copy` cannot be made into an object
+  --> $DIR/wf-fn-where-clause.rs:22:1
+   |
+LL | fn bar() where Vec<dyn Copy>:, {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors occurred: E0038, E0277.
+For more information about an error, try `rustc --explain E0038`.
index e563a4ffc56899b84417bd019d8197d499ac8f58..51aec2a949f998f51d9248a25715443c30ba0035 100644 (file)
@@ -1,33 +1,3 @@
-warning: not reporting region error due to nll
-  --> $DIR/wf-static-method.rs:27:9
-   |
-LL |         u //~ ERROR E0312
-   |         ^
-
-warning: not reporting region error due to nll
-  --> $DIR/wf-static-method.rs:36:18
-   |
-LL |         let me = Self::make_me(); //~ ERROR lifetime bound not satisfied
-   |                  ^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/wf-static-method.rs:43:9
-   |
-LL |         u //~ ERROR E0312
-   |         ^
-
-warning: not reporting region error due to nll
-  --> $DIR/wf-static-method.rs:51:5
-   |
-LL |     <()>::static_evil(b) //~ ERROR cannot infer an appropriate lifetime
-   |     ^^^^^^^^^^^^^^^^^
-
-warning: not reporting region error due to nll
-  --> $DIR/wf-static-method.rs:55:5
-   |
-LL |     <IndirectEvil>::static_evil(b)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: unsatisfied lifetime constraints
   --> $DIR/wf-static-method.rs:27:9
    |
diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md
new file mode 100644 (file)
index 0000000..6834f56
--- /dev/null
@@ -0,0 +1,30 @@
+# build-manifest
+
+This tool generates the manifests uploaded to static.rust-lang.org and used by
+rustup. The tool is invoked by the bootstrap tool.
+
+## Testing changes locally
+
+In order to test the changes locally you need to have a valid dist directory
+available locally. If you don't want to build all the compiler, you can easily
+create one from the nightly artifacts with:
+
+```
+#!/bin/bash
+for cmpn in rust rustc rust-std rust-docs cargo; do
+    wget https://static.rust-lang.org/dist/${cmpn}-nightly-x86_64-unknown-linux-gnu.tar.gz
+done
+```
+
+Then, you can generate the manifest and all the packages from `path/to/dist` to
+`path/to/output` with:
+
+```
+$ BUILD_MANIFEST_DISABLE_SIGNING=1 cargo +nightly run \
+    path/to/dist path/to/output 1970-01-01 \
+    nightly nightly nightly nightly nightly nightly nightly \
+    http://example.com
+```
+
+In the future, if the tool complains about missing arguments just add more
+`nightly`s in the middle.
index f43bd88d04f3233993c94c9c669ff5e276acc796..f81964ccbc23c6405d4533fe5bd06865004bcd34 100644 (file)
@@ -92,6 +92,7 @@
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
     "powerpc64le-unknown-linux-musl",
+    "riscv32imc-unknown-none-elf",
     "riscv32imac-unknown-none-elf",
     "s390x-unknown-linux-gnu",
     "sparc-unknown-linux-gnu",
     "x86_64-unknown-redox",
 ];
 
+static DOCS_TARGETS: &'static [&'static str] = &[
+    "i686-apple-darwin",
+    "i686-pc-windows-gnu",
+    "i686-pc-windows-msvc",
+    "i686-unknown-linux-gnu",
+    "x86_64-apple-darwin",
+    "x86_64-pc-windows-gnu",
+    "x86_64-pc-windows-msvc",
+    "x86_64-unknown-linux-gnu",
+];
+
 static MINGW: &'static [&'static str] = &[
     "i686-pc-windows-gnu",
     "x86_64-pc-windows-gnu",
@@ -216,9 +228,23 @@ struct Builder {
     rustfmt_git_commit_hash: Option<String>,
     llvm_tools_git_commit_hash: Option<String>,
     lldb_git_commit_hash: Option<String>,
+
+    should_sign: bool,
 }
 
 fn main() {
+    // Avoid signing packages while manually testing
+    // Do NOT set this envvar in CI
+    let should_sign = env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err();
+
+    // Safety check to ensure signing is always enabled on CI
+    // The CI environment variable is set by both Travis and AppVeyor
+    if !should_sign && env::var("CI").is_ok() {
+        println!("The 'BUILD_MANIFEST_DISABLE_SIGNING' env var can't be enabled on CI.");
+        println!("If you're not running this on CI, unset the 'CI' env var.");
+        panic!();
+    }
+
     let mut args = env::args().skip(1);
     let input = PathBuf::from(args.next().unwrap());
     let output = PathBuf::from(args.next().unwrap());
@@ -231,8 +257,12 @@ fn main() {
     let llvm_tools_release = args.next().unwrap();
     let lldb_release = args.next().unwrap();
     let s3_address = args.next().unwrap();
+
+    // Do not ask for a passphrase while manually testing
     let mut passphrase = String::new();
-    t!(io::stdin().read_to_string(&mut passphrase));
+    if should_sign {
+        t!(io::stdin().read_to_string(&mut passphrase));
+    }
 
     Builder {
         rust_release,
@@ -265,6 +295,8 @@ fn main() {
         rustfmt_git_commit_hash: None,
         llvm_tools_git_commit_hash: None,
         lldb_git_commit_hash: None,
+
+        should_sign,
     }.build();
 }
 
@@ -318,7 +350,7 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("cargo", &mut manifest.pkg, HOSTS);
         self.package("rust-mingw", &mut manifest.pkg, MINGW);
         self.package("rust-std", &mut manifest.pkg, TARGETS);
-        self.package("rust-docs", &mut manifest.pkg, TARGETS);
+        self.package("rust-docs", &mut manifest.pkg, DOCS_TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
         self.package("rls-preview", &mut manifest.pkg, HOSTS);
         self.package("clippy-preview", &mut manifest.pkg, HOSTS);
@@ -402,11 +434,7 @@ fn build_manifest(&mut self) -> Manifest {
                         Some(p) => p,
                         None => return false,
                     };
-                    let target = match pkg.target.get(&c.target) {
-                        Some(t) => t,
-                        None => return false,
-                    };
-                    target.available
+                    pkg.target.get(&c.target).is_some()
                 };
                 extensions.retain(&has_component);
                 components.retain(&has_component);
@@ -588,6 +616,10 @@ fn hash(&self, path: &Path) -> String {
     }
 
     fn sign(&self, path: &Path) {
+        if !self.should_sign {
+            return;
+        }
+
         let filename = path.file_name().unwrap().to_str().unwrap();
         let asc = self.output.join(format!("{}.asc", filename));
         println!("signing: {:?}", path);
index 2a284a70e26997273c296afe06586ffdf3a142fd..d0fc1788123de9844c8088b977cd142021cea1f2 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2a284a70e26997273c296afe06586ffdf3a142fd
+Subproject commit d0fc1788123de9844c8088b977cd142021cea1f2
index d99cea0f16633556871a59500c610782b07233b9..131c8f86b2b712d4d9b00f486b6c67f97782228a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d99cea0f16633556871a59500c610782b07233b9
+Subproject commit 131c8f86b2b712d4d9b00f486b6c67f97782228a
index 6639ba51b12816a13944dd2bb2fe58c11aa59dac..7fec2e003a4452ee5ee7ffbe51ff24d1fd325958 100644 (file)
@@ -9,7 +9,7 @@ env_logger = { version = "0.5", default-features = false }
 filetime = "0.2"
 getopts = "0.2"
 log = "0.4"
-regex = "0.2"
+regex = "1.0"
 serde = "1.0"
 serde_json = "1.0"
 serde_derive = "1.0"
index 813b3b952c07b6b85732c3fbdf3eb74f61a9fa96..2a9b88b8b419d094fb2185c0ca31c28d31bdca00 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 813b3b952c07b6b85732c3fbdf3eb74f61a9fa96
+Subproject commit 2a9b88b8b419d094fb2185c0ca31c28d31bdca00
index 3dbe998969d457c5cef245f61b48bdaed0f5c059..7728fa22bebea288abfea3b70cf795c60b93df3a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3dbe998969d457c5cef245f61b48bdaed0f5c059
+Subproject commit 7728fa22bebea288abfea3b70cf795c60b93df3a
index e67fd48f1aa2a31daee70dc3e80621077a31c52d..cf6358a00540a83dcc6e8c243f3306ccdbb9c354 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e67fd48f1aa2a31daee70dc3e80621077a31c52d
+Subproject commit cf6358a00540a83dcc6e8c243f3306ccdbb9c354
index 5c9a2b6c13d3b6f8d3f9c02b130bb4b54fd489fb..1c408818c8a752dd584e7858b4afd3ceb011a7da 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5c9a2b6c13d3b6f8d3f9c02b130bb4b54fd489fb
+Subproject commit 1c408818c8a752dd584e7858b4afd3ceb011a7da
index 68a4b7898575d0765135275d1904225e5c58fc1d..d6a2c17d6f6f9a6d2b265180313840d927e296db 100644 (file)
     Crate("kernel32-sys"),
     Crate("lazy_static"),
     Crate("libc"),
+    Crate("lock_api"),
     Crate("log"),
     Crate("log_settings"),
     Crate("memchr"),
+    Crate("memmap"),
     Crate("memoffset"),
     Crate("miniz-sys"),
     Crate("nodrop"),
     Crate("owning_ref"),
     Crate("parking_lot"),
     Crate("parking_lot_core"),
-    Crate("polonius-engine"),
     Crate("pkg-config"),
+    Crate("polonius-engine"),
     Crate("quick-error"),
     Crate("rand"),
     Crate("rand_core"),
     Crate("winapi"),
     Crate("winapi-build"),
     Crate("winapi-i686-pc-windows-gnu"),
+    Crate("winapi-util"),
     Crate("winapi-x86_64-pc-windows-gnu"),
     Crate("wincolor"),
 ];