]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #54891 - rust-lang:SimonSapin-patch-1, r=nagisa
authorkennytm <kennytm@gmail.com>
Fri, 12 Oct 2018 14:04:07 +0000 (22:04 +0800)
committerGitHub <noreply@github.com>
Fri, 12 Oct 2018 14:04:07 +0000 (22:04 +0800)
Fix tracking issue for Once::is_completed

https://github.com/rust-lang/rust/pull/53027 was merged without a tracking issue. I just filed https://github.com/rust-lang/rust/issues/54890. CC @matklad

445 files changed:
RELEASES.md
config.toml.example
src/Cargo.lock
src/bootstrap/config.rs
src/bootstrap/lib.rs
src/bootstrap/sanity.rs
src/bootstrap/test.rs
src/doc/not_found.md
src/doc/unstable-book/src/language-features/cfg-attr-multi.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/tool-lints.md [deleted file]
src/etc/gdb_rust_pretty_printing.py
src/liballoc/collections/btree/node.rs
src/liballoc/lib.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/liballoc/tests/lib.rs
src/liballoc/vec.rs
src/libcore/option.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libcore/task/wake.rs
src/libcore/tests/lib.rs
src/libgraphviz/lib.rs
src/librustc/Cargo.toml
src/librustc/cfg/graphviz.rs
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_ty.rs
src/librustc/lib.rs
src/librustc/lint/levels.rs
src/librustc/middle/dead.rs
src/librustc/middle/resolve_lifetime.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/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/constness.rs
src/librustc/ty/context.rs
src/librustc/ty/flags.rs
src/librustc/ty/structural_impls.rs
src/librustc_borrowck/graphviz.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/allocator.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/declare.rs
src/librustc_codegen_llvm/diagnostics.rs
src/librustc_codegen_llvm/glue.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_llvm/metadata.rs
src/librustc_codegen_llvm/mir/analyze.rs
src/librustc_codegen_llvm/mir/block.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/statement.rs
src/librustc_codegen_llvm/mono_item.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_llvm/value.rs
src/librustc_driver/lib.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_lint/builtin.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/constraints/graph.rs
src/librustc_mir/borrow_check/nll/constraints/mod.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/renumber.rs
src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
src/librustc_mir/borrow_check/nll/type_check/input_output.rs
src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/dataflow/graphviz.rs
src/librustc_mir/diagnostics.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/mod.rs
src/librustc_mir/hair/util.rs [new file with mode: 0644]
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
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_target/lib.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
src/librustc_traits/Cargo.toml
src/librustc_traits/chalk_context.rs
src/librustc_traits/lowering.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/Cargo.toml
src/librustdoc/html/highlight.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/libstd/io/error.rs
src/libstd/lib.rs
src/libstd/primitive_docs.rs
src/libstd/thread/mod.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/config.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/parser.rs
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.h
src/test/codegen-units/item-collection/unreferenced-const-fn.rs
src/test/codegen/link-dead-code.rs
src/test/codegen/naked-functions.rs
src/test/codegen/no-plt.rs [new file with mode: 0644]
src/test/compile-fail/issue-43733-2.rs
src/test/debuginfo/associated-types.rs
src/test/debuginfo/basic-types.rs
src/test/debuginfo/borrowed-basic.rs
src/test/debuginfo/borrowed-c-style-enum.rs
src/test/debuginfo/borrowed-enum.rs
src/test/debuginfo/borrowed-struct.rs
src/test/debuginfo/borrowed-tuple.rs
src/test/debuginfo/borrowed-unique-basic.rs
src/test/debuginfo/box.rs
src/test/debuginfo/boxed-struct.rs
src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
src/test/debuginfo/c-style-enum-in-composite.rs
src/test/debuginfo/c-style-enum.rs
src/test/debuginfo/closure-in-generic-function.rs
src/test/debuginfo/cross-crate-spans.rs
src/test/debuginfo/destructured-fn-argument.rs
src/test/debuginfo/destructured-for-loop-variable.rs
src/test/debuginfo/destructured-local.rs
src/test/debuginfo/evec-in-struct.rs
src/test/debuginfo/extern-c-fn.rs
src/test/debuginfo/function-arguments.rs
src/test/debuginfo/generic-function.rs
src/test/debuginfo/generic-functions-nested.rs
src/test/debuginfo/generic-method-on-generic-struct.rs
src/test/debuginfo/generic-struct.rs
src/test/debuginfo/generic-tuple-style-enum.rs
src/test/debuginfo/include_string.rs
src/test/debuginfo/issue-22656.rs
src/test/debuginfo/lexical-scope-in-for-loop.rs
src/test/debuginfo/lexical-scope-in-if.rs
src/test/debuginfo/lexical-scope-in-match.rs
src/test/debuginfo/lexical-scope-in-stack-closure.rs
src/test/debuginfo/lexical-scope-in-unconditional-loop.rs
src/test/debuginfo/lexical-scope-in-unique-closure.rs
src/test/debuginfo/lexical-scope-in-while.rs
src/test/debuginfo/lexical-scope-with-macro.rs
src/test/debuginfo/lexical-scopes-in-block-expression.rs
src/test/debuginfo/method-on-generic-struct.rs
src/test/debuginfo/method-on-struct.rs
src/test/debuginfo/method-on-trait.rs
src/test/debuginfo/method-on-tuple-struct.rs
src/test/debuginfo/multi-cgu.rs
src/test/debuginfo/multiple-functions-equal-var-names.rs
src/test/debuginfo/multiple-functions.rs
src/test/debuginfo/name-shadowing-and-scope-nesting.rs
src/test/debuginfo/packed-struct-with-destructor.rs
src/test/debuginfo/packed-struct.rs
src/test/debuginfo/self-in-default-method.rs
src/test/debuginfo/self-in-generic-default-method.rs
src/test/debuginfo/shadowed-argument.rs
src/test/debuginfo/shadowed-variable.rs
src/test/debuginfo/simple-lexical-scope.rs
src/test/debuginfo/simple-struct.rs
src/test/debuginfo/simple-tuple.rs
src/test/debuginfo/static-method-on-struct-and-enum.rs
src/test/debuginfo/struct-in-struct.rs
src/test/debuginfo/struct-namespace.rs
src/test/debuginfo/struct-style-enum.rs
src/test/debuginfo/struct-with-destructor.rs
src/test/debuginfo/tuple-in-tuple.rs
src/test/debuginfo/tuple-struct.rs
src/test/debuginfo/tuple-style-enum.rs
src/test/debuginfo/union-smoke.rs
src/test/debuginfo/unique-enum.rs
src/test/debuginfo/var-captured-in-nested-closure.rs
src/test/debuginfo/var-captured-in-sendable-closure.rs
src/test/debuginfo/var-captured-in-stack-closure.rs
src/test/debuginfo/vec-slices.rs
src/test/debuginfo/vec.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-pass-fulldeps/newtype_index.rs
src/test/run-pass/async-await.rs
src/test/run-pass/consts/auxiliary/const_fn_lib.rs
src/test/run-pass/consts/const-fn-const-eval.rs
src/test/run-pass/consts/const-fn-method.rs
src/test/run-pass/consts/const-fn-nested.rs
src/test/run-pass/consts/const-meth-pattern.rs
src/test/run-pass/consts/const-pattern-variant.rs
src/test/run-pass/consts/const-size_of-align_of.rs
src/test/run-pass/consts/const-unsafe-fn.rs
src/test/run-pass/consts/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/impl-trait/existential-minimal.rs [deleted file]
src/test/run-pass/impl-trait/issue-42479.rs [deleted file]
src/test/run-pass/impl-trait/issue-49376.rs [deleted file]
src/test/run-pass/issues/auxiliary/issue-36954.rs
src/test/run-pass/issues/issue-29927.rs
src/test/run-pass/issues/issue-33537.rs
src/test/run-pass/issues/issue-37991.rs
src/test/run-pass/issues/issue-49556.rs [deleted file]
src/test/run-pass/issues/issue29927-1.rs
src/test/run-pass/macros/macro-as-fn-body.rs [new file with mode: 0644]
src/test/run-pass/tool_lints.rs
src/test/run-pass/tool_lints_2018_preview.rs
src/test/run-pass/traits/conservative_impl_trait.rs [deleted file]
src/test/rustdoc-ui/invalid-syntax.rs [new file with mode: 0644]
src/test/rustdoc-ui/invalid-syntax.stderr [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/ui-fulldeps/lint_tool_test.rs
src/test/ui/auxiliary/namespaced_enums.rs [deleted file]
src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.rs
src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr
src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr
src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr
src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs
src/test/ui/cfg-arg-invalid-1.rs [deleted file]
src/test/ui/cfg-arg-invalid-2.rs [deleted file]
src/test/ui/cfg-arg-invalid-3.rs [deleted file]
src/test/ui/cfg-arg-invalid-4.rs [deleted file]
src/test/ui/cfg-arg-invalid-5.rs [deleted file]
src/test/ui/cfg-attr-cfg-2.rs [deleted file]
src/test/ui/cfg-attr-cfg-2.stderr [deleted file]
src/test/ui/cfg-attr-crate-2.rs [deleted file]
src/test/ui/cfg-attr-crate-2.stderr [deleted file]
src/test/ui/cfg-attr-invalid-predicate.rs [deleted file]
src/test/ui/cfg-attr-invalid-predicate.stderr [deleted file]
src/test/ui/cfg-attr-syntax-validation.rs [deleted file]
src/test/ui/cfg-attr-syntax-validation.stderr [deleted file]
src/test/ui/cfg-attr-trailing-comma.rs [deleted file]
src/test/ui/cfg-attr-trailing-comma.stderr [deleted file]
src/test/ui/cfg-attr-unknown-attribute-macro-expansion.rs [deleted file]
src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr [deleted file]
src/test/ui/cfg-empty-codemap.rs [deleted file]
src/test/ui/cfg-in-crate-1.rs [deleted file]
src/test/ui/cfg-in-crate-1.stderr [deleted file]
src/test/ui/cfg-non-opt-expr.rs [deleted file]
src/test/ui/cfg-non-opt-expr.stderr [deleted file]
src/test/ui/cfg_attr_path.rs [deleted file]
src/test/ui/cfg_attr_path.stderr [deleted file]
src/test/ui/chalkify/lower_trait.rs
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-crate-2.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-false.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-true.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-parse.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-parse.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-empty-codemap.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-in-crate-1.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-in-crate-1.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-non-opt-expr.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_attr_path.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_attr_path.stderr [new file with mode: 0644]
src/test/ui/consts/auxiliary/const_fn_lib.rs
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
src/test/ui/consts/const-eval/issue-43197.rs
src/test/ui/consts/const-eval/issue-43197.stderr
src/test/ui/consts/const-eval/issue-47971.rs
src/test/ui/consts/const-eval/transmute-const.rs
src/test/ui/consts/const-eval/ub-enum.stderr
src/test/ui/consts/const-eval/ub-nonnull.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-nonnull.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-ref.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-ref.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-uninhabit.rs
src/test/ui/consts/const-eval/ub-uninhabit.stderr
src/test/ui/consts/const-eval/ub-usize-in-ref.rs [deleted file]
src/test/ui/consts/const-eval/union-ice.stderr
src/test/ui/consts/const-eval/union-ub-fat-ptr.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/union-ub.rs
src/test/ui/consts/const-eval/valid-const.rs [new file with mode: 0644]
src/test/ui/consts/const-pattern-not-const-evaluable.rs
src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
src/test/ui/consts/min_const_fn/min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
src/test/ui/consts/min_const_fn/promotion.nll.stderr
src/test/ui/consts/min_const_fn/promotion.rs
src/test/ui/consts/min_const_fn/promotion.stderr
src/test/ui/did_you_mean/issue-38147-2.nll.stderr
src/test/ui/did_you_mean/issue-38147-3.nll.stderr
src/test/ui/extern/external-doc-error.rs
src/test/ui/extern/external-doc-error.stderr
src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs [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
src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
src/test/ui/feature-gates/feature-gate-tool_lints-fail.rs [deleted file]
src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-tool_lints.rs [deleted file]
src/test/ui/feature-gates/feature-gate-tool_lints.stderr [deleted file]
src/test/ui/impl-trait/existential-minimal.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-42479.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-49376.rs [new file with mode: 0644]
src/test/ui/infinite/infinite-recursion-const-fn.rs
src/test/ui/infinite/infinite-recursion-const-fn.stderr
src/test/ui/inline-asm-bad-operand.rs [new file with mode: 0644]
src/test/ui/inline-asm-bad-operand.stderr [new file with mode: 0644]
src/test/ui/issue-49556.rs [new file with mode: 0644]
src/test/ui/issues/issue-10291.nll.stderr
src/test/ui/issues/issue-14227.rs
src/test/ui/issues/issue-14227.stderr
src/test/ui/issues/issue-20801.nll.stderr
src/test/ui/issues/issue-24338.rs [new file with mode: 0644]
src/test/ui/issues/issue-28134.rs [new file with mode: 0644]
src/test/ui/issues/issue-28134.stderr [new file with mode: 0644]
src/test/ui/issues/issue-28822.rs
src/test/ui/issues/issue-29743.rs [new file with mode: 0644]
src/test/ui/issues/issue-40510-1.nll.stderr
src/test/ui/issues/issue-40510-3.nll.stderr
src/test/ui/issues/issue-49824.nll.stderr
src/test/ui/lint/lint-dead-code-1.rs
src/test/ui/lint/lint-dead-code-1.stderr
src/test/ui/macros/macros-nonfatal-errors.rs
src/test/ui/macros/macros-nonfatal-errors.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-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/issue-52663-trait-object.rs [new file with mode: 0644]
src/test/ui/nll/issue-52663-trait-object.stderr [new file with mode: 0644]
src/test/ui/nll/issue-53040.rs [new file with mode: 0644]
src/test/ui/nll/issue-53040.stderr [new file with mode: 0644]
src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr [new file with mode: 0644]
src/test/ui/range/issue-54505-no-literals.fixed [new file with mode: 0644]
src/test/ui/range/issue-54505-no-literals.rs [new file with mode: 0644]
src/test/ui/range/issue-54505-no-literals.stderr [new file with mode: 0644]
src/test/ui/range/issue-54505-no-std.rs [new file with mode: 0644]
src/test/ui/range/issue-54505-no-std.stderr [new file with mode: 0644]
src/test/ui/range/issue-54505.fixed [new file with mode: 0644]
src/test/ui/range/issue-54505.rs [new file with mode: 0644]
src/test/ui/range/issue-54505.stderr [new file with mode: 0644]
src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr
src/test/ui/regions/regions-nested-fns.nll.stderr
src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.nll.stderr
src/test/ui/resolve/issue-54379.rs [new file with mode: 0644]
src/test/ui/resolve/issue-54379.stderr [new file with mode: 0644]
src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed [new file with mode: 0644]
src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr
src/test/ui/tool_lints-fail.rs
src/test/ui/tool_lints.rs
src/test/ui/traits/conservative_impl_trait.rs [new file with mode: 0644]
src/test/ui/union-ub-fat-ptr.rs [deleted file]
src/test/ui/union-ub-fat-ptr.stderr [deleted file]
src/test/ui/unknown-lint-tool-name.rs
src/test/ui/unsafe/unsafe-const-fn.rs
src/test/ui/unsafe/unsafe-const-fn.stderr
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri

index 08470e731d8e7390f89d8479f0d9a363089268ad..9bc750ddef5dbf317b172f935cc7cdf9e0425b63 100644 (file)
@@ -1,3 +1,11 @@
+Version 1.29.2 (2018-10-11)
+===========================
+
+- [Workaround for an aliasing-related LLVM bug, which caused miscompilation.][54639]
+- The `rls-preview` component on the windows-gnu targets has been restored.
+
+[54639]: https://github.com/rust-lang/rust/pull/54639
+
 Version 1.29.1 (2018-09-25)
 ===========================
 
index 312270532affc7bbaaaa1001f0effeb1bd229055..1c851999130a0213ae5daded08d1e8eda4f637ae 100644 (file)
 # =============================================================================
 [rust]
 
-# Indicates that the build should be optimized for debugging Rust. Note that
-# this is typically not what you want as it takes an incredibly large amount of
-# time to have a debug-mode rustc compile any code (notably libstd). If this
-# value is set to `true` it will affect a number of configuration options below
-# as well, if unconfigured.
-#debug = false
-
-# Whether or not to optimize the compiler and standard library
+# Whether or not to optimize the compiler and standard library.
+#
 # Note: the slowness of the non optimized compiler compiling itself usually
 #       outweighs the time gains in not doing optimizations, therefore a
-#       full bootstrap takes much more time with optimize set to false.
+#       full bootstrap takes much more time with `optimize` set to false.
 #optimize = true
 
+# Indicates that the build should be configured for debugging Rust. A
+# `debug`-enabled compiler and standard library will be somewhat
+# slower (due to e.g. checking of debug assertions) but should remain
+# usable.
+#
+# Note: If this value is set to `true`, it will affect a number of
+#       configuration options below as well, if they have been left
+#       unconfigured in this file.
+#
+# Note: changes to the `debug` setting do *not* affect `optimize`
+#       above. In theory, a "maximally debuggable" environment would
+#       set `optimize` to `false` above to assist the introspection
+#       facilities of debuggers like lldb and gdb. To recreate such an
+#       environment, explicitly set `optimize` to `false` and `debug`
+#       to `true`. In practice, everyone leaves `optimize` set to
+#       `true`, because an unoptimized rustc with debugging
+#       enabled becomes *unusably slow* (e.g. rust-lang/rust#24840
+#       reported a 25x slowdown) and bootstrapping the supposed
+#       "maximally debuggable" environment (notably libstd) takes
+#       hours to build.
+#
+#debug = false
+
 # Number of codegen units to use for each compiler invocation. A value of 0
 # means "the number of cores on this machine", and 1+ is passed through to the
 # compiler.
index 6a9488226b1bdc61a35479268dcce8fee9cfaf16..c01086b3f6f2b42cc809401afbf94fbfdd979f82 100644 (file)
@@ -270,7 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "chalk-engine"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1269,7 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "minifier"
-version = "0.0.19"
+version = "0.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1898,7 +1898,7 @@ dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
@@ -2434,7 +2434,7 @@ name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -2484,7 +2484,7 @@ dependencies = [
 name = "rustdoc"
 version = "0.0.0"
 dependencies = [
- "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3195,7 +3195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
 "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
 "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
-"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0"
+"checksum chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6749eb72e7d4355d944a99f15fbaea701b978c18c5e184a025fcde942b0c9779"
 "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
 "checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37"
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
@@ -3289,7 +3289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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 minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
 "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
 "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
index c3fbc8eeca6ba65ee428f6cff468f05283334219..a5ed096a735810b09a0304faa53686c3aa1bac33 100644 (file)
@@ -628,6 +628,9 @@ pub fn parse(args: &[String]) -> Config {
         let default = false;
         config.llvm_assertions = llvm_assertions.unwrap_or(default);
 
+        let default = true;
+        config.rust_optimize = optimize.unwrap_or(default);
+
         let default = match &config.channel[..] {
             "stable" | "beta" | "nightly" => true,
             _ => false,
@@ -640,7 +643,6 @@ pub fn parse(args: &[String]) -> Config {
         config.debug_jemalloc = debug_jemalloc.unwrap_or(default);
         config.rust_debuginfo = debuginfo.unwrap_or(default);
         config.rust_debug_assertions = debug_assertions.unwrap_or(default);
-        config.rust_optimize = optimize.unwrap_or(!default);
 
         let default = config.channel == "dev";
         config.ignore_git = ignore_git.unwrap_or(default);
index 75c18cd2dd41c81ac8041ce97a29524a4a5b36f5..247727762d16e7efcf1fbfa06e3ff14835b2a565 100644 (file)
@@ -278,10 +278,6 @@ pub struct Build {
     initial_rustc: PathBuf,
     initial_cargo: PathBuf,
 
-    // Probed tools at runtime
-    lldb_version: Option<String>,
-    lldb_python_dir: Option<String>,
-
     // Runtime state filled in later on
     // C/C++ compilers and archiver for all targets
     cc: HashMap<Interned<String>, cc::Tool>,
@@ -416,8 +412,6 @@ pub fn new(config: Config) -> Build {
             ar: HashMap::new(),
             ranlib: HashMap::new(),
             crates: HashMap::new(),
-            lldb_version: None,
-            lldb_python_dir: None,
             is_sudo,
             ci_env: CiEnv::current(),
             delayed_failures: RefCell::new(Vec::new()),
index c2610de23bebadf6678a5c5bf7187b3311398dd2..724cb5841f48f1e975861dede918b5d7bc71779e 100644 (file)
@@ -236,19 +236,6 @@ pub fn check(build: &mut Build) {
         }
     }
 
-    let run = |cmd: &mut Command| {
-        cmd.output().map(|output| {
-            String::from_utf8_lossy(&output.stdout)
-                   .lines().next().unwrap_or_else(|| {
-                       panic!("{:?} failed {:?}", cmd, output)
-                   }).to_string()
-        })
-    };
-    build.lldb_version = run(Command::new("lldb").arg("--version")).ok();
-    if build.lldb_version.is_some() {
-        build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok();
-    }
-
     if let Some(ref s) = build.config.ccache {
         cmd_finder.must_have(s);
     }
index 0c4816dc90458e291d28a9abd4cd82ef2a861ee8..633c15b54b9ef22298a6e7b47f862b57531ec399 100644 (file)
@@ -1082,11 +1082,34 @@ fn run(self, builder: &Builder) {
         if let Some(ref gdb) = builder.config.gdb {
             cmd.arg("--gdb").arg(gdb);
         }
-        if let Some(ref vers) = builder.lldb_version {
+
+        let run = |cmd: &mut Command| {
+            cmd.output().map(|output| {
+                String::from_utf8_lossy(&output.stdout)
+                    .lines().next().unwrap_or_else(|| {
+                        panic!("{:?} failed {:?}", cmd, output)
+                    }).to_string()
+            })
+        };
+        let lldb_exe = if builder.config.lldb_enabled && !target.contains("emscripten") {
+            // Test against the lldb that was just built.
+            builder.llvm_out(target)
+                .join("bin")
+                .join("lldb")
+        } else {
+            PathBuf::from("lldb")
+        };
+        let lldb_version = Command::new(&lldb_exe)
+            .arg("--version")
+            .output()
+            .map(|output| { String::from_utf8_lossy(&output.stdout).to_string() })
+            .ok();
+        if let Some(ref vers) = lldb_version {
             cmd.arg("--lldb-version").arg(vers);
-        }
-        if let Some(ref dir) = builder.lldb_python_dir {
-            cmd.arg("--lldb-python-dir").arg(dir);
+            let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok();
+            if let Some(ref dir) = lldb_python_dir {
+                cmd.arg("--lldb-python-dir").arg(dir);
+            }
         }
 
         // Get paths from cmd args
index f404aa046c1aecf52bb34b3e4d14d2eae7c9a8ce..d26fcfc0168d7676138a74ac2ef336b115268b30 100644 (file)
@@ -5,6 +5,28 @@
 #TOC { display: none; }
 .header-section-number { display: none; }
 li {list-style-type: none; }
+#search-input {
+    width: calc(100% - 100px);
+}
+#search-but {
+    cursor: pointer;
+}
+#search-but, #search-input {
+    padding: 4px;
+    border: 1px solid #ccc;
+    border-radius: 3px;
+    outline: none;
+    font-size: 0.7em;
+    background-color: #fff;
+}
+#search-but:hover, #search-input:focus {
+    border-color: #55a9ff;
+}
+#search-from {
+    border: none;
+    padding: 0;
+    font-size: 0.7em;
+}
 </style>
 
 Looks like you've taken a wrong turn.
@@ -13,11 +35,20 @@ Some things that might be helpful to you though:
 
 # Search
 
-<form action="https://duckduckgo.com/">
-    <input type="text" id="site-search" name="q" size="80"></input>
-    <input type="submit" value="Search DuckDuckGo"></form>
-
-Rust doc search: <span id="core-search"></span>
+<div>
+  <form id="search-form" action="https://duckduckgo.com/">
+    <input id="search-input" type="search" name="q"></input>
+    <input type="submit" value="Search" id="search-but">
+    <!--
+      Don't show the options by default,
+      since "From the Standary Library" doesn't work without JavaScript
+    -->
+    <fieldset id="search-from" style="display:none">
+      <label><input name="from" value="library" type="radio"> From the Standard Library</label>
+      <label><input name="from" value="duckduckgo" type="radio" checked> From DuckDuckGo</label>
+    </fieldset>
+  </form>
+</div>
 
 # Reference
 
@@ -44,26 +75,28 @@ function get_url_fragments() {
     return op;
 }
 
-function populate_site_search() {
-    var op = get_url_fragments();
+function on_submit(event) {
+    var form = event.target;
+    var q = form['q'].value;
+
+    event.preventDefault();
 
-    var search = document.getElementById('site-search');
-    search.value = op.join(' ') + " site:doc.rust-lang.org";
+    if (form['from'].value === 'duckduckgo') {
+        document.location.href = form.action + '?q=' + encodeURIComponent(q + ' site:doc.rust-lang.org');
+    } else if (form['from'].value === 'library') {
+        document.location.href = 'std/index.html?search=' + encodeURIComponent(q);
+    }
 }
 
-function populate_rust_search() {
-    var op = get_url_fragments();
-    var lt = op.pop();
+function populate_search() {
+    var form = document.getElementById('search-form');
+    form.addEventListener('submit', on_submit);
+    document.getElementById('search-from').style.display = '';
 
-    // #18540, use a single token
+    form['from'].value = 'library';
 
-    var a = document.createElement("a");
-    a.href = "https://doc.rust-lang.org/core/?search=" + encodeURIComponent(lt);
-    a.textContent = lt;
-    var search = document.getElementById('core-search');
-    search.innerHTML = "";
-    search.appendChild(a);
+    var op = get_url_fragments();
+    document.getElementById('search-input').value = op.join(' ');
 }
-populate_site_search();
-populate_rust_search();
+populate_search();
 </script>
diff --git a/src/doc/unstable-book/src/language-features/cfg-attr-multi.md b/src/doc/unstable-book/src/language-features/cfg-attr-multi.md
new file mode 100644 (file)
index 0000000..6365d3e
--- /dev/null
@@ -0,0 +1,20 @@
+# `cfg_attr_multi`
+
+The tracking issue for this feature is: [#54881]
+The RFC for this feature is: [#2539]
+
+[#54881]: https://github.com/rust-lang/rust/issues/54881
+[#2539]: https://github.com/rust-lang/rfcs/pull/2539
+
+------------------------
+
+This feature flag lets you put multiple attributes into a `cfg_attr` attribute.
+
+Example:
+
+```rust,ignore
+#[cfg_attr(all(), must_use, optimize)]
+```
+
+Because `cfg_attr` resolves before procedural macros, this does not affect
+macro resolution at all.
\ No newline at end of file
diff --git a/src/doc/unstable-book/src/language-features/tool-lints.md b/src/doc/unstable-book/src/language-features/tool-lints.md
deleted file mode 100644 (file)
index 5c0d33b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-# `tool_lints`
-
-The tracking issue for this feature is: [#44690]
-
-[#44690]: https://github.com/rust-lang/rust/issues/44690
-
-------------------------
-
-Tool lints let you use scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of
-certain tools.
-
-Currently `clippy` is the only available lint tool.
-
-It is recommended for lint tools to implement the scoped lints like this:
-
-- `#[_(TOOL_NAME::lintname)]`: for lint names
-- `#[_(TOOL_NAME::lintgroup)]`: for groups of lints
-- `#[_(TOOL_NAME::all)]`: for (almost[^1]) all lints
-
-## An example
-
-```rust
-#![feature(tool_lints)]
-
-#![warn(clippy::pedantic)]
-
-#[allow(clippy::filter_map)]
-fn main() {
-    let v = vec![0; 10];
-    let _ = v.into_iter().filter(|&x| x < 1).map(|x| x + 1).collect::<Vec<_>>();
-    println!("No filter_map()!");
-}
-```
-
-[^1]: Some defined lint groups can be excluded here.
index 216915dba5fe7c03116d1cf2906afd7bbafe392f..b1252f386df364dcd18708dc5bc6139fe465e0dd 100755 (executable)
@@ -322,8 +322,11 @@ class RustStdBTreeSetPrinter(object):
     def children(self):
         (length, data_ptr) = \
             rustpp.extract_length_and_ptr_from_std_btreeset(self.__val)
-        val = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3)
-        gdb_ptr = val.get_wrapped_value()
+        leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference())
+        maybe_uninit_keys = leaf_node.get_child_at_index(3)
+        manually_drop_keys = maybe_uninit_keys.get_child_at_index(1)
+        keys = manually_drop_keys.get_child_at_index(0)
+        gdb_ptr = keys.get_wrapped_value()
         for index in xrange(length):
             yield (str(index), gdb_ptr[index])
 
@@ -345,9 +348,14 @@ class RustStdBTreeMapPrinter(object):
     def children(self):
         (length, data_ptr) = \
             rustpp.extract_length_and_ptr_from_std_btreemap(self.__val)
-        keys = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3)
+        leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference())
+        maybe_uninit_keys = leaf_node.get_child_at_index(3)
+        manually_drop_keys = maybe_uninit_keys.get_child_at_index(1)
+        keys = manually_drop_keys.get_child_at_index(0)
         keys_ptr = keys.get_wrapped_value()
-        vals = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(4)
+        maybe_uninit_vals = leaf_node.get_child_at_index(4)
+        manually_drop_vals = maybe_uninit_vals.get_child_at_index(1)
+        vals = manually_drop_vals.get_child_at_index(0)
         vals_ptr = vals.get_wrapped_value()
         for index in xrange(length):
             yield (str(index), keys_ptr[index])
index 0315545262b6bc0a295953f22b4328070223356b..deca9591fbd5c499210a17f6ed67990eda11fae3 100644 (file)
@@ -42,7 +42,7 @@
 //   This implies that even an empty internal node has at least one edge.
 
 use core::marker::PhantomData;
-use core::mem;
+use core::mem::{self, MaybeUninit};
 use core::ptr::{self, Unique, NonNull};
 use core::slice;
 
@@ -58,9 +58,6 @@
 /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
 /// case.
 ///
-/// See also rust-lang/rfcs#197, which would make this structure significantly more safe by
-/// avoiding accidentally dropping unused and uninitialized keys and values.
-///
 /// We put the metadata first so that its position is the same for every `K` and `V`, in order
 /// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
 /// prevent them from being reordered.
@@ -73,7 +70,7 @@ struct LeafNode<K, V> {
     /// This node's index into the parent node's `edges` array.
     /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
     /// This is only guaranteed to be initialized when `parent` is nonnull.
-    parent_idx: u16,
+    parent_idx: MaybeUninit<u16>,
 
     /// The number of keys and values this node stores.
     ///
@@ -83,8 +80,8 @@ struct LeafNode<K, V> {
 
     /// The arrays storing the actual data of the node. Only the first `len` elements of each
     /// array are initialized and valid.
-    keys: [K; CAPACITY],
-    vals: [V; CAPACITY],
+    keys: MaybeUninit<[K; CAPACITY]>,
+    vals: MaybeUninit<[V; CAPACITY]>,
 }
 
 impl<K, V> LeafNode<K, V> {
@@ -94,10 +91,10 @@ unsafe fn new() -> Self {
         LeafNode {
             // As a general policy, we leave fields uninitialized if they can be, as this should
             // be both slightly faster and easier to track in Valgrind.
-            keys: mem::uninitialized(),
-            vals: mem::uninitialized(),
+            keys: MaybeUninit::uninitialized(),
+            vals: MaybeUninit::uninitialized(),
             parent: ptr::null(),
-            parent_idx: mem::uninitialized(),
+            parent_idx: MaybeUninit::uninitialized(),
             len: 0
         }
     }
@@ -115,10 +112,10 @@ unsafe impl Sync for LeafNode<(), ()> {}
 // ever take a pointer past the first key.
 static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
     parent: ptr::null(),
-    parent_idx: 0,
+    parent_idx: MaybeUninit::uninitialized(),
     len: 0,
-    keys: [(); CAPACITY],
-    vals: [(); CAPACITY],
+    keys: MaybeUninit::uninitialized(),
+    vals: MaybeUninit::uninitialized(),
 };
 
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
@@ -430,7 +427,7 @@ pub fn ascend(self) -> Result<
                     root: self.root,
                     _marker: PhantomData
                 },
-                idx: self.as_leaf().parent_idx as usize,
+                idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
                 _marker: PhantomData
             })
         } else {
@@ -567,7 +564,7 @@ fn into_key_slice(self) -> &'a [K] {
             // the node, which is allowed by LLVM.
             unsafe {
                 slice::from_raw_parts(
-                    self.as_leaf().keys.as_ptr(),
+                    self.as_leaf().keys.as_ptr() as *const K,
                     self.len()
                 )
             }
@@ -578,7 +575,7 @@ fn into_val_slice(self) -> &'a [V] {
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts(
-                self.as_leaf().vals.as_ptr(),
+                self.as_leaf().vals.as_ptr() as *const V,
                 self.len()
             )
         }
@@ -605,7 +602,7 @@ fn into_key_slice_mut(mut self) -> &'a mut [K] {
         } else {
             unsafe {
                 slice::from_raw_parts_mut(
-                    &mut self.as_leaf_mut().keys as *mut [K] as *mut K,
+                    self.as_leaf_mut().keys.get_mut() as *mut [K] as *mut K,
                     self.len()
                 )
             }
@@ -616,7 +613,7 @@ fn into_val_slice_mut(mut self) -> &'a mut [V] {
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts_mut(
-                &mut self.as_leaf_mut().vals as *mut [V] as *mut V,
+                self.as_leaf_mut().vals.get_mut() as *mut [V] as *mut V,
                 self.len()
             )
         }
@@ -1013,7 +1010,7 @@ fn correct_parent_link(mut self) {
         let ptr = self.node.as_internal_mut() as *mut _;
         let mut child = self.descend();
         child.as_leaf_mut().parent = ptr;
-        child.as_leaf_mut().parent_idx = idx;
+        child.as_leaf_mut().parent_idx.set(idx);
     }
 
     /// Unsafely asserts to the compiler some static information about whether the underlying
@@ -1152,12 +1149,12 @@ pub fn split(mut self)
 
             ptr::copy_nonoverlapping(
                 self.node.keys().as_ptr().add(self.idx + 1),
-                new_node.keys.as_mut_ptr(),
+                new_node.keys.as_mut_ptr() as *mut K,
                 new_len
             );
             ptr::copy_nonoverlapping(
                 self.node.vals().as_ptr().add(self.idx + 1),
-                new_node.vals.as_mut_ptr(),
+                new_node.vals.as_mut_ptr() as *mut V,
                 new_len
             );
 
@@ -1210,12 +1207,12 @@ pub fn split(mut self)
 
             ptr::copy_nonoverlapping(
                 self.node.keys().as_ptr().add(self.idx + 1),
-                new_node.data.keys.as_mut_ptr(),
+                new_node.data.keys.as_mut_ptr() as *mut K,
                 new_len
             );
             ptr::copy_nonoverlapping(
                 self.node.vals().as_ptr().add(self.idx + 1),
-                new_node.data.vals.as_mut_ptr(),
+                new_node.data.vals.as_mut_ptr() as *mut V,
                 new_len
             );
             ptr::copy_nonoverlapping(
index 5f9ceb8599cf51321e4c15542d6708004d2fc7ef..987572e6b74a9c2dbb803b60aafb2e7f503798bd 100644 (file)
@@ -86,7 +86,7 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
-#![feature(min_const_fn)]
+#![cfg_attr(stage0, feature(min_const_fn))]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
 #![feature(rustc_const_unstable)]
 #![feature(const_vec_new)]
 #![feature(slice_partition_dedup)]
+#![feature(maybe_uninit)]
 
 // Allow testing this library
 
index 2af89562d69fe1d0a6f37c07350c212117c8b131..9916fa639e1d484acbcea4ec7bafcb2a62327f3a 100644 (file)
@@ -203,6 +203,7 @@ fn borrow(&self) -> &str {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToOwned for str {
     type Owned = String;
+    #[inline]
     fn to_owned(&self) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
     }
index 837e17cf640173b127fce5cd2758c1ad361e9aa7..ab3f8fc27072071c754c842094d57b295e441dbc 100644 (file)
@@ -2196,6 +2196,7 @@ fn as_ref(&self) -> &[u8] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&'a str> for String {
+    #[inline]
     fn from(s: &'a str) -> String {
         s.to_owned()
     }
index b9ba319a943caa9d76644d8f12f3538444884d67..c771c41dc3ed318203813deb68bfad8b539fcb77 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(allocator_api)]
 #![feature(alloc_system)]
 #![feature(box_syntax)]
-#![feature(min_const_fn)]
+#![cfg_attr(stage0, feature(min_const_fn))]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
 #![feature(pattern)]
index 2bc037e3fee126343715212911c8b62e1d28867e..f7a0bbdceafc93325359fbb83a51b413548db0da 100644 (file)
 /// assert_eq!(vec, [1, 2, 3, 4]);
 /// ```
 ///
-/// It can also initialize each element of a `Vec<T>` with a given value:
+/// It can also initialize each element of a `Vec<T>` with a given value.
+/// This may be more efficient than performing allocation and initialization
+/// in separate steps, especially when initializing a vector of zeros:
 ///
 /// ```
 /// let vec = vec![0; 5];
 /// assert_eq!(vec, [0, 0, 0, 0, 0]);
+///
+/// // The following is equivalent, but potentially slower:
+/// let mut vec1 = Vec::with_capacity(5);
+/// vec1.resize(5, 0);
 /// ```
 ///
 /// Use a `Vec<T>` as an efficient stack:
index 0255f7a0885ead6d69c17ee72a4d8b12d8f26990..cf1c77041b91fe24dcf4e92361ad7f018a26cee1 100644 (file)
@@ -867,8 +867,6 @@ pub fn take(&mut self) -> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(option_replace)]
-    ///
     /// let mut x = Some(2);
     /// let old = x.replace(5);
     /// assert_eq!(x, Some(5));
@@ -880,7 +878,7 @@ pub fn take(&mut self) -> Option<T> {
     /// assert_eq!(old, None);
     /// ```
     #[inline]
-    #[unstable(feature = "option_replace", issue = "51998")]
+    #[stable(feature = "option_replace", since = "1.31.0")]
     pub fn replace(&mut self, value: T) -> Option<T> {
         mem::replace(self, Some(value))
     }
index bd58dcf4ae055fd9578608f71b87919ccbb8658b..b8d7fcffbcc0968922dc2ed3d5786a0c70efb4be 100644 (file)
@@ -2370,13 +2370,13 @@ fn mod_inv(x: usize, m: usize) -> usize {
         ///
         /// Note, that this table does not contain values where inverse does not exist (i.e. for
         /// `0⁻¹ mod 16`, `2⁻¹ mod 16`, etc.)
-        const INV_TABLE_MOD_16: [usize; 8] = [1, 11, 13, 7, 9, 3, 5, 15];
+        const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15];
         /// Modulo for which the `INV_TABLE_MOD_16` is intended.
         const INV_TABLE_MOD: usize = 16;
         /// INV_TABLE_MOD²
         const INV_TABLE_MOD_SQUARED: usize = INV_TABLE_MOD * INV_TABLE_MOD;
 
-        let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1];
+        let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1] as usize;
         if m <= INV_TABLE_MOD {
             table_inverse & (m - 1)
         } else {
@@ -2429,36 +2429,23 @@ fn mod_inv(x: usize, m: usize) -> usize {
     let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a));
     let gcd = 1usize << gcdpow;
 
-    if gcd == 1 {
-        // This branch solves for the variable $o$ in following linear congruence equation:
-        //
-        // ⎰ p + o ≡ 0 (mod a)   # $p + o$ must be aligned to specified alignment $a$
-        // ⎱     o ≡ 0 (mod s)   # offset $o$ must be a multiple of stride $s$
-        //
-        // where
+    if p as usize & (gcd - 1) == 0 {
+        // This branch solves for the following linear congruence equation:
         //
-        // * a, s are co-prime
+        // $$ p + so ≡ 0 mod a $$
         //
-        // This gives us the formula below:
+        // $p$ here is the pointer value, $s$ – stride of `T`, $o$ offset in `T`s, and $a$ – the
+        // requested alignment.
         //
-        // o = (a - (p mod a)) * (s⁻¹ mod a) * s
+        // g = gcd(a, s)
+        // o = (a - (p mod a))/g * ((s/g)⁻¹ mod a)
         //
         // The first term is “the relative alignment of p to a”, the second term is “how does
-        // incrementing p by one s change the relative alignment of p”, the third term is
-        // translating change in units of s to a byte count.
+        // incrementing p by s bytes change the relative alignment of p”. Division by `g` is
+        // necessary to make this equation well formed if $a$ and $s$ are not co-prime.
         //
         // Furthermore, the result produced by this solution is not “minimal”, so it is necessary
-        // to take the result $o mod lcm(s, a)$. Since $s$ and $a$ are co-prime (i.e. $gcd(s, a) =
-        // 1$) and $lcm(s, a) = s * a / gcd(s, a)$, we can replace $lcm(s, a)$ with just a $s * a$.
-        //
-        // (Author note: we decided later on to express the offset in "elements" rather than bytes,
-        // which drops the multiplication by `s` on both sides of the modulo.)
-        return intrinsics::unchecked_rem(a.wrapping_sub(pmoda).wrapping_mul(mod_inv(smoda, a)), a);
-    }
-
-    if p as usize & (gcd - 1) == 0 {
-        // This can be aligned, but `a` and `stride` are not co-prime, so a somewhat adapted
-        // formula is used.
+        // to take the result $o mod lcm(s, a)$. We can replace $lcm(s, a)$ with just a $a / g$.
         let j = a.wrapping_sub(pmoda) >> gcdpow;
         let k = smoda >> gcdpow;
         return intrinsics::unchecked_rem(j.wrapping_mul(mod_inv(k, a)), a >> gcdpow);
index a50426ba886bb0e71b9d940f3c3cf28b39e8c01d..c9013f589edd36eb9159d62b9a3c7bae9106d69d 100644 (file)
@@ -1175,9 +1175,10 @@ pub fn ends_with(&self, needle: &[T]) -> bool
 
     /// Binary searches this sorted slice for a given element.
     ///
-    /// If the value is found then `Ok` is returned, containing the
-    /// index of the matching element; if the value is not found then
-    /// `Err` is returned, containing the index where a matching
+    /// If the value is found then [`Result::Ok`] is returned, containing the
+    /// index of the matching element. If there are multiple matches, then any
+    /// one of the matches could be returned. If the value is not found then
+    /// [`Result::Err`] is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
     /// # Examples
@@ -1209,9 +1210,10 @@ pub fn binary_search(&self, x: &T) -> Result<usize, usize>
     /// order code that indicates whether its argument is `Less`,
     /// `Equal` or `Greater` the desired target.
     ///
-    /// If a matching value is found then returns `Ok`, containing
-    /// the index for the matched element; if no match is found then
-    /// `Err` is returned, containing the index where a matching
+    /// If the value is found then [`Result::Ok`] is returned, containing the
+    /// index of the matching element. If there are multiple matches, then any
+    /// one of the matches could be returned. If the value is not found then
+    /// [`Result::Err`] is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
     /// # Examples
@@ -1265,10 +1267,11 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
     /// Assumes that the slice is sorted by the key, for instance with
     /// [`sort_by_key`] using the same key extraction function.
     ///
-    /// If a matching value is found then returns `Ok`, containing the
-    /// index for the matched element; if no match is found then `Err`
-    /// is returned, containing the index where a matching element could
-    /// be inserted while maintaining sorted order.
+    /// If the value is found then [`Result::Ok`] is returned, containing the
+    /// index of the matching element. If there are multiple matches, then any
+    /// one of the matches could be returned. If the value is not found then
+    /// [`Result::Err`] is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
     ///
     /// [`sort_by_key`]: #method.sort_by_key
     ///
@@ -1929,7 +1932,7 @@ fn align_to_offsets<U>(&self) -> (usize, usize) {
         fn gcd(a: usize, b: usize) -> usize {
             // iterative stein’s algorithm
             // We should still make this `const fn` (and revert to recursive algorithm if we do)
-            // because relying on llvm to consteval all this is… well, it makes me
+            // because relying on llvm to consteval all this is… well, it makes me uncomfortable.
             let (ctz_a, mut ctz_b) = unsafe {
                 if a == 0 { return b; }
                 if b == 0 { return a; }
index 651db6356ba07e93bd727adb9ed81932a3492fc8..ab4ae50c44367f3dce204ba60a4572cf60993e7d 100644 (file)
@@ -12,7 +12,7 @@
             reason = "futures in libcore are unstable",
             issue = "50547")]
 
-use {fmt, mem};
+use fmt;
 use marker::Unpin;
 use ptr::NonNull;
 
@@ -63,6 +63,20 @@ pub fn wake(&self) {
     pub fn will_wake(&self, other: &Waker) -> bool {
         self.inner == other.inner
     }
+
+    /// Returns whether or not this `Waker` and `other` `LocalWaker` awaken
+    /// the same task.
+    ///
+    /// This function works on a best-effort basis, and may return false even
+    /// when the `Waker`s would awaken the same task. However, if this function
+    /// returns true, it is guaranteed that the `Waker`s will awaken the same
+    /// task.
+    ///
+    /// This function is primarily used for optimization purposes.
+    #[inline]
+    pub fn will_wake_local(&self, other: &LocalWaker) -> bool {
+        self.will_wake(&other.0)
+    }
 }
 
 impl Clone for Waker {
@@ -97,9 +111,8 @@ fn drop(&mut self) {
 /// Task executors can use this type to implement more optimized singlethreaded wakeup
 /// behavior.
 #[repr(transparent)]
-pub struct LocalWaker {
-    inner: NonNull<dyn UnsafeWake>,
-}
+#[derive(Clone)]
+pub struct LocalWaker(Waker);
 
 impl Unpin for LocalWaker {}
 impl !Send for LocalWaker {}
@@ -120,7 +133,16 @@ impl LocalWaker {
     /// on the current thread.
     #[inline]
     pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
-        LocalWaker { inner }
+        LocalWaker(Waker::new(inner))
+    }
+
+    /// Borrows this `LocalWaker` as a `Waker`.
+    ///
+    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
+    /// (implements `Send` and `Sync`).
+    #[inline]
+    pub fn as_waker(&self) -> &Waker {
+        &self.0
     }
 
     /// Converts this `LocalWaker` into a `Waker`.
@@ -129,13 +151,13 @@ pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
     /// (implements `Send` and `Sync`).
     #[inline]
     pub fn into_waker(self) -> Waker {
-        self.into()
+        self.0
     }
 
     /// Wake up the task associated with this `LocalWaker`.
     #[inline]
     pub fn wake(&self) {
-        unsafe { self.inner.as_ref().wake_local() }
+        unsafe { self.0.inner.as_ref().wake_local() }
     }
 
     /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
@@ -148,7 +170,7 @@ pub fn wake(&self) {
     /// This function is primarily used for optimization purposes.
     #[inline]
     pub fn will_wake(&self, other: &LocalWaker) -> bool {
-        self.inner == other.inner
+        self.0.will_wake(&other.0)
     }
 
     /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task.
@@ -161,45 +183,24 @@ pub fn will_wake(&self, other: &LocalWaker) -> bool {
     /// This function is primarily used for optimization purposes.
     #[inline]
     pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
-        self.inner == other.inner
+        self.0.will_wake(other)
     }
 }
 
 impl From<LocalWaker> for Waker {
     #[inline]
     fn from(local_waker: LocalWaker) -> Self {
-        let inner = local_waker.inner;
-        mem::forget(local_waker);
-        Waker { inner }
-    }
-}
-
-impl Clone for LocalWaker {
-    #[inline]
-    fn clone(&self) -> Self {
-        let waker = unsafe { self.inner.as_ref().clone_raw() };
-        let inner = waker.inner;
-        mem::forget(waker);
-        LocalWaker { inner }
+        local_waker.0
     }
 }
 
 impl fmt::Debug for LocalWaker {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Waker")
+        f.debug_struct("LocalWaker")
             .finish()
     }
 }
 
-impl Drop for LocalWaker {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            self.inner.as_ref().drop_raw()
-        }
-    }
-}
-
 /// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
 ///
 /// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
index ada61d8dfd8739129a5d9cb83313dd738b393a33..0beb60a127097b18204197aa7491b321cd717792 100644 (file)
@@ -39,7 +39,6 @@
 #![feature(reverse_bits)]
 #![feature(inner_deref)]
 #![feature(slice_internals)]
-#![feature(option_replace)]
 #![feature(slice_partition_dedup)]
 #![feature(copy_within)]
 
index 7acadc32048bd8a49627ae0d0a107a42bc9eaa36..396b0366074b2ebe4ba739662d765900b9e273bb 100644 (file)
@@ -49,7 +49,6 @@
 //! ```rust
 //! #![feature(rustc_private)]
 //!
-//! use graphviz::IntoCow;
 //! use std::io::Write;
 //! use graphviz as dot;
 //!
 //!         }
 //!         nodes.sort();
 //!         nodes.dedup();
-//!         nodes.into_cow()
+//!         nodes.into()
 //!     }
 //!
 //!     fn edges(&'a self) -> dot::Edges<'a,Ed> {
 //!         let &Edges(ref edges) = self;
-//!         (&edges[..]).into_cow()
+//!         (&edges[..]).into()
 //!     }
 //!
 //!     fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }
 //! Since both the set of nodes and the set of edges are always
 //! constructed from scratch via iterators, we use the `collect()` method
 //! from the `Iterator` trait to collect the nodes and edges into freshly
-//! constructed growable `Vec` values (rather use the `into_cow`
-//! from the `IntoCow` trait as was used in the first example
-//! above).
+//! constructed growable `Vec` values (rather than using `Cow` as in the
+//! first example above).
 //!
 //! The output from this example renders four nodes that make up the
 //! Hasse-diagram for the subsets of the set `{x, y}`. Each edge is
 
 use self::LabelText::*;
 
-use std::borrow::{Cow, ToOwned};
+use std::borrow::Cow;
 use std::io::prelude::*;
 use std::io;
 
@@ -411,8 +409,8 @@ impl<'a> Id<'a> {
     ///
     /// Passing an invalid string (containing spaces, brackets,
     /// quotes, ...) will return an empty `Err` value.
-    pub fn new<Name: IntoCow<'a, str>>(name: Name) -> Result<Id<'a>, ()> {
-        let name = name.into_cow();
+    pub fn new<Name: Into<Cow<'a, str>>>(name: Name) -> Result<Id<'a>, ()> {
+        let name = name.into();
         match name.chars().next() {
             Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
             _ => return Err(()),
@@ -473,7 +471,7 @@ fn node_label(&'a self, n: &Self::Node) -> LabelText<'a> {
     /// The label need not be unique, and may be the empty string; the
     /// default is in fact the empty string.
     fn edge_label(&'a self, _e: &Self::Edge) -> LabelText<'a> {
-        LabelStr("".into_cow())
+        LabelStr("".into())
     }
 
     /// Maps `n` to a style that will be used in the rendered output.
@@ -497,16 +495,16 @@ pub fn escape_html(s: &str) -> String {
 }
 
 impl<'a> LabelText<'a> {
-    pub fn label<S: IntoCow<'a, str>>(s: S) -> LabelText<'a> {
-        LabelStr(s.into_cow())
+    pub fn label<S: Into<Cow<'a, str>>>(s: S) -> LabelText<'a> {
+        LabelStr(s.into())
     }
 
-    pub fn escaped<S: IntoCow<'a, str>>(s: S) -> LabelText<'a> {
-        EscStr(s.into_cow())
+    pub fn escaped<S: Into<Cow<'a, str>>>(s: S) -> LabelText<'a> {
+        EscStr(s.into())
     }
 
-    pub fn html<S: IntoCow<'a, str>>(s: S) -> LabelText<'a> {
-        HtmlStr(s.into_cow())
+    pub fn html<S: Into<Cow<'a, str>>>(s: S) -> LabelText<'a> {
+        HtmlStr(s.into())
     }
 
     fn escape_char<F>(c: char, mut f: F)
@@ -550,7 +548,7 @@ fn pre_escaped_content(self) -> Cow<'a, str> {
             EscStr(s) => s,
             LabelStr(s) => {
                 if s.contains('\\') {
-                    (&*s).escape_default().into_cow()
+                    (&*s).escape_default().into()
                 } else {
                     s
                 }
@@ -570,7 +568,7 @@ pub fn suffix_line(self, suffix: LabelText) -> LabelText<'static> {
         let suffix = suffix.pre_escaped_content();
         prefix.push_str(r"\n\n");
         prefix.push_str(&suffix);
-        EscStr(prefix.into_cow())
+        EscStr(prefix.into())
     }
 }
 
@@ -696,40 +694,6 @@ pub fn render_opts<'a, N, E, G, W>(g: &'a G,
     writeln!(w, "}}")
 }
 
-pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
-    fn into_cow(self) -> Cow<'a, B>;
-}
-
-impl<'a> IntoCow<'a, str> for String {
-    fn into_cow(self) -> Cow<'a, str> {
-        Cow::Owned(self)
-    }
-}
-
-impl<'a> IntoCow<'a, str> for &'a str {
-    fn into_cow(self) -> Cow<'a, str> {
-        Cow::Borrowed(self)
-    }
-}
-
-impl<'a> IntoCow<'a, str> for Cow<'a, str> {
-    fn into_cow(self) -> Cow<'a, str> {
-        self
-    }
-}
-
-impl<'a, T: Clone> IntoCow<'a, [T]> for Vec<T> {
-    fn into_cow(self) -> Cow<'a, [T]> {
-        Cow::Owned(self)
-    }
-}
-
-impl<'a, T: Clone> IntoCow<'a, [T]> for &'a [T] {
-    fn into_cow(self) -> Cow<'a, [T]> {
-        Cow::Borrowed(self)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use self::NodeLabels::*;
@@ -737,7 +701,6 @@ mod tests {
     use super::LabelText::{self, LabelStr, EscStr, HtmlStr};
     use std::io;
     use std::io::prelude::*;
-    use IntoCow;
 
     /// each node is an index in a vector in the graph.
     type Node = usize;
@@ -852,12 +815,12 @@ fn node_id(&'a self, n: &Node) -> Id<'a> {
         }
         fn node_label(&'a self, n: &Node) -> LabelText<'a> {
             match self.node_labels[*n] {
-                Some(ref l) => LabelStr(l.into_cow()),
+                Some(l) => LabelStr(l.into()),
                 None => LabelStr(id_name(n).name()),
             }
         }
         fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> {
-            LabelStr(e.label.into_cow())
+            LabelStr(e.label.into())
         }
         fn node_style(&'a self, n: &Node) -> Style {
             self.node_styles[*n]
index 6c3b52196a3a2bb03c459e4f96b8a821fda5864d..d0ec8640ce9ef3edcf4a1e9aa07e42a64cbbf398 100644 (file)
@@ -31,7 +31,7 @@ syntax_pos = { path = "../libsyntax_pos" }
 backtrace = "0.3.3"
 parking_lot = "0.6"
 byteorder = { version = "1.1", features = ["i128"]}
-chalk-engine = { version = "0.7.0", default-features=false }
+chalk-engine = { version = "0.8.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
 smallvec = { version = "0.6.5", features = ["union"] }
 
index 9241240caf043b174a72fdd913d6c2bbf91b940d..cc4f3f95d079a5ab73196acbff67450ebceafb92 100644 (file)
@@ -13,7 +13,6 @@
 
 // For clarity, rename the graphviz crate locally to dot.
 use graphviz as dot;
-use graphviz::IntoCow;
 
 use cfg;
 use hir;
@@ -71,21 +70,21 @@ fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
 
     fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
         if i == self.cfg.entry {
-            dot::LabelText::LabelStr("entry".into_cow())
+            dot::LabelText::LabelStr("entry".into())
         } else if i == self.cfg.exit {
-            dot::LabelText::LabelStr("exit".into_cow())
+            dot::LabelText::LabelStr("exit".into())
         } else if n.data.id() == hir::DUMMY_ITEM_LOCAL_ID {
-            dot::LabelText::LabelStr("(dummy_node)".into_cow())
+            dot::LabelText::LabelStr("(dummy_node)".into())
         } else {
             let s = self.local_id_to_string(n.data.id());
-            dot::LabelText::EscStr(s.into_cow())
+            dot::LabelText::EscStr(s.into())
         }
     }
 
     fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
         let mut label = String::new();
         if !self.labelled_edges {
-            return dot::LabelText::EscStr(label.into_cow());
+            return dot::LabelText::EscStr(label.into());
         }
         let mut put_one = false;
         for (i, &id) in e.data.exiting_scopes.iter().enumerate() {
@@ -99,7 +98,7 @@ fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
                                    i,
                                    &s[..]));
         }
-        dot::LabelText::EscStr(label.into_cow())
+        dot::LabelText::EscStr(label.into())
     }
 }
 
@@ -109,7 +108,7 @@ impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG {
     fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
         let mut v = Vec::new();
         self.graph.each_node(|i, nd| { v.push((i, nd)); true });
-        v.into_cow()
+        v.into()
     }
     fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
         self.graph.all_edges().iter().collect()
index 9312349ee405528d6db4a5fad114f29a5841e4c3..337cc0fc627649ff22a29c90a38fe34e3281c001 100644 (file)
@@ -551,7 +551,23 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> {
     subject,
     outlived_free_region,
-    blame_span
+    blame_span,
+    category
+});
+
+impl_stable_hash_for!(enum mir::ConstraintCategory {
+    Return,
+    TypeAnnotation,
+    Cast,
+    ClosureBounds,
+    CallArgument,
+    CopyBound,
+    SizedBound,
+    Assignment,
+    OpaqueType,
+    Boring,
+    BoringNoLocation,
+    Internal,
 });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubject<'gcx> {
index 3ff0034fbbee7d850988e443c87c9922861c36e0..f51a3e71d0741f9eb68aeaa1a4f8381906aabe40 100644 (file)
@@ -391,10 +391,39 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl_stable_hash_for!(struct mir::interpret::Pointer {
-    alloc_id,
-    offset
-});
+impl<'a, Tag> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::Pointer<Tag>
+where Tag: HashStable<StableHashingContext<'a>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let ::mir::interpret::Pointer { alloc_id, offset, tag } = self;
+        alloc_id.hash_stable(hcx, hasher);
+        offset.hash_stable(hcx, hasher);
+        tag.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a, Tag> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::Scalar<Tag>
+where Tag: HashStable<StableHashingContext<'a>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use mir::interpret::Scalar::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Bits { bits, size } => {
+                bits.hash_stable(hcx, hasher);
+                size.hash_stable(hcx, hasher);
+            },
+            Ptr(ptr) => ptr.hash_stable(hcx, hasher),
+        }
+    }
+}
 
 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
     fn hash_stable<W: StableHasherResult>(
@@ -449,25 +478,6 @@ fn hash_stable<W: StableHasherResult>(
     Mutable
 });
 
-
-impl<'a> HashStable<StableHashingContext<'a>>
-for ::mir::interpret::Scalar {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        use mir::interpret::Scalar::*;
-
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            Bits { bits, size } => {
-                bits.hash_stable(hcx, hasher);
-                size.hash_stable(hcx, hasher);
-            },
-            Ptr(ptr) => ptr.hash_stable(hcx, hasher),
-        }
-    }
-}
-
 impl_stable_hash_for!(struct ty::Const<'tcx> {
     ty,
     val
@@ -560,6 +570,10 @@ fn hash_stable<W: StableHasherResult>(&self,
                 a.hash_stable(hcx, hasher);
                 b.hash_stable(hcx, hasher)
             },
+            FunctionRetMismatch(a, b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher)
+            },
             NoMirFor(ref s) => s.hash_stable(hcx, hasher),
             UnterminatedCString(ptr) => ptr.hash_stable(hcx, hasher),
             PointerOutOfBounds {
@@ -1356,7 +1370,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use traits::Goal::*;
+        use traits::GoalKind::*;
 
         mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
index 0ac9d415756308030a7f2d457c8b37caf3acf642..5519330a37427e9fa1c71bee45a9bdb7619558e7 100644 (file)
@@ -42,7 +42,7 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(min_const_fn)]
+#![cfg_attr(stage0, feature(min_const_fn))]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![cfg_attr(windows, feature(libc))]
index 87d33e473e7f6cd97bc392e3f6bf926518744264..950754a07ab09787b94e05db5ca8b381a2e9ae29 100644 (file)
 use lint::{self, Lint, LintId, Level, LintSource};
 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
-use session::{config::nightly_options, Session};
+use session::Session;
 use syntax::ast;
 use syntax::attr;
 use syntax::source_map::MultiSpan;
-use syntax::feature_gate;
 use syntax::symbol::Symbol;
 use util::nodemap::FxHashMap;
 
@@ -228,18 +227,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                     }
                 };
                 let tool_name = if let Some(lint_tool) = word.is_scoped() {
-                    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),
-                        );
-                    }
-                    if !known_tool {
+                    if !attr::is_known_lint_tool(lint_tool) {
                         span_err!(
                             sess,
                             lint_tool.span,
@@ -247,9 +235,6 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                             "an unknown tool name found in scoped lint: `{}`",
                             word.ident
                         );
-                    }
-
-                    if gate_feature || !known_tool {
                         continue;
                     }
 
@@ -299,13 +284,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                                     "change it to",
                                     new_lint_name.to_string(),
                                     Applicability::MachineApplicable,
-                                );
-
-                                if nightly_options::is_nightly_build() {
-                                    err.emit();
-                                } else {
-                                    err.cancel();
-                                }
+                                ).emit();
 
                                 let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span);
                                 for id in ids {
index 2ac185b681e48f8cad5678e685794eb49ccf0060..ea90922b11066ad0e633cf1e34caef837b456742 100644 (file)
@@ -398,7 +398,13 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       krate: &hir::Crate)
                                       -> Vec<ast::NodeId>
 {
-    let worklist = access_levels.map.iter().map(|(&id, _)| id).chain(
+    let worklist = access_levels.map.iter().filter_map(|(&id, level)| {
+        if level >= &privacy::AccessLevel::Reachable {
+            Some(id)
+        } else {
+            None
+        }
+    }).chain(
         // Seed entry point
         tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
     ).collect::<Vec<_>>();
index a10b387672ad6311a4da7e7497dbbcd17a46bd7b..2f3fdb7966f25adde4a27f6ccd3ef2f29173211c 100644 (file)
@@ -19,9 +19,9 @@
 use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use hir::map::Map;
 use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName, Node};
-use ty::{self, TyCtxt, GenericParamDefKind};
+use ty::{self, TyCtxt, DefIdTree, GenericParamDefKind};
 
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 use rustc::lint;
 use rustc_data_structures::sync::Lrc;
 use session::Session;
@@ -1398,6 +1398,30 @@ fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
         self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
     }
 
+    /// helper method to determine the span to remove when suggesting the
+    /// deletion of a lifetime
+    fn lifetime_deletion_span(&self, name: ast::Ident, generics: &hir::Generics) -> Option<Span> {
+        if generics.params.len() == 1 {
+            // if sole lifetime, remove the `<>` brackets
+            Some(generics.span)
+        } else {
+            generics.params.iter().enumerate()
+                .find_map(|(i, param)| {
+                    if param.name.ident() == name {
+                        // We also want to delete a leading or trailing comma
+                        // as appropriate
+                        if i >= generics.params.len() - 1 {
+                            Some(generics.params[i-1].span.shrink_to_hi().to(param.span))
+                        } else {
+                            Some(param.span.to(generics.params[i+1].span.shrink_to_lo()))
+                        }
+                    } else {
+                        None
+                    }
+                })
+        }
+    }
+
     fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
         let defined_by = match self.scope {
             Scope::Binder { lifetimes, .. } => lifetimes,
@@ -1468,12 +1492,26 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                         _ => None,
                     } {
                         debug!("id ={:?} span = {:?} name = {:?}", node_id, span, name);
-                        self.tcx.struct_span_lint_node(
+                        let mut err = self.tcx.struct_span_lint_node(
                             lint::builtin::UNUSED_LIFETIMES,
                             id,
                             span,
                             &format!("lifetime parameter `{}` never used", name)
-                        ).emit();
+                        );
+                        if let Some(parent_def_id) = self.tcx.parent(def_id) {
+                            if let Some(generics) = self.tcx.hir.get_generics(parent_def_id) {
+                                let unused_lt_span = self.lifetime_deletion_span(name, generics);
+                                if let Some(span) = unused_lt_span {
+                                    err.span_suggestion_with_applicability(
+                                        span,
+                                        "remove it",
+                                        String::new(),
+                                        Applicability::MachineApplicable
+                                    );
+                                }
+                            }
+                        }
+                        err.emit();
                     }
                 }
             }
index 566673857b975b14df86284a76cf19ecd5e12f18..fe466e247c91749b8f5a2f6dc1b5be7ead80b362 100644 (file)
@@ -186,6 +186,7 @@ pub enum EvalErrorKind<'tcx, O> {
 
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
+    FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
     FunctionArgCountMismatch,
     NoMirFor(String),
     UnterminatedCString(Pointer),
@@ -294,7 +295,8 @@ pub fn description(&self) -> &str {
         use self::EvalErrorKind::*;
         match *self {
             MachineError(ref inner) => inner,
-            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionArgCountMismatch =>
+            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionRetMismatch(..)
+            | FunctionArgCountMismatch =>
                 "tried to call a function through a function pointer of incompatible type",
             InvalidMemoryAccess =>
                 "tried to access memory through an invalid pointer",
@@ -470,6 +472,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "tried to call a function with argument of type {:?} \
                            passing data of type {:?}",
                     callee_ty, caller_ty),
+            FunctionRetMismatch(caller_ty, callee_ty) =>
+                write!(f, "tried to call a function with return type {:?} \
+                           passing return place of type {:?}",
+                    callee_ty, caller_ty),
             FunctionArgCountMismatch =>
                 write!(f, "tried to call a function with incorrect number of arguments"),
             BoundsCheck { ref len, ref index } =>
index e9d0b041339556162c663a4e6c7bfce5b73c88a5..5eee0fba5fb463bfb5a53fec00f34f418c629406 100644 (file)
@@ -138,54 +138,82 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 /// each context.
 ///
 /// Defaults to the index based and loosely coupled AllocId.
+///
+/// Pointer is also generic over the `Tag` associated with each pointer,
+/// which is used to do provenance tracking during execution.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub struct Pointer<Id=AllocId> {
+pub struct Pointer<Tag=(),Id=AllocId> {
     pub alloc_id: Id,
     pub offset: Size,
+    pub tag: Tag,
 }
 
 /// Produces a `Pointer` which points to the beginning of the Allocation
 impl From<AllocId> for Pointer {
+    #[inline(always)]
     fn from(alloc_id: AllocId) -> Self {
         Pointer::new(alloc_id, Size::ZERO)
     }
 }
 
-impl<'tcx> Pointer {
+impl<'tcx> Pointer<()> {
+    #[inline(always)]
     pub fn new(alloc_id: AllocId, offset: Size) -> Self {
-        Pointer { alloc_id, offset }
+        Pointer { alloc_id, offset, tag: () }
+    }
+
+    #[inline(always)]
+    pub fn with_default_tag<Tag>(self) -> Pointer<Tag>
+        where Tag: Default
+    {
+        Pointer::new_with_tag(self.alloc_id, self.offset, Default::default())
+    }
+}
+
+impl<'tcx, Tag> Pointer<Tag> {
+    #[inline(always)]
+    pub fn new_with_tag(alloc_id: AllocId, offset: Size, tag: Tag) -> Self {
+        Pointer { alloc_id, offset, tag }
     }
 
     pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
-        Pointer::new(
+        Pointer::new_with_tag(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
+            self.tag,
         )
     }
 
     pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Self, bool) {
         let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
-        (Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
+        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
     }
 
     pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
-        Ok(Pointer::new(
+        Ok(Pointer::new_with_tag(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
+            self.tag,
         ))
     }
 
     pub fn overflowing_offset<C: HasDataLayout>(self, i: Size, cx: C) -> (Self, bool) {
         let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
-        (Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
+        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
     }
 
     pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
-        Ok(Pointer::new(
+        Ok(Pointer::new_with_tag(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
+            self.tag
         ))
     }
+
+    #[inline]
+    pub fn erase_tag(self) -> Pointer {
+        Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
+    }
 }
 
 
@@ -496,15 +524,15 @@ pub fn set_id_same_memory(&mut self, id: AllocId, mem: M) {
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
-pub struct Allocation {
+pub struct Allocation<Tag=()> {
     /// The actual bytes of the allocation.
     /// Note that the bytes of a pointer represent the offset of the pointer
     pub bytes: Vec<u8>,
-    /// Maps from byte addresses to allocations.
+    /// Maps from byte addresses to extra data for each pointer.
     /// 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,
+    pub relocations: Relocations<Tag>,
     /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
     pub undef_mask: UndefMask,
     /// The alignment of the allocation to detect unaligned reads.
@@ -515,7 +543,7 @@ pub struct Allocation {
     pub mutability: Mutability,
 }
 
-impl Allocation {
+impl<Tag> Allocation<Tag> {
     /// Creates a read-only allocation initialized by the given bytes
     pub fn from_bytes(slice: &[u8], align: Align) -> Self {
         let mut undef_mask = UndefMask::new(Size::ZERO);
@@ -548,29 +576,29 @@ 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<Id=AllocId>(SortedMap<Size, Id>);
+pub struct Relocations<Tag=(), Id=AllocId>(SortedMap<Size, (Tag, Id)>);
 
-impl<Id> Relocations<Id> {
+impl<Tag, Id> Relocations<Tag, 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, Id)>) -> Self {
+    pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self {
         Relocations(SortedMap::from_presorted_elements(r))
     }
 }
 
-impl Deref for Relocations {
-    type Target = SortedMap<Size, AllocId>;
+impl<Tag> Deref for Relocations<Tag> {
+    type Target = SortedMap<Size, (Tag, AllocId)>;
 
     fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
 
-impl DerefMut for Relocations {
+impl<Tag> DerefMut for Relocations<Tag> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.0
     }
index c81d55e69b61a124b380142c3c7cb7b99ef5f847..9e54b146fd02a61edcf79d88ccd9de0ca1d9804d 100644 (file)
@@ -79,7 +79,47 @@ pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
     }
 }
 
-impl<'tcx> Scalar {
+/// A `Scalar` represents an immediate, primitive value existing outside of a
+/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
+/// 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<Tag=(), Id=AllocId> {
+    /// The raw bytes of a simple value.
+    Bits {
+        /// The first `size` bytes are the value.
+        /// Do not try to read less or more bytes that that. The remaining bytes must be 0.
+        size: u8,
+        bits: u128,
+    },
+
+    /// 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<Tag, Id>),
+}
+
+impl<'tcx> Scalar<()> {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> Scalar<Tag>
+        where Tag: Default
+    {
+        match self {
+            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_default_tag()),
+            Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
+        }
+    }
+}
+
+impl<'tcx, Tag> Scalar<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> Scalar {
+        match self {
+            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
+            Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
+        }
+    }
+
     #[inline]
     pub fn ptr_null(cx: impl HasDataLayout) -> Self {
         Scalar::Bits {
@@ -208,7 +248,7 @@ pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
     }
 
     #[inline]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         match self {
             Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
             Scalar::Bits { .. } => err!(ReadBytesAsPointer),
@@ -317,29 +357,9 @@ pub fn to_f64(self) -> EvalResult<'static, f64> {
     }
 }
 
-impl From<Pointer> for Scalar {
+impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
     #[inline(always)]
-    fn from(ptr: Pointer) -> Self {
+    fn from(ptr: Pointer<Tag>) -> Self {
         Scalar::Ptr(ptr)
     }
 }
-
-/// A `Scalar` represents an immediate, primitive value existing outside of a
-/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
-/// 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<Id=AllocId> {
-    /// The raw bytes of a simple value.
-    Bits {
-        /// The first `size` bytes are the value.
-        /// Do not try to read less or more bytes that that. The remaining bytes must be 0.
-        size: u8,
-        bits: u128,
-    },
-
-    /// 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<Id>),
-}
index 2ae06e9ab0de79affb0a60c7c38dde9cbe217045..ea4eb761964eb184f0c69b5488331f65ac503cff 100644 (file)
@@ -2676,11 +2676,51 @@ pub struct ClosureOutlivesRequirement<'tcx> {
     // This region or type ...
     pub subject: ClosureOutlivesSubject<'tcx>,
 
-    // .. must outlive this one.
+    // ... must outlive this one.
     pub outlived_free_region: ty::RegionVid,
 
-    // If not, report an error here.
+    // If not, report an error here ...
     pub blame_span: Span,
+
+    // ... due to this reason.
+    pub category: ConstraintCategory,
+}
+
+/// Outlives constraints can be categorized to determine whether and why they
+/// are interesting (for error reporting). Order of variants indicates sort
+/// order of the category, thereby influencing diagnostic output.
+///
+/// See also [rustc_mir::borrow_check::nll::constraints]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum ConstraintCategory {
+    Return,
+    TypeAnnotation,
+    Cast,
+
+    /// A constraint that came from checking the body of a closure.
+    ///
+    /// We try to get the category that the closure used when reporting this.
+    ClosureBounds,
+    CallArgument,
+    CopyBound,
+    SizedBound,
+    Assignment,
+    OpaqueType,
+
+    /// A "boring" constraint (caused by the given location) is one that
+    /// the user probably doesn't want to see described in diagnostics,
+    /// because it is kind of an artifact of the type system setup.
+    /// Example: `x = Foo { field: y }` technically creates
+    /// intermediate regions representing the "type of `Foo { field: y
+    /// }`", and data flows from `y` into those variables, but they
+    /// are not very interesting. The assignment into `x` on the other
+    /// hand might be.
+    Boring,
+    // Boring and applicable everywhere.
+    BoringNoLocation,
+
+    /// A constraint that doesn't correspond to anything the user sees.
+    Internal,
 }
 
 /// The subject of a ClosureOutlivesRequirement -- that is, the thing
index 7d8227053b373c3aa23ccdb6edf3150da8f66142..d2b0a6a37a74ac5a6bd8bd31ab275c1c0bd80c9c 100644 (file)
@@ -214,7 +214,7 @@ fn visit_ty(&mut self,
                 self.super_ty(ty);
             }
 
-            fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
+            fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
                 self.super_canonical_ty(ty);
             }
 
@@ -640,7 +640,7 @@ fn super_ascribe_user_ty(&mut self,
                                      c_ty: & $($mutability)* CanonicalTy<'tcx>,
                                      location: Location) {
                 self.visit_place(place, PlaceContext::Validate, location);
-                self.visit_canonical_ty(c_ty);
+                self.visit_user_ty(c_ty);
             }
 
             fn super_place(&mut self,
@@ -736,7 +736,7 @@ fn super_local_decl(&mut self,
                     source_info: *source_info,
                 });
                 if let Some(user_ty) = user_ty {
-                    self.visit_canonical_ty(user_ty);
+                    self.visit_user_ty(user_ty);
                 }
                 self.visit_source_info(source_info);
                 self.visit_source_scope(visibility_scope);
index c532b5ee56f47d2d908cf442795842f84b0182e5..d8c36f81da32427bfb86d2775babd1dced494f60 100644 (file)
@@ -1387,6 +1387,10 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
           "output a json file with profiler results"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
           "emits a section containing stack size metadata"),
+    plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
+          "whether to use the PLT when calling into shared libraries;
+          only has effect for PIC code on systems with ELF binaries
+          (default: PLT is disabled if full relro is enabled)"),
 }
 
 pub fn default_lib_output() -> CrateType {
index 3c209a4324675a5b0681375b7f9b75869f0d2ae0..10a506da4eab44c6cffbc8da7f5405ad357afffd 100644 (file)
@@ -40,8 +40,7 @@
 use syntax_pos::{MultiSpan, Span};
 use util::profiling::SelfProfiler;
 
-use rustc_target::spec::PanicStrategy;
-use rustc_target::spec::{Target, TargetTriple};
+use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
 use rustc_data_structures::flock;
 use jobserver::Client;
 
@@ -984,6 +983,27 @@ pub fn rust_2018(&self) -> bool {
     pub fn edition(&self) -> Edition {
         self.opts.edition
     }
+
+    /// True if we cannot skip the PLT for shared library calls.
+    pub fn needs_plt(&self) -> bool {
+        // Check if the current target usually needs PLT to be enabled.
+        // The user can use the command line flag to override it.
+        let needs_plt = self.target.target.options.needs_plt;
+
+        let dbg_opts = &self.opts.debugging_opts;
+
+        let relro_level = dbg_opts.relro_level
+            .unwrap_or(self.target.target.options.relro_level);
+
+        // Only enable this optimization by default if full relro is also enabled.
+        // In this case, lazy binding was already unavailable, so nothing is lost.
+        // This also ensures `-Wl,-z,now` is supported by the linker.
+        let full_relro = RelroLevel::Full == relro_level;
+
+        // If user didn't explicitly forced us to use / skip the PLT,
+        // then try to skip it where possible.
+        dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
+    }
 }
 
 pub fn build_session(
index 286e35c5d4e9582cebe50b93dd204b5f3d2f67f2..6e4abee32c0771e3b87ef9c016a0ed0b0df48672 100644 (file)
@@ -318,31 +318,33 @@ pub enum QuantifierKind {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum Goal<'tcx> {
-    Implies(Clauses<'tcx>, &'tcx Goal<'tcx>),
-    And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>),
-    Not(&'tcx Goal<'tcx>),
+pub enum GoalKind<'tcx> {
+    Implies(Clauses<'tcx>, Goal<'tcx>),
+    And(Goal<'tcx>, Goal<'tcx>),
+    Not(Goal<'tcx>),
     DomainGoal(DomainGoal<'tcx>),
-    Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>),
+    Quantified(QuantifierKind, ty::Binder<Goal<'tcx>>),
     CannotProve,
 }
 
+pub type Goal<'tcx> = &'tcx GoalKind<'tcx>;
+
 pub type Goals<'tcx> = &'tcx List<Goal<'tcx>>;
 
 impl<'tcx> DomainGoal<'tcx> {
-    pub fn into_goal(self) -> Goal<'tcx> {
-        Goal::DomainGoal(self)
+    pub fn into_goal(self) -> GoalKind<'tcx> {
+        GoalKind::DomainGoal(self)
     }
 }
 
-impl<'tcx> Goal<'tcx> {
+impl<'tcx> GoalKind<'tcx> {
     pub fn from_poly_domain_goal<'a>(
         domain_goal: PolyDomainGoal<'tcx>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    ) -> Goal<'tcx> {
+    ) -> GoalKind<'tcx> {
         match domain_goal.no_late_bound_regions() {
             Some(p) => p.into_goal(),
-            None => Goal::Quantified(
+            None => GoalKind::Quantified(
                 QuantifierKind::Universal,
                 domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal()))
             ),
index 22e79fc2638abbf1a7f9e1a712c62060a91060ef..1524f89af291d05b8738bdbe3df0b9b29152bff7 100644 (file)
@@ -469,7 +469,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl<'tcx> fmt::Display for traits::Goal<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::Goal::*;
+        use traits::GoalKind::*;
 
         match self {
             Implies(hypotheses, goal) => {
@@ -598,25 +598,25 @@ impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
 }
 
 EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
-        (traits::Goal::Implies)(hypotheses, goal),
-        (traits::Goal::And)(goal1, goal2),
-        (traits::Goal::Not)(goal),
-        (traits::Goal::DomainGoal)(domain_goal),
-        (traits::Goal::Quantified)(qkind, goal),
-        (traits::Goal::CannotProve),
+    impl<'tcx> TypeFoldable<'tcx> for traits::GoalKind<'tcx> {
+        (traits::GoalKind::Implies)(hypotheses, goal),
+        (traits::GoalKind::And)(goal1, goal2),
+        (traits::GoalKind::Not)(goal),
+        (traits::GoalKind::DomainGoal)(domain_goal),
+        (traits::GoalKind::Quantified)(qkind, goal),
+        (traits::GoalKind::CannotProve),
     }
 }
 
 EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::Goal<'a> {
-        type Lifted = traits::Goal<'tcx>;
-        (traits::Goal::Implies)(hypotheses, goal),
-        (traits::Goal::And)(goal1, goal2),
-        (traits::Goal::Not)(goal),
-        (traits::Goal::DomainGoal)(domain_goal),
-        (traits::Goal::Quantified)(kind, goal),
-        (traits::Goal::CannotProve),
+    impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
+        type Lifted = traits::GoalKind<'tcx>;
+        (traits::GoalKind::Implies)(hypotheses, goal),
+        (traits::GoalKind::And)(goal1, goal2),
+        (traits::GoalKind::Not)(goal),
+        (traits::GoalKind::DomainGoal)(domain_goal),
+        (traits::GoalKind::Quantified)(kind, goal),
+        (traits::GoalKind::CannotProve),
     }
 }
 
@@ -633,7 +633,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = (**self).fold_with(folder);
         folder.tcx().mk_goal(v)
index 64e677fbe1261230356f025ac6434a6383d96bf1..47aea7a5f07960d09e3fd2caa7d66a990503f92f 100644 (file)
@@ -65,7 +65,7 @@ pub fn is_min_const_fn(self, def_id: DefId) -> bool {
                 _ => true,
             }
         } else {
-            // users enabling the `const_fn` can do what they want
+            // users enabling the `const_fn` feature gate can do what they want
             !self.sess.features_untracked().const_fn
         }
     }
index 46ba5f5ef362dfb30e6f5b5deb2186dbe577d255..3d4ae572d0b81fb0880f6bc76a8c98c08075ef37 100644 (file)
@@ -36,7 +36,7 @@
 use ty::subst::{CanonicalSubsts, Kind, Substs, Subst};
 use ty::ReprOptions;
 use traits;
-use traits::{Clause, Clauses, Goal, Goals};
+use traits::{Clause, Clauses, GoalKind, Goal, Goals};
 use ty::{self, Ty, TypeAndMut};
 use ty::{TyS, TyKind, List};
 use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
@@ -143,7 +143,8 @@ pub struct CtxtInterners<'tcx> {
     predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
     const_: InternedSet<'tcx, Const<'tcx>>,
     clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
-    goals: InternedSet<'tcx, List<Goal<'tcx>>>,
+    goal: InternedSet<'tcx, GoalKind<'tcx>>,
+    goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -159,7 +160,8 @@ fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
             predicates: Default::default(),
             const_: Default::default(),
             clauses: Default::default(),
-            goals: Default::default(),
+            goal: Default::default(),
+            goal_list: Default::default(),
         }
     }
 
@@ -1731,9 +1733,9 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'t
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for &'a Goal<'a> {
-    type Lifted = &'tcx Goal<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Goal<'tcx>> {
+impl<'a, 'tcx> Lift<'tcx> for Goal<'a> {
+    type Lifted = Goal<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Goal<'tcx>> {
         if tcx.interners.arena.in_arena(*self as *const _) {
             return Some(unsafe { mem::transmute(*self) });
         }
@@ -2304,6 +2306,12 @@ fn borrow<'a>(&'a self) -> &'a RegionKind {
     }
 }
 
+impl<'tcx: 'lcx, 'lcx> Borrow<GoalKind<'lcx>> for Interned<'tcx, GoalKind<'tcx>> {
+    fn borrow<'a>(&'a self) -> &'a GoalKind<'lcx> {
+        &self.0
+    }
+}
+
 impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
     for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
@@ -2419,7 +2427,8 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
 
 direct_interners!('tcx,
     region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
-    const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>
+    const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>,
+    goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>
 );
 
 macro_rules! slice_interners {
@@ -2438,7 +2447,7 @@ macro_rules! slice_interners {
     type_list: _intern_type_list(Ty),
     substs: _intern_substs(Kind),
     clauses: _intern_clauses(Clause),
-    goals: _intern_goals(Goal)
+    goal_list: _intern_goals(Goal)
 );
 
 // This isn't a perfect fit: CanonicalVarInfo slices are always
@@ -2818,10 +2827,6 @@ pub fn mk_goals<I: InternAs<[Goal<'tcx>], Goals<'tcx>>>(self, iter: I) -> I::Out
         iter.intern_with(|xs| self.intern_goals(xs))
     }
 
-    pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal<'_> {
-        &self.intern_goals(&[goal])[0]
-    }
-
     pub fn lint_hir<S: Into<MultiSpan>>(self,
                                         lint: &'static Lint,
                                         hir_id: HirId,
index c3d41873009a7b1d294a88e611b96e8f1d127df9..10a90dfc8a8cf936a56662820ca3300e8600c0be 100644 (file)
@@ -148,7 +148,10 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) {
                 self.add_projection_ty(data);
             }
 
-            &ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+            &ty::UnnormalizedProjection(ref data) => {
+                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_projection_ty(data);
+            },
 
             &ty::Opaque(_, substs) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
index 83a9491cf4673c57cc6629775a8d9c0c3a6d9b0c..3f62883c6a57b549cead28b2fcc35ec7532e7177 100644 (file)
@@ -492,6 +492,10 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 tcx.lift(&a)?,
                 tcx.lift(&b)?,
             ),
+            FunctionRetMismatch(a, b) => FunctionRetMismatch(
+                tcx.lift(&a)?,
+                tcx.lift(&b)?,
+            ),
             FunctionArgCountMismatch => FunctionArgCountMismatch,
             NoMirFor(ref s) => NoMirFor(s.clone()),
             UnterminatedCString(ptr) => UnterminatedCString(ptr),
index c177ed85c3482ce49f419ecc7ac8a5961990a723..56dd5a846da6b08677f5d19847c27d356406fb70 100644 (file)
@@ -23,7 +23,6 @@
 use rustc::cfg::CFGIndex;
 use dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
 use std::rc::Rc;
-use dot::IntoCow;
 
 #[derive(Debug, Copy, Clone)]
 pub enum Variant {
@@ -139,8 +138,8 @@ fn node_label(&'a self, n: &Node<'a>) -> dot::LabelText<'a> {
         let suffix = self.dataflow_for(EntryOrExit::Exit, n);
         let inner_label = self.inner.node_label(n);
         inner_label
-            .prefix_line(dot::LabelText::LabelStr(prefix.into_cow()))
-            .suffix_line(dot::LabelText::LabelStr(suffix.into_cow()))
+            .prefix_line(dot::LabelText::LabelStr(prefix.into()))
+            .suffix_line(dot::LabelText::LabelStr(suffix.into()))
     }
     fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) }
 }
index 684f2b358858f935387d082d6b0b26607a796cb1..c8e8d0dc84ef038027ffc589c558923721a253d2 100644 (file)
@@ -150,7 +150,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         // Create list of fields in the main structure
         let mut args: Vec<_> =
             self.prefix.iter().flat_map(|option_kind| option_kind.map(
-                    |kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)))
+                |kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)))
             .chain((0..rest_count).map(|_| rest_ll_unit))
             .collect();
 
@@ -259,8 +259,7 @@ fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceR
 }
 
 pub trait FnTypeExt<'tcx> {
-    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
-                   -> Self;
+    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self;
     fn new(cx: &CodegenCx<'ll, 'tcx>,
            sig: ty::FnSig<'tcx>,
            extra_args: &[Ty<'tcx>]) -> Self;
@@ -283,8 +282,7 @@ fn adjust_for_abi(&mut self,
 }
 
 impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
-    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
-                       -> Self {
+    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self {
         let fn_ty = instance.ty(cx.tcx);
         let sig = ty_fn_sig(cx, fn_ty);
         let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
@@ -292,16 +290,16 @@ fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
     }
 
     fn new(cx: &CodegenCx<'ll, 'tcx>,
-               sig: ty::FnSig<'tcx>,
-               extra_args: &[Ty<'tcx>]) -> Self {
+           sig: ty::FnSig<'tcx>,
+           extra_args: &[Ty<'tcx>]) -> Self {
         FnType::new_internal(cx, sig, extra_args, |ty, _| {
             ArgType::new(cx.layout_of(ty))
         })
     }
 
     fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
-                      sig: ty::FnSig<'tcx>,
-                      extra_args: &[Ty<'tcx>]) -> Self {
+                  sig: ty::FnSig<'tcx>,
+                  extra_args: &[Ty<'tcx>]) -> Self {
         FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
             let mut layout = cx.layout_of(ty);
             // Don't pass the vtable, it's not an argument of the virtual fn.
@@ -338,7 +336,7 @@ fn new_internal(
             RustIntrinsic | PlatformIntrinsic |
             Rust | RustCall => Conv::C,
 
-            // It's the ABI's job to select this, not us.
+            // It's the ABI's job to select this, not ours.
             System => bug!("system abi should be selected elsewhere"),
 
             Stdcall => Conv::X86Stdcall,
@@ -697,14 +695,13 @@ fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value
             // If the value is a boolean, the range is 0..2 and that ultimately
             // become 0..0 when the type becomes i1, which would be rejected
             // by the LLVM verifier.
-            match scalar.value {
-                layout::Int(..) if !scalar.is_bool() => {
+            if let layout::Int(..) = scalar.value {
+                if !scalar.is_bool() {
                     let range = scalar.valid_range_exclusive(bx.cx);
                     if range.start != range.end {
                         bx.range_metadata(callsite, range);
                     }
                 }
-                _ => {}
             }
         }
         for arg in &self.args {
index 0beb8a8844c958f281f98f9e902c4b8dcb9a3fb3..7c237407c8f54b219a903b0e360392f18ff87761 100644 (file)
@@ -33,7 +33,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind
     let void = llvm::LLVMVoidTypeInContext(llcx);
 
     for method in ALLOCATOR_METHODS {
-        let mut args = Vec::new();
+        let mut args = Vec::with_capacity(method.inputs.len());
         for ty in method.inputs.iter() {
             match *ty {
                 AllocatorTy::Layout => {
index 51380db5b23df295c4f1125e5d12a3ec8f7d4c22..90ba103ca4ceb2540d0173dd0c7ae8016f6746e8 100644 (file)
@@ -94,9 +94,8 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     // Currently stack probes seem somewhat incompatible with the address
     // sanitizer. With asan we're already protected from stack overflow anyway
     // so we don't really need stack probes regardless.
-    match cx.sess().opts.debugging_opts.sanitizer {
-        Some(Sanitizer::Address) => return,
-        _ => {}
+    if let Some(Sanitizer::Address) = cx.sess().opts.debugging_opts.sanitizer {
+        return
     }
 
     // probestack doesn't play nice either with pgo-gen.
@@ -138,6 +137,15 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
             target_cpu.as_c_str());
 }
 
+/// Sets the `NonLazyBind` LLVM attribute on a given function,
+/// assuming the codegen options allow skipping the PLT.
+pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) {
+    // Don't generate calls through PLT if it's not necessary
+    if !sess.needs_plt() {
+        Attribute::NonLazyBind.apply_llfn(Function, llfn);
+    }
+}
+
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
 pub fn from_fn_attrs(
@@ -280,12 +288,14 @@ pub fn provide_extern(providers: &mut Providers) {
         // `NativeLibrary` internally contains information about
         // `#[link(wasm_import_module = "...")]` for example.
         let native_libs = tcx.native_libraries(cnum);
-        let mut def_id_to_native_lib = FxHashMap();
-        for lib in native_libs.iter() {
+
+        let def_id_to_native_lib = native_libs.iter().filter_map(|lib|
             if let Some(id) = lib.foreign_module {
-                def_id_to_native_lib.insert(id, lib);
+                Some((id, lib))
+            } else {
+                None
             }
-        }
+        ).collect::<FxHashMap<_, _>>();
 
         let mut ret = FxHashMap();
         for lib in tcx.foreign_modules(cnum).iter() {
@@ -296,10 +306,10 @@ pub fn provide_extern(providers: &mut Providers) {
                 Some(s) => s,
                 None => continue,
             };
-            for id in lib.foreign_items.iter() {
+            ret.extend(lib.foreign_items.iter().map(|id| {
                 assert_eq!(id.krate, cnum);
-                ret.insert(*id, module.to_string());
-            }
+                (*id, module.to_string())
+            }));
         }
 
         Lrc::new(ret)
index 55dc43ec1fbca6d3198f22d090df582af7072fe9..c814ab4ab6710123e8e69069ad7690761134ea7d 100644 (file)
@@ -213,8 +213,8 @@ pub fn unsized_info(
                             vtable_ptr.llvm_type(cx))
         }
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
-                                     source,
-                                     target),
+                  source,
+                  target),
     }
 }
 
@@ -340,11 +340,11 @@ pub fn cast_shift_expr_rhs(
 }
 
 fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
-                        lhs: &'ll Value,
-                        rhs: &'ll Value,
-                        trunc: F,
-                        zext: G)
-                        -> &'ll Value
+                             lhs: &'ll Value,
+                             rhs: &'ll Value,
+                             trunc: F,
+                             zext: G)
+                             -> &'ll Value
     where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
           G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value
 {
@@ -363,8 +363,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
         if lhs_sz < rhs_sz {
             trunc(rhs, lhs_llty)
         } else if lhs_sz > rhs_sz {
-            // FIXME (#1877: If shifting by negative
-            // values becomes not undefined then this is wrong.
+            // FIXME (#1877: If in the future shifting by negative
+            // values is no longer undefined then this is wrong.
             zext(rhs, lhs_llty)
         } else {
             rhs
@@ -495,10 +495,8 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
     let sig = common::ty_fn_sig(cx, fn_ty);
     let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
 
-    let lldecl = match cx.instances.borrow().get(&instance) {
-        Some(&val) => val,
-        None => bug!("Instance `{:?}` not already declared", instance)
-    };
+    let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(||
+        bug!("Instance `{:?}` not already declared", instance));
 
     cx.stats.borrow_mut().n_closures += 1;
 
@@ -566,8 +564,8 @@ fn create_entry_fn(
         if declare::get_defined_value(cx, "main").is_some() {
             // FIXME: We should be smart and show a better diagnostic here.
             cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
-                      .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
-                      .emit();
+                     .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
+                     .emit();
             cx.sess().abort_if_errors();
             bug!();
         }
@@ -736,9 +734,9 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             rx: mpsc::Receiver<Box<dyn Any + Send>>)
-                             -> OngoingCodegen {
-
+                               rx: mpsc::Receiver<Box<dyn Any + Send>>)
+                               -> OngoingCodegen
+{
     check_for_rustc_errors_attr(tcx);
 
     if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
@@ -803,8 +801,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Run the monomorphization collector and partition the collected items into
     // codegen units.
-    let codegen_units =
-        tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
+    let codegen_units = tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
     let codegen_units = (*codegen_units).clone();
 
     // Force all codegen_unit queries so they are already either red or green
@@ -837,12 +834,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         .iter()
         .any(|(_, list)| {
             use rustc::middle::dependency_format::Linkage;
-            list.iter().any(|linkage| {
-                match linkage {
-                    Linkage::Dynamic => true,
-                    _ => false,
-                }
-            })
+            list.iter().any(|&linkage| linkage == Linkage::Dynamic)
         });
     let allocator_module = if any_dynamic_crate {
         None
@@ -988,7 +980,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
                 if mode_string != "lazy" {
                     let message = format!("Unknown codegen-item collection mode '{}'. \
                                            Falling back to 'lazy' mode.",
-                                           mode_string);
+                                          mode_string);
                     tcx.sess.warn(&message);
                 }
 
@@ -1123,7 +1115,15 @@ pub fn new(tcx: TyCtxt) -> CrateInfo {
             info.load_wasm_imports(tcx, LOCAL_CRATE);
         }
 
-        for &cnum in tcx.crates().iter() {
+        let crates = tcx.crates();
+
+        let n_crates = crates.len();
+        info.native_libraries.reserve(n_crates);
+        info.crate_name.reserve(n_crates);
+        info.used_crate_source.reserve(n_crates);
+        info.missing_lang_items.reserve(n_crates);
+
+        for &cnum in crates.iter() {
             info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
             info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
             info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
@@ -1165,11 +1165,12 @@ pub fn new(tcx: TyCtxt) -> CrateInfo {
     }
 
     fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) {
-        for (&id, module) in tcx.wasm_import_module_map(cnum).iter() {
+        self.wasm_imports.extend(tcx.wasm_import_module_map(cnum).iter().map(|(&id, module)| {
             let instance = Instance::mono(tcx, id);
             let import_name = tcx.symbol_name(instance);
-            self.wasm_imports.insert(import_name.to_string(), module.clone());
-        }
+
+            (import_name.to_string(), module.clone())
+        }));
     }
 }
 
index 77de88997e4903ebc0326203049a4d1756e670a7..df9c4e874bd95b61ce2bdf20d6690c940b7d4e41 100644 (file)
@@ -110,10 +110,10 @@ fn count_insn(&self, category: &str) {
         }
         if self.cx.sess().count_llvm_insns() {
             *self.cx.stats
-                .borrow_mut()
-                .llvm_insns
-                .entry(category.to_string())
-                .or_insert(0) += 1;
+                    .borrow_mut()
+                    .llvm_insns
+                    .entry(category.to_string())
+                    .or_insert(0) += 1;
         }
     }
 
@@ -735,9 +735,9 @@ pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -
     }
 
     pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
-                         inputs: &[&'ll Value], output: &'ll Type,
-                         volatile: bool, alignstack: bool,
-                         dia: AsmDialect) -> Option<&'ll Value> {
+                           inputs: &[&'ll Value], output: &'ll Type,
+                           volatile: bool, alignstack: bool,
+                           dia: AsmDialect) -> Option<&'ll Value> {
         self.count_insn("inlineasm");
 
         let volatile = if volatile { llvm::True }
@@ -1093,7 +1093,7 @@ pub fn atomic_cmpxchg(
     ) -> &'ll Value {
         unsafe {
             llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
-                                         order, failure_order, weak)
+                                             order, failure_order, weak)
         }
     }
     pub fn atomic_rmw(
@@ -1194,7 +1194,7 @@ fn check_call<'b>(&self,
             })
             .collect();
 
-        return Cow::Owned(casted_args);
+        Cow::Owned(casted_args)
     }
 
     pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
index 53bb02ddd99d947887ad4a555fb4330114df511e..c08937fa9b9162669bcb04f021cbde86c2aa6736 100644 (file)
@@ -336,16 +336,13 @@ pub fn langcall(tcx: TyCtxt,
                 msg: &str,
                 li: LangItem)
                 -> DefId {
-    match tcx.lang_items().require(li) {
-        Ok(id) => id,
-        Err(s) => {
-            let msg = format!("{} {}", msg, s);
-            match span {
-                Some(span) => tcx.sess.span_fatal(span, &msg[..]),
-                None => tcx.sess.fatal(&msg[..]),
-            }
+    tcx.lang_items().require(li).unwrap_or_else(|s| {
+        let msg = format!("{} {}", msg, s);
+        match span {
+            Some(span) => tcx.sess.span_fatal(span, &msg[..]),
+            None => tcx.sess.fatal(&msg[..]),
         }
-    }
+    })
 }
 
 // To avoid UB from LLVM, these two functions mask RHS with an
index 522de2f15e0a95806b15fc2f3023b54a9ae3ed4b..9228870bf3a5c2105d84fe298aca420e165524fb 100644 (file)
@@ -124,7 +124,7 @@ pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
     assert!(!defined_in_current_codegen_unit,
             "consts::get_static() should always hit the cache for \
              statics defined in the same CGU, but did not for `{:?}`",
-             def_id);
+            def_id);
 
     let ty = instance.ty(cx.tcx);
     let sym = cx.tcx.symbol_name(instance).as_str();
@@ -249,14 +249,13 @@ fn check_and_apply_linkage(
         // extern "C" fn() from being non-null, so we can't just declare a
         // static and call it a day. Some linkages (like weak) will make it such
         // that the static actually has a null value.
-        let llty2 = match ty.sty {
-            ty::RawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
-            _ => {
-                if span.is_some() {
-                    cx.sess().span_fatal(span.unwrap(), "must have type `*const T` or `*mut T`")
-                } else {
-                    bug!("must have type `*const T` or `*mut T`")
-                }
+        let llty2 = if let ty::RawPtr(ref mt) = ty.sty {
+            cx.layout_of(mt.ty).llvm_type(cx)
+        } else {
+            if let Some(span) = span {
+                cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`")
+            } else {
+                bug!("must have type `*const T` or `*mut T`")
             }
         };
         unsafe {
@@ -273,9 +272,9 @@ fn check_and_apply_linkage(
             let mut real_name = "_rust_extern_with_linkage_".to_string();
             real_name.push_str(&sym);
             let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{
-                if span.is_some() {
+                if let Some(span) = span {
                     cx.sess().span_fatal(
-                        span.unwrap(),
+                        span,
                         &format!("symbol `{}` is already defined", &sym)
                     )
                 } else {
index 9547f4a190e7896d721cda285efb8217b05fc674..578018c7adc8a7fa0334394c28b3fd87f81c40fa 100644 (file)
@@ -59,8 +59,8 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
     /// Cache instances of monomorphic and polymorphic items
     pub instances: RefCell<FxHashMap<Instance<'tcx>, &'a Value>>,
     /// Cache generated vtables
-    pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
-                                Option<ty::PolyExistentialTraitRef<'tcx>>), &'a Value>>,
+    pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
+                                   &'a Value>>,
     /// Cache of constant strings,
     pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'a Value>>,
 
@@ -208,14 +208,21 @@ pub unsafe fn create_module(
         llvm::LLVMRustSetModulePIELevel(llmod);
     }
 
+    // If skipping the PLT is enabled, we need to add some module metadata
+    // to ensure intrinsic calls don't use it.
+    if !sess.needs_plt() {
+        let avoid_plt = "RtLibUseGOT\0".as_ptr() as *const _;
+        llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
+    }
+
     llmod
 }
 
 impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
     crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-               codegen_unit: Arc<CodegenUnit<'tcx>>,
-               llvm_module: &'a ::ModuleLlvm)
-               -> CodegenCx<'a, 'tcx> {
+                 codegen_unit: Arc<CodegenUnit<'tcx>>,
+                 llvm_module: &'a ::ModuleLlvm)
+                 -> CodegenCx<'a, 'tcx> {
         // An interesting part of Windows which MSVC forces our hand on (and
         // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
         // attributes in LLVM IR as well as native dependencies (in C these
@@ -270,8 +277,8 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
         let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
             let dctx = debuginfo::CrateDebugContext::new(llmod);
             debuginfo::metadata::compile_unit_metadata(tcx,
-                                                        &codegen_unit.name().as_str(),
-                                                        &dctx);
+                                                       &codegen_unit.name().as_str(),
+                                                       &dctx);
             Some(dctx)
         } else {
             None
@@ -318,10 +325,8 @@ pub fn get_intrinsic(&self, key: &str) -> &'b Value {
         if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
             return v;
         }
-        match declare_intrinsic(self, key) {
-            Some(v) => return v,
-            None => bug!("unknown intrinsic '{}'", key)
-        }
+
+        declare_intrinsic(self, key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key))
     }
 
     /// Generate a new symbol name with the given prefix. This symbol name must
@@ -465,9 +470,10 @@ impl LayoutOf for &'a CodegenCx<'ll, 'tcx> {
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
         self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty))
-            .unwrap_or_else(|e| match e {
-                LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
-                _ => bug!("failed to get layout for `{}`: {}", ty, e)
+            .unwrap_or_else(|e| if let LayoutError::SizeOverflow(_) = e {
+                self.sess().fatal(&e.to_string())
+            } else {
+                bug!("failed to get layout for `{}`: {}", ty, e)
             })
     }
 }
@@ -772,5 +778,6 @@ macro_rules! mk_struct {
         ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
         ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);
     }
-    return None;
+
+    None
 }
index 7141c9ece89d7180ea0c7f85f22e1fb29afbf8e1..26969e24f0883503d9178699bd9ba32377bc351b 100644 (file)
@@ -104,6 +104,8 @@ fn declare_raw_fn(
         attributes::unwind(llfn, false);
     }
 
+    attributes::non_lazy_bind(cx.sess(), llfn);
+
     llfn
 }
 
index 242b7a1a119f7ef54b8aace01f4769ead2a40329..5721938c9c0a75a9899b34c1551f28ed176cf85e 100644 (file)
@@ -69,4 +69,15 @@ fn main() {
 ```
 "##,
 
+E0669: r##"
+Cannot convert inline assembly operand to a single LLVM value.
+
+This error usually happens when trying to pass in a value to an input inline
+assembly operand that is actually a pair of values. In particular, this can
+happen when trying to pass in a slice, for instance a `&str`. In Rust, these
+values are represented internally as a pair of values, the pointer and its
+length. When passed as an input operand, this pair of values can not be
+coerced into a register and thus we must fail with an error.
+"##,
+
 }
index ff33cec043729eaacffd4a1dddce437e147da263..842bdf3cb493ff1b01772c5d4026c8388ae440e3 100644 (file)
@@ -97,8 +97,8 @@ pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Opt
                     C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
                 }
                 _ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
-                                sized_align,
-                                unsized_align)
+                               sized_align,
+                               unsized_align)
             };
 
             // Issue #27023: must add any necessary padding to `size`
index 5ec934ebd066750458e51275d6e75e24a9606862..272196afa6f92bdf6ce3ee50a99b6170abe269ff 100644 (file)
@@ -115,8 +115,8 @@ pub fn codegen_intrinsic_call(
     let llval = match name {
         _ if simple.is_some() => {
             bx.call(simple.unwrap(),
-                     &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
-                     None)
+                    &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
+                    None)
         }
         "unreachable" => {
             return;
@@ -373,7 +373,6 @@ pub fn codegen_intrinsic_call(
                     return;
                 }
             }
-
         },
         "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
             let sty = &arg_tys[0].sty;
@@ -540,10 +539,9 @@ pub fn codegen_intrinsic_call(
         }
 
         _ => {
-            let intr = match Intrinsic::find(&name) {
-                Some(intr) => intr,
-                None => bug!("unknown intrinsic '{}'", name),
-            };
+            let intr = Intrinsic::find(&name).unwrap_or_else(||
+                bug!("unknown intrinsic '{}'", name));
+
             fn one<T>(x: Vec<T>) -> T {
                 assert_eq!(x.len(), 1);
                 x.into_iter().next().unwrap()
@@ -822,8 +820,7 @@ fn codegen_msvc_try(
         let i64p = Type::i64(cx).ptr_to();
         let ptr_align = bx.tcx().data_layout.pointer_align;
         let slot = bx.alloca(i64p, "slot", ptr_align);
-        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
-            None);
+        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
 
         normal.ret(C_i32(cx, 0));
 
@@ -911,8 +908,7 @@ fn codegen_gnu_try(
         // being thrown.  The second value is a "selector" indicating which of
         // the landing pad clauses the exception's type had been matched to.
         // rust_try ignores the selector.
-        let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)],
-                                    false);
+        let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false);
         let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
         catch.add_clause(vals, C_null(Type::i8p(cx)));
         let ptr = catch.extract_value(vals, 0);
@@ -976,7 +972,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
     let output = tcx.types.i32;
     let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen);
     cx.rust_try_fn.set(Some(rust_try));
-    return rust_try
+    rust_try
 }
 
 fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
@@ -1000,11 +996,11 @@ macro_rules! emit_error {
         ($msg: tt, $($fmt: tt)*) => {
             span_invalid_monomorphization_error(
                 bx.sess(), span,
-                &format!(concat!("invalid monomorphization of `{}` intrinsic: ",
-                                 $msg),
+                &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
                          name, $($fmt)*));
         }
     }
+
     macro_rules! return_error {
         ($($fmt: tt)*) => {
             {
@@ -1021,14 +1017,13 @@ macro_rules! require {
             }
         };
     }
+
     macro_rules! require_simd {
         ($ty: expr, $position: expr) => {
             require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
         }
     }
 
-
-
     let tcx = bx.tcx();
     let sig = tcx.normalize_erasing_late_bound_regions(
         ty::ParamEnv::reveal_all(),
@@ -1075,11 +1070,8 @@ macro_rules! require_simd {
     }
 
     if name.starts_with("simd_shuffle") {
-        let n: usize = match name["simd_shuffle".len()..].parse() {
-            Ok(n) => n,
-            Err(_) => span_bug!(span,
-                                "bad `simd_shuffle` instruction only caught in codegen?")
-        };
+        let n: usize = name["simd_shuffle".len()..].parse().unwrap_or_else(|_|
+            span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?"));
 
         require_simd!(ret_ty, "return");
 
@@ -1121,8 +1113,8 @@ macro_rules! require_simd {
         };
 
         return Ok(bx.shuffle_vector(args[0].immediate(),
-                                     args[1].immediate(),
-                                     C_vector(&indices)))
+                                    args[1].immediate(),
+                                    C_vector(&indices)))
     }
 
     if name == "simd_insert" {
@@ -1130,8 +1122,8 @@ macro_rules! require_simd {
                  "expected inserted type `{}` (element of input `{}`), found `{}`",
                  in_elem, in_ty, arg_tys[2]);
         return Ok(bx.insert_element(args[0].immediate(),
-                                     args[2].immediate(),
-                                     args[1].immediate()))
+                                    args[2].immediate(),
+                                    args[1].immediate()))
     }
     if name == "simd_extract" {
         require!(ret_ty == in_elem,
@@ -1150,9 +1142,7 @@ macro_rules! require_simd {
         );
         match m_elem_ty.sty {
             ty::Int(_) => {},
-            _ => {
-                return_error!("mask element type is `{}`, expected `i_`", m_elem_ty);
-            }
+            _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty)
         }
         // truncate the mask to a vector of i1s
         let i1 = Type::i1(bx.cx);
@@ -1177,8 +1167,7 @@ macro_rules! emit_error {
             ($msg: tt, $($fmt: tt)*) => {
                 span_invalid_monomorphization_error(
                     bx.sess(), span,
-                    &format!(concat!("invalid monomorphization of `{}` intrinsic: ",
-                                     $msg),
+                    &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
                              name, $($fmt)*));
             }
         }
@@ -1223,63 +1212,53 @@ macro_rules! return_error {
                         &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
                         None);
         unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) };
-        return Ok(c);
-    }
-
-    if name == "simd_fsqrt" {
-        return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fsin" {
-        return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fcos" {
-        return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fabs" {
-        return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_floor" {
-        return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_ceil" {
-        return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fexp" {
-        return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fexp2" {
-        return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_flog10" {
-        return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_flog2" {
-        return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_flog" {
-        return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args);
+        Ok(c)
     }
 
-    if name == "simd_fpowi" {
-        return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fpow"  {
-        return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args);
-    }
-
-    if name == "simd_fma" {
-        return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args);
+    match name {
+        "simd_fsqrt" => {
+            return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fsin" => {
+            return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fcos" => {
+            return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fabs" => {
+            return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_floor" => {
+            return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_ceil" => {
+            return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fexp" => {
+            return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fexp2" => {
+            return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_flog10" => {
+            return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_flog2" => {
+            return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_flog" => {
+            return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fpowi" => {
+            return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fpow" => {
+            return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args);
+        }
+        "simd_fma" => {
+            return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args);
+        }
+        _ => { /* fallthrough */ }
     }
 
     // FIXME: use:
@@ -1312,7 +1291,7 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize,
     }
 
 
-    if name == "simd_gather"  {
+    if name == "simd_gather" {
         // simd_gather(values: <N x T>, pointers: <N x *_ T>,
         //             mask: <N x i{M}>) -> <N x T>
         // * N: number of elements in the input vectors
@@ -1360,7 +1339,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         // to the element type of the first argument
         let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty {
             ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)),
-                                                   non_ptr(arg_tys[1].simd_type(tcx))),
+                                                 non_ptr(arg_tys[1].simd_type(tcx))),
             _ => {
                 require!(false, "expected element type `{}` of second argument `{}` \
                                  to be a pointer to the element type `{}` of the first \
@@ -1371,7 +1350,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
             }
         };
         assert!(pointer_count > 0);
-        assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
+        assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx)));
         assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
 
         // The element type of the third argument must be a signed integer type of any width:
@@ -1414,7 +1393,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         return Ok(v);
     }
 
-    if name == "simd_scatter"  {
+    if name == "simd_scatter" {
         // simd_scatter(values: <N x T>, pointers: <N x *mut T>,
         //             mask: <N x i{M}>) -> ()
         // * N: number of elements in the input vectors
@@ -1468,7 +1447,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
             }
         };
         assert!(pointer_count > 0);
-        assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
+        assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx)));
         assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
 
         // The element type of the third argument must be a signed integer type of any width:
@@ -1570,7 +1549,6 @@ macro_rules! arith_red {
                                     )
                                 }
                             }
-
                         };
                         Ok(bx.$float_reduce(acc, args[0].immediate()))
                     }
@@ -1750,9 +1728,9 @@ macro_rules! arith {
                     _ => {},
                 }
                 require!(false,
-                            "unsupported operation on `{}` with element `{}`",
-                            in_ty,
-                            in_elem)
+                         "unsupported operation on `{}` with element `{}`",
+                         in_ty,
+                         in_elem)
             })*
         }
     }
index 71d739222b60a1adf17a11084af8f11da282b219..63a8ab077e5ae494c90d00c14ce0b24da08288a0 100644 (file)
@@ -306,7 +306,7 @@ fn into_compiled_module(self,
         };
         let bytecode_compressed = if emit_bc_compressed {
             Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
-                    .with_extension(RLIB_BYTECODE_EXTENSION))
+                        .with_extension(RLIB_BYTECODE_EXTENSION))
         } else {
             None
         };
index 8485db4210cb0b691fb2cfcbe7b6987838bf6f96..c9f51efdc50957bbb01e080c50f5165d27ae2f2c 100644 (file)
@@ -122,6 +122,7 @@ pub enum Attribute {
     SanitizeThread  = 20,
     SanitizeAddress = 21,
     SanitizeMemory  = 22,
+    NonLazyBind     = 23,
 }
 
 /// LLVMIntPredicate
index 9e8ff2047036bc6767fe75c04dd97a57f81648ef..8456cf2f4805912400e12160e8fc41183139ca33 100644 (file)
@@ -52,8 +52,9 @@ fn require_inited() {
 }
 
 unsafe fn configure_llvm(sess: &Session) {
-    let mut llvm_c_strs = Vec::new();
-    let mut llvm_args = Vec::new();
+    let n_args = sess.opts.cg.llvm_args.len();
+    let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
+    let mut llvm_args = Vec::with_capacity(n_args + 1);
 
     {
         let mut add = |arg: &str| {
index a4526a53769ba786838c7765a3266bbd19f4b80c..7752465d885bbff47574b533b7bc8cc4f669af29 100644 (file)
@@ -63,7 +63,7 @@ fn get_dylib_metadata(&self,
             let of = ObjectFile::new(mb)
                 .map(|of| OwningRef::new(box of))
                 .ok_or_else(|| format!("provided path not an object file: '{}'",
-                                        filename.display()))?;
+                                       filename.display()))?;
             let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
             Ok(rustc_erase_owner!(buf))
         }
index c3e3785a724a2a7273f5b0f348f0aa7f7c2d8a4f..a0d6cc4629589da5572e08bfac18c963e6e1ab70 100644 (file)
@@ -151,9 +151,9 @@ fn visit_terminator_kind(&mut self,
     }
 
     fn visit_place(&mut self,
-                    place: &mir::Place<'tcx>,
-                    context: PlaceContext<'tcx>,
-                    location: Location) {
+                   place: &mir::Place<'tcx>,
+                   context: PlaceContext<'tcx>,
+                   location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
         let cx = self.fx.cx;
 
index db95b46c38ebeee537e0948fb2bcd5d39a1589a6..5be176f75c96a7ef88ed3b31d18b5ed92d8fa29c 100644 (file)
@@ -49,9 +49,9 @@ pub fn codegen_block(&mut self, bb: mir::BasicBlock) {
     }
 
     fn codegen_terminator(&mut self,
-                        mut bx: Builder<'a, 'll, 'tcx>,
-                        bb: mir::BasicBlock,
-                        terminator: &mir::Terminator<'tcx>)
+                          mut bx: Builder<'a, 'll, 'tcx>,
+                          bb: mir::BasicBlock,
+                          terminator: &mir::Terminator<'tcx>)
     {
         debug!("codegen_terminator: {:?}", terminator);
 
index ce18f31da6907f440a25a5772bf0fcdf8e000b50..9f0f744389089c56981a35d1a08a55be3dc4ec32 100644 (file)
@@ -92,7 +92,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
     let pointer_size = layout.pointer_size.bytes() as usize;
 
     let mut next_offset = 0;
-    for &(offset, alloc_id) in alloc.relocations.iter() {
+    for &(offset, ((), alloc_id)) in alloc.relocations.iter() {
         let offset = offset.bytes();
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
@@ -105,7 +105,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(scalar_to_llvm(
             cx,
-            Pointer { alloc_id, offset: Size::from_bytes(ptr_offset) }.into(),
+            Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
             &layout::Scalar {
                 value: layout::Primitive::Pointer,
                 valid_range: 0..=!0
index 6bd41bfe16feee3d6c23e6f8fd8eb271ecc45123..93be0074f6e9b57cd24992958ad84a72af72576d 100644 (file)
@@ -15,6 +15,7 @@
 
 use super::FunctionCx;
 use super::LocalRef;
+use super::OperandValue;
 
 impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_statement(&mut self,
@@ -82,14 +83,27 @@ pub fn codegen_statement(&mut self,
                     self.codegen_place(&bx, output)
                 }).collect();
 
-                let input_vals = inputs.iter().map(|input| {
-                    self.codegen_operand(&bx, input).immediate()
-                }).collect();
+                let input_vals = inputs.iter()
+                    .try_fold(Vec::with_capacity(inputs.len()), |mut acc, input| {
+                        let op = self.codegen_operand(&bx, input);
+                        if let OperandValue::Immediate(_) = op.val {
+                            acc.push(op.immediate());
+                            Ok(acc)
+                        } else {
+                            Err(op)
+                        }
+                });
 
-                let res = asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
-                if !res {
-                    span_err!(bx.sess(), statement.source_info.span, E0668,
-                              "malformed inline assembly");
+                if input_vals.is_err() {
+                   span_err!(bx.sess(), statement.source_info.span, E0669,
+                             "invalid value for constraint in inline assembly");
+                } else {
+                    let input_vals = input_vals.unwrap();
+                    let res = asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
+                    if !res {
+                        span_err!(bx.sess(), statement.source_info.span, E0668,
+                                  "malformed inline assembly");
+                    }
                 }
                 bx
             }
index a8502e9244768b8aee7835dd4167bfffeff311fb..dab9b147cc0708d055dba215493bbc6d58842f12 100644 (file)
@@ -108,8 +108,8 @@ fn to_raw_string(&self) -> String {
         match *self.as_mono_item() {
             MonoItem::Fn(instance) => {
                 format!("Fn({:?}, {})",
-                         instance.def,
-                         instance.substs.as_ptr() as usize)
+                        instance.def,
+                        instance.substs.as_ptr() as usize)
             }
             MonoItem::Static(id) => {
                 format!("Static({:?})", id)
index 765708aeafd94f7e2f1c257a53fb3f0b17d4a754..03ded64e642355706e8c7b5471028a0ec8a5e30e 100644 (file)
@@ -65,13 +65,12 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             let mut name = String::with_capacity(32);
             let printer = DefPathBasedNames::new(cx.tcx, true, true);
             printer.push_type_name(layout.ty, &mut name);
-            match (&layout.ty.sty, &layout.variants) {
-                (&ty::Adt(def, _), &layout::Variants::Single { index }) => {
-                    if def.is_enum() && !def.variants.is_empty() {
-                        write!(&mut name, "::{}", def.variants[index].name).unwrap();
-                    }
+            if let (&ty::Adt(def, _), &layout::Variants::Single { index })
+                 = (&layout.ty.sty, &layout.variants)
+            {
+                if def.is_enum() && !def.variants.is_empty() {
+                    write!(&mut name, "::{}", def.variants[index].name).unwrap();
                 }
-                _ => {}
             }
             Some(name)
         }
@@ -132,7 +131,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \
                 effective_field_align: {}",
-            i, field, offset, target_offset, effective_field_align.abi());
+               i, field, offset, target_offset, effective_field_align.abi());
         assert!(target_offset >= offset);
         let padding = target_offset - offset;
         let padding_align = prev_effective_align.min(effective_field_align);
@@ -155,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
                padding, offset, layout.size);
         result.push(Type::padding_filler(cx, padding, padding_align));
-        assert!(result.len() == 1 + field_count * 2);
+        assert_eq!(result.len(), 1 + field_count * 2);
     } else {
         debug!("struct_llfields: offset: {:?} stride: {:?}",
                offset, layout.size);
index 3328948c2951e5ce18e8b500b4ce9e1189c7f6a9..4bf5b09baa6294ffbfd022bdb4bc8e5646f3cdfa 100644 (file)
@@ -34,6 +34,6 @@ impl fmt::Debug for Value {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
             llvm::LLVMRustWriteValueToString(self, s);
-        }).expect("nun-UTF8 value description from LLVM"))
+        }).expect("non-UTF8 value description from LLVM"))
     }
 }
index 4405c0aef9023367201af0bc00a608e1af718e3b..0514bd20c985a2fa802ba1f879c026820be7f6cf 100644 (file)
@@ -21,7 +21,6 @@
 #![feature(box_syntax)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(nll)]
-#![feature(option_replace)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
index 64036690927bd881d5585c4944b52afc9dfe94f6..8e07e44513b0a98346290fa3b5417758318c9947 100644 (file)
@@ -55,7 +55,6 @@
 use rustc::hir;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
-use graphviz::IntoCow;
 use std::env;
 use std::fs::{self, File};
 use std::io::Write;
@@ -274,10 +273,10 @@ impl<'a, 'tcx, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> {
     type Edge = (&'q DepNode, &'q DepNode);
     fn nodes(&self) -> dot::Nodes<&'q DepNode> {
         let nodes: Vec<_> = self.0.iter().cloned().collect();
-        nodes.into_cow()
+        nodes.into()
     }
     fn edges(&self) -> dot::Edges<(&'q DepNode, &'q DepNode)> {
-        self.1[..].into_cow()
+        self.1[..].into()
     }
     fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode {
         edge.0
index f04e5496ce443fb503c821c7c09b0fae140b422f..d18edf22dc10c29c3a1902a088134497c6a5063d 100644 (file)
@@ -1558,15 +1558,13 @@ fn validate_const<'a, 'tcx>(
     let ecx = ::rustc_mir::const_eval::mk_eval_cx(tcx, gid.instance, param_env).unwrap();
     let result = (|| {
         let op = ecx.const_to_op(constant)?;
-        let mut todo = vec![(op, Vec::new())];
-        let mut seen = FxHashSet();
-        seen.insert(op);
-        while let Some((op, mut path)) = todo.pop() {
+        let mut ref_tracking = ::rustc_mir::interpret::RefTracking::new(op);
+        while let Some((op, mut path)) = ref_tracking.todo.pop() {
             ecx.validate_operand(
                 op,
                 &mut path,
-                &mut seen,
-                &mut todo,
+                Some(&mut ref_tracking),
+                /* const_mode */ true,
             )?;
         }
         Ok(())
index 693cfea3c95f0d4b3cbabdaa44d944abfb407c83..ea62694f8be753c7c52e6b1c71fd8127b0af5282 100644 (file)
@@ -68,6 +68,7 @@ enum GroupedMoveError<'tcx> {
 enum BorrowedContentSource {
     Arc,
     Rc,
+    DerefRawPointer,
     Other,
 }
 
@@ -76,6 +77,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             BorrowedContentSource::Arc => write!(f, "an `Arc`"),
             BorrowedContentSource::Rc => write!(f, "an `Rc`"),
+            BorrowedContentSource::DerefRawPointer => write!(f, "dereference of raw pointer"),
             BorrowedContentSource::Other => write!(f, "borrowed content"),
         }
     }
@@ -279,6 +281,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
                             self.prefixes(&original_path, PrefixSet::All)
                             .any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
                                  .is_some());
+                        debug!("report: ty={:?}", ty);
                         match ty.sty {
                             ty::Array(..) | ty::Slice(..) =>
                                 self.infcx.tcx.cannot_move_out_of_interior_noncopy(
@@ -582,6 +585,18 @@ fn borrowed_content_source(&self, place: &Place<'tcx>) -> BorrowedContentSource
             }
         }
 
+        // If we didn't find an `Arc` or an `Rc`, then check specifically for
+        // a dereference of a place that has the type of a raw pointer.
+        // We can't use `place.ty(..).to_ty(..)` here as that strips away the raw pointer.
+        if let Place::Projection(box Projection {
+            base,
+            elem: ProjectionElem::Deref,
+        }) = place {
+            if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
+                return BorrowedContentSource::DerefRawPointer;
+            }
+        }
+
         BorrowedContentSource::Other
     }
 }
index ba625fb08c82c6865d9103cc000c06f9f40c2e45..5ab1605d7f07ab404fc79d2ae791a68fe8a5412e 100644 (file)
@@ -218,6 +218,38 @@ pub(super) fn report_mutability_error(
         debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on);
 
         match the_place_err {
+            // Suggest making an existing shared borrow in a struct definition a mutable borrow.
+            //
+            // This is applicable when we have a deref of a field access to a deref of a local -
+            // something like `*((*_1).0`. The local that we get will be a reference to the
+            // struct we've got a field access of (it must be a reference since there's a deref
+            // after the field access).
+            Place::Projection(box Projection {
+                base: Place::Projection(box Projection {
+                    base: Place::Projection(box Projection {
+                        base,
+                        elem: ProjectionElem::Deref,
+                    }),
+                    elem: ProjectionElem::Field(field, _),
+                }),
+                elem: ProjectionElem::Deref,
+            }) => {
+                err.span_label(span, format!("cannot {ACT}", ACT = act));
+
+                if let Some((span, message)) = annotate_struct_field(
+                    self.infcx.tcx,
+                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx),
+                    field,
+                ) {
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "consider changing this to be mutable",
+                        message,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            },
+
             // Suggest removing a `&mut` from the use of a mutable reference.
             Place::Local(local)
                 if {
@@ -592,3 +624,54 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
 fn is_closure_or_generator(ty: ty::Ty) -> bool {
     ty.is_closure() || ty.is_generator()
 }
+
+/// Add a suggestion to a struct definition given a field access to a local.
+/// This function expects the local to be a reference to a struct in order to produce a suggestion.
+///
+/// ```text
+/// LL |     s: &'a String
+///    |        ---------- use `&'a mut String` here to make mutable
+/// ```
+fn annotate_struct_field(
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    field: &mir::Field,
+) -> Option<(Span, String)> {
+    // Expect our local to be a reference to a struct of some kind.
+    if let ty::TyKind::Ref(_, ty, _) = ty.sty {
+        if let ty::TyKind::Adt(def, _) = ty.sty {
+            let field = def.all_fields().nth(field.index())?;
+            // Use the HIR types to construct the diagnostic message.
+            let node_id = tcx.hir.as_local_node_id(field.did)?;
+            let node = tcx.hir.find(node_id)?;
+            // Now we're dealing with the actual struct that we're going to suggest a change to,
+            // we can expect a field that is an immutable reference to a type.
+            if let hir::Node::Field(field) = node {
+                if let hir::TyKind::Rptr(lifetime, hir::MutTy {
+                    mutbl: hir::Mutability::MutImmutable,
+                    ref ty
+                }) = field.ty.node {
+                    // Get the snippets in two parts - the named lifetime (if there is one) and
+                    // type being referenced, that way we can reconstruct the snippet without loss
+                    // of detail.
+                    let type_snippet = tcx.sess.source_map().span_to_snippet(ty.span).ok()?;
+                    let lifetime_snippet = if !lifetime.is_elided() {
+                        format!("{} ", tcx.sess.source_map().span_to_snippet(lifetime.span).ok()?)
+                    } else {
+                        String::new()
+                    };
+
+                    return Some((
+                        field.ty.span,
+                        format!(
+                            "&{}mut {}",
+                            lifetime_snippet, &*type_snippet,
+                        ),
+                    ));
+                }
+            }
+        }
+    }
+
+    None
+}
index 2e018f746f38937f697ed7cc856f6fb8780f8020..3d4b2456f9657eebe8c30c1dbb7d7cb50755134b 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 use borrow_check::nll::type_check::Locations;
-use borrow_check::nll::constraints::{ConstraintCategory, ConstraintIndex};
+use borrow_check::nll::constraints::ConstraintIndex;
 use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph;
 use rustc_data_structures::indexed_vec::IndexVec;
index 76ebc06bfd2f612617bfc144948a1f4ce6472f10..a873af8333a7fb0af867ae6423ed36645e4951d6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
     constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
 }
 
-/// Constraints can be categorized to determine whether and why they are
-/// interesting. Order of variants indicates sort order of the category,
-/// thereby influencing diagnostic output.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-pub enum ConstraintCategory {
-    Return,
-    TypeAnnotation,
-    Cast,
-    CallArgument,
-
-    /// A constraint that came from checking the body of a closure.
-    ///
-    /// Ideally we would give an explanation that points to the relevant part
-    /// of the closure's body.
-    ClosureBounds,
-    CopyBound,
-    SizedBound,
-    Assignment,
-    OpaqueType,
-
-    /// A "boring" constraint (caused by the given location) is one that
-    /// the user probably doesn't want to see described in diagnostics,
-    /// because it is kind of an artifact of the type system setup.
-    /// Example: `x = Foo { field: y }` technically creates
-    /// intermediate regions representing the "type of `Foo { field: y
-    /// }`", and data flows from `y` into those variables, but they
-    /// are not very interesting. The assignment into `x` on the other
-    /// hand might be.
-    Boring,
-    // Boring and applicable everywhere.
-    BoringNoLocation,
-
-    /// A constraint that doesn't correspond to anything the user sees.
-    Internal,
-}
-
 impl ConstraintSet {
     crate fn push(&mut self, constraint: OutlivesConstraint) {
         debug!(
index e55469436abf0a72b08541f9d4097ae143a4a30c..307112f8ba16a26fb17dd4e4a482d4d2b5d96db7 100644 (file)
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
 use rustc::ty::{self, Region, TyCtxt};
-use rustc::mir::{FakeReadCause, Local, Location, Mir, Operand};
-use rustc::mir::{Place, StatementKind, TerminatorKind};
+use rustc::mir::{
+    CastKind, FakeReadCause, Local, Location, Mir, Operand, Place, Projection, ProjectionElem,
+    Rvalue, Statement, StatementKind, TerminatorKind
+};
 use rustc_errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
@@ -34,6 +36,7 @@ pub(in borrow_check) enum BorrowExplanation<'tcx> {
 
 #[derive(Clone, Copy)]
 pub(in borrow_check) enum LaterUseKind {
+    TraitCapture,
     ClosureCapture,
     Call,
     FakeLetRead,
@@ -51,6 +54,7 @@ pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx>(
         match *self {
             BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => {
                 let message = match later_use_kind {
+                    LaterUseKind::TraitCapture => "borrow later captured here by trait object",
                     LaterUseKind::ClosureCapture => "borrow later captured here by closure",
                     LaterUseKind::Call =>  "borrow later used by call",
                     LaterUseKind::FakeLetRead => "borrow later stored here",
@@ -60,9 +64,10 @@ pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx>(
             },
             BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => {
                 let message = match later_use_kind {
-                    LaterUseKind::ClosureCapture => {
-                        "borrow captured here by closure, in later iteration of loop"
-                    },
+                    LaterUseKind::TraitCapture =>
+                        "borrow captured here by trait object, in later iteration of loop",
+                    LaterUseKind::ClosureCapture =>
+                        "borrow captured here by closure, in later iteration of loop",
                     LaterUseKind::Call =>  "borrow used by call, in later iteration of loop",
                     LaterUseKind::FakeLetRead => "borrow later stored here",
                     LaterUseKind::Other => "borrow used here, in later iteration of loop",
@@ -200,13 +205,13 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                     .or_else(|| self.borrow_spans(span, location));
 
                 if self.is_borrow_location_in_loop(context.loc) {
-                    let later_use = self.later_use_kind(spans, location);
+                    let later_use = self.later_use_kind(borrow, spans, location);
                     BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1)
                 } else {
                     // Check if the location represents a `FakeRead`, and adapt the error
                     // message to the `FakeReadCause` it is from: in particular,
                     // the ones inserted in optimized `let var = <expr>` patterns.
-                    let later_use = self.later_use_kind(spans, location);
+                    let later_use = self.later_use_kind(borrow, spans, location);
                     BorrowExplanation::UsedLater(later_use.0, later_use.1)
                 }
             }
@@ -316,42 +321,184 @@ fn is_borrow_location_in_loop(
         false
     }
 
-    fn later_use_kind(&self, use_spans: UseSpans, location: Location) -> (LaterUseKind, Span) {
-        use self::LaterUseKind::*;
-
-        let block = &self.mir.basic_blocks()[location.block];
+    /// Determine how the borrow was later used.
+    fn later_use_kind(
+        &self,
+        borrow: &BorrowData<'tcx>,
+        use_spans: UseSpans,
+        location: Location
+    ) -> (LaterUseKind, Span) {
         match use_spans {
-            UseSpans::ClosureUse { var_span, .. } => (LaterUseKind::ClosureCapture, var_span),
+            UseSpans::ClosureUse { var_span, .. } => {
+                // Used in a closure.
+                (LaterUseKind::ClosureCapture, var_span)
+            },
             UseSpans::OtherUse(span) => {
-                (if let Some(stmt) = block.statements.get(location.statement_index) {
-                    match stmt.kind {
-                        StatementKind::FakeRead(FakeReadCause::ForLet, _) => FakeLetRead,
-                        _ => Other,
+                let block = &self.mir.basic_blocks()[location.block];
+
+                let kind = if let Some(&Statement {
+                    kind: StatementKind::FakeRead(FakeReadCause::ForLet, _),
+                    ..
+                }) = block.statements.get(location.statement_index) {
+                    LaterUseKind::FakeLetRead
+                } else if self.was_captured_by_trait_object(borrow) {
+                    LaterUseKind::TraitCapture
+                } else if location.statement_index == block.statements.len() {
+                    if let TerminatorKind::Call {
+                        ref func, from_hir_call: true, ..
+                    } = block.terminator().kind {
+                        // Just point to the function, to reduce the chance of overlapping spans.
+                        let function_span = match func {
+                            Operand::Constant(c) => c.span,
+                            Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => {
+                                let local_decl = &self.mir.local_decls[*l];
+                                if local_decl.name.is_none() {
+                                    local_decl.source_info.span
+                                } else {
+                                    span
+                                }
+                            },
+                            _ => span,
+                        };
+                        return (LaterUseKind::Call, function_span);
+                    } else {
+                        LaterUseKind::Other
                     }
                 } else {
-                    assert_eq!(location.statement_index, block.statements.len());
-                    match block.terminator().kind {
-                        TerminatorKind::Call { ref func, from_hir_call: true, .. } => {
-                            // Just point to the function, to reduce the chance
-                            // of overlapping spans.
-                            let function_span = match func {
-                                Operand::Constant(c) => c.span,
-                                Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => {
-                                    let local_decl = &self.mir.local_decls[*l];
-                                    if local_decl.name.is_none() {
-                                        local_decl.source_info.span
-                                    } else {
-                                        span
-                                    }
-                                },
-                                _ => span,
-                            };
-                            return (Call, function_span);
+                    LaterUseKind::Other
+                };
+
+                (kind, span)
+            }
+        }
+    }
+
+    /// Check if a borrowed value was captured by a trait object. We do this by
+    /// looking forward in the MIR from the reserve location and checking if we see
+    /// a unsized cast to a trait object on our data.
+    fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
+        // Start at the reserve location, find the place that we want to see cast to a trait object.
+        let location = borrow.reserve_location;
+        let block = &self.mir[location.block];
+        let stmt = block.statements.get(location.statement_index);
+        debug!("was_captured_by_trait_object: location={:?} stmt={:?}", location, stmt);
+
+        // We make a `queue` vector that has the locations we want to visit. As of writing, this
+        // will only ever have one item at any given time, but by using a vector, we can pop from
+        // it which simplifies the termination logic.
+        let mut queue = vec![location];
+        let mut target = if let Some(&Statement {
+            kind: StatementKind::Assign(Place::Local(local), _),
+            ..
+        }) = stmt {
+            local
+        } else {
+            return false;
+        };
+
+        debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
+        while let Some(current_location) = queue.pop() {
+            debug!("was_captured_by_trait: target={:?}", target);
+            let block = &self.mir[current_location.block];
+            // We need to check the current location to find out if it is a terminator.
+            let is_terminator = current_location.statement_index == block.statements.len();
+            if !is_terminator {
+                let stmt = &block.statements[current_location.statement_index];
+                debug!("was_captured_by_trait_object: stmt={:?}", stmt);
+
+                // The only kind of statement that we care about is assignments...
+                if let StatementKind::Assign(
+                    place,
+                    box rvalue,
+                ) = &stmt.kind {
+                    let into = match place {
+                        Place::Local(into) => into,
+                        Place::Projection(box Projection {
+                            base: Place::Local(into),
+                            elem: ProjectionElem::Deref,
+                        }) => into,
+                        _ =>  {
+                            // Continue at the next location.
+                            queue.push(current_location.successor_within_block());
+                            continue;
                         },
-                        _ => Other,
+                    };
+
+                    match rvalue {
+                        // If we see a use, we should check whether it is our data, and if so
+                        // update the place that we're looking for to that new place.
+                        Rvalue::Use(operand) => match operand {
+                            Operand::Copy(Place::Local(from)) |
+                            Operand::Move(Place::Local(from)) if *from == target => {
+                                target = *into;
+                            },
+                            _ => {},
+                        },
+                        // If we see a unsized cast, then if it is our data we should check
+                        // whether it is being cast to a trait object.
+                        Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand {
+                            Operand::Copy(Place::Local(from)) |
+                            Operand::Move(Place::Local(from)) if *from == target => {
+                                debug!("was_captured_by_trait_object: ty={:?}", ty);
+                                // Check the type for a trait object.
+                                match ty.sty {
+                                    // `&dyn Trait`
+                                    ty::TyKind::Ref(_, ty, _) if ty.is_trait() => return true,
+                                    // `Box<dyn Trait>`
+                                    _ if ty.is_box() && ty.boxed_ty().is_trait() =>
+                                        return true,
+                                    // `dyn Trait`
+                                    _ if ty.is_trait() => return true,
+                                    // Anything else.
+                                    _ => return false,
+                                }
+                            },
+                            _ => return false,
+                        },
+                        _ => {},
                     }
-                }, span)
+                }
+
+                // Continue at the next location.
+                queue.push(current_location.successor_within_block());
+            } else {
+                // The only thing we need to do for terminators is progress to the next block.
+                let terminator = block.terminator();
+                debug!("was_captured_by_trait_object: terminator={:?}", terminator);
+
+                match &terminator.kind {
+                    TerminatorKind::Call {
+                        destination: Some((Place::Local(dest), block)),
+                        args,
+                        ..
+                    } => {
+                        debug!(
+                            "was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
+                            target, dest, args
+                        );
+                        // Check if one of the arguments to this function is the target place.
+                        let found_target = args.iter().any(|arg| {
+                            if let Operand::Move(Place::Local(potential)) = arg {
+                                *potential == target
+                            } else {
+                                false
+                            }
+                        });
+
+                        // If it is, follow this to the next block and update the target.
+                        if found_target {
+                            target = *dest;
+                            queue.push(block.start_location());
+                        }
+                    },
+                    _ => {},
+                }
             }
+
+            debug!("was_captured_by_trait: queue={:?}", queue);
         }
+
+        // We didn't find anything and ran out of locations to check.
+        false
     }
 }
index 723b0e6fff6f8d4219d6c17814f6cf7eb19541e8..6e35f2e63f74c2d090718d5c81ba98810e3c780a 100644 (file)
@@ -138,6 +138,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     let MirTypeckRegionConstraints {
         mut liveness_constraints,
         outlives_constraints,
+        closure_bounds_mapping,
         type_tests,
     } = constraints;
 
@@ -157,6 +158,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         universal_region_relations,
         mir,
         outlives_constraints,
+        closure_bounds_mapping,
         type_tests,
         liveness_constraints,
         elements,
index 31d7c7c631e1791f177d6996164b415ca7dc553b..8191dd720e7b2db1a2abfa419c2940c723d0c15b 100644 (file)
@@ -8,17 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::constraints::{OutlivesConstraint, ConstraintCategory};
+use borrow_check::nll::constraints::{OutlivesConstraint};
 use borrow_check::nll::region_infer::RegionInferenceContext;
+use borrow_check::nll::region_infer::error_reporting::region_name::RegionNameSource;
+use borrow_check::nll::type_check::Locations;
+use borrow_check::nll::universal_regions::DefiningTy;
 use rustc::hir::def_id::DefId;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc::infer::InferCtxt;
-use rustc::mir::{Location, Mir};
+use rustc::mir::{ConstraintCategory, Location, Mir};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use std::collections::VecDeque;
-use std::fmt;
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 use syntax::errors::Applicability;
 
 use self::region_name::RegionName;
 
-impl fmt::Display for ConstraintCategory {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+trait ConstraintDescription {
+    fn description(&self) -> &'static str;
+}
+
+impl ConstraintDescription for ConstraintCategory {
+    fn description(&self) -> &'static str {
         // Must end with a space. Allows for empty names to be provided.
         match self {
-            ConstraintCategory::Assignment => write!(f, "assignment "),
-            ConstraintCategory::Return => write!(f, "returning this value "),
-            ConstraintCategory::Cast => write!(f, "cast "),
-            ConstraintCategory::CallArgument => write!(f, "argument "),
-            ConstraintCategory::TypeAnnotation => write!(f, "type annotation "),
-            ConstraintCategory::ClosureBounds => write!(f, "closure body "),
-            ConstraintCategory::SizedBound => write!(f, "proving this value is `Sized` "),
-            ConstraintCategory::CopyBound => write!(f, "copying this value "),
-            ConstraintCategory::OpaqueType => write!(f, "opaque type "),
+            ConstraintCategory::Assignment => "assignment ",
+            ConstraintCategory::Return => "returning this value ",
+            ConstraintCategory::Cast => "cast ",
+            ConstraintCategory::CallArgument => "argument ",
+            ConstraintCategory::TypeAnnotation => "type annotation ",
+            ConstraintCategory::ClosureBounds => "closure body ",
+            ConstraintCategory::SizedBound => "proving this value is `Sized` ",
+            ConstraintCategory::CopyBound => "copying this value ",
+            ConstraintCategory::OpaqueType => "opaque type ",
             ConstraintCategory::Boring
             | ConstraintCategory::BoringNoLocation
-            | ConstraintCategory::Internal => write!(f, ""),
+            | ConstraintCategory::Internal => "",
         }
     }
 }
@@ -89,7 +95,13 @@ fn best_blame_constraint(
         // Classify each of the constraints along the path.
         let mut categorized_path: Vec<(ConstraintCategory, Span)> = path
             .iter()
-            .map(|constraint| (constraint.category, constraint.locations.span(mir)))
+            .map(|constraint| {
+                if constraint.category == ConstraintCategory::ClosureBounds {
+                    self.retrieve_closure_constraint_info(mir, &constraint)
+                } else {
+                    (constraint.category, constraint.locations.span(mir))
+                }
+            })
             .collect();
         debug!(
             "best_blame_constraint: categorized_path={:#?}",
@@ -253,6 +265,9 @@ pub(super) fn report_error(
         debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
                fr_is_local, outlived_fr_is_local, category);
         match (category, fr_is_local, outlived_fr_is_local) {
+            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) =>
+                self.report_fnmut_error(mir, infcx, mir_def_id, fr, outlived_fr, span,
+                                        errors_buffer),
             (ConstraintCategory::Assignment, true, false) |
             (ConstraintCategory::CallArgument, true, false) =>
                 self.report_escaping_data_error(mir, infcx, mir_def_id, fr, outlived_fr,
@@ -264,6 +279,85 @@ pub(super) fn report_error(
         };
     }
 
+    /// Report a specialized error when `FnMut` closures return a reference to a captured variable.
+    /// This function expects `fr` to be local and `outlived_fr` to not be local.
+    ///
+    /// ```text
+    /// error: captured variable cannot escape `FnMut` closure body
+    ///   --> $DIR/issue-53040.rs:15:8
+    ///    |
+    /// LL |     || &mut v;
+    ///    |     -- ^^^^^^ creates a reference to a captured variable which escapes the closure body
+    ///    |     |
+    ///    |     inferred to be a `FnMut` closure
+    ///    |
+    ///    = note: `FnMut` closures only have access to their captured variables while they are
+    ///            executing...
+    ///    = note: ...therefore, returned references to captured variables will escape the closure
+    /// ```
+    fn report_fnmut_error(
+        &self,
+        mir: &Mir<'tcx>,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        mir_def_id: DefId,
+        _fr: RegionVid,
+        outlived_fr: RegionVid,
+        span: Span,
+        errors_buffer: &mut Vec<Diagnostic>,
+    ) {
+        let mut diag = infcx.tcx.sess.struct_span_err(
+            span,
+            "captured variable cannot escape `FnMut` closure body",
+        );
+
+        // We should check if the return type of this closure is in fact a closure - in that
+        // case, we can special case the error further.
+        let return_type_is_closure = self.universal_regions.unnormalized_output_ty.is_closure();
+        let message = if return_type_is_closure {
+            "returns a closure that contains a reference to a captured variable, which then \
+             escapes the closure body"
+        } else {
+            "returns a reference to a captured variable which escapes the closure body"
+        };
+
+        diag.span_label(
+            span,
+            message,
+        );
+
+        match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).source {
+            RegionNameSource::NamedEarlyBoundRegion(fr_span) |
+            RegionNameSource::NamedFreeRegion(fr_span) |
+            RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _) |
+            RegionNameSource::CannotMatchHirTy(fr_span, _) |
+            RegionNameSource::MatchedHirTy(fr_span) |
+            RegionNameSource::MatchedAdtAndSegment(fr_span) |
+            RegionNameSource::AnonRegionFromUpvar(fr_span, _) |
+            RegionNameSource::AnonRegionFromOutput(fr_span, _, _) => {
+                diag.span_label(fr_span, "inferred to be a `FnMut` closure");
+            },
+            _ => {},
+        }
+
+        diag.note("`FnMut` closures only have access to their captured variables while they are \
+                   executing...");
+        diag.note("...therefore, they cannot allow references to captured variables to escape");
+
+        diag.buffer(errors_buffer);
+    }
+
+    /// Reports a error specifically for when data is escaping a closure.
+    ///
+    /// ```text
+    /// error: borrowed data escapes outside of function
+    ///   --> $DIR/lifetime-bound-will-change-warning.rs:44:5
+    ///    |
+    /// LL | fn test2<'a>(x: &'a Box<Fn()+'a>) {
+    ///    |              - `x` is a reference that is only valid in the function body
+    /// LL |     // but ref_obj will not, so warn.
+    /// LL |     ref_obj(x)
+    ///    |     ^^^^^^^^^^ `x` escapes the function body here
+    /// ```
     fn report_escaping_data_error(
         &self,
         mir: &Mir<'tcx>,
@@ -295,31 +389,46 @@ fn report_escaping_data_error(
             span, &format!("borrowed data escapes outside of {}", escapes_from),
         );
 
-        if let Some((outlived_fr_name, outlived_fr_span)) = outlived_fr_name_and_span {
-            if let Some(name) = outlived_fr_name {
-                diag.span_label(
-                    outlived_fr_span,
-                    format!("`{}` is declared here, outside of the {} body", name, escapes_from),
-                );
-            }
+        if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
+            diag.span_label(
+                outlived_fr_span,
+                format!(
+                    "`{}` is declared here, outside of the {} body",
+                    outlived_fr_name, escapes_from
+                ),
+            );
         }
 
-        if let Some((fr_name, fr_span)) = fr_name_and_span {
-            if let Some(name) = fr_name {
-                diag.span_label(
-                    fr_span,
-                    format!("`{}` is a reference that is only valid in the {} body",
-                            name, escapes_from),
-                );
+        if let Some((Some(fr_name), fr_span)) = fr_name_and_span {
+            diag.span_label(
+                fr_span,
+                format!(
+                    "`{}` is a reference that is only valid in the {} body",
+                    fr_name, escapes_from
+                ),
+            );
 
-                diag.span_label(span, format!("`{}` escapes the {} body here",
-                                               name, escapes_from));
-            }
+            diag.span_label(span, format!("`{}` escapes the {} body here", fr_name, escapes_from));
         }
 
         diag.buffer(errors_buffer);
     }
 
+    /// Reports a region inference error for the general case with named/synthesized lifetimes to
+    /// explain what is happening.
+    ///
+    /// ```text
+    /// error: unsatisfied lifetime constraints
+    ///   --> $DIR/regions-creating-enums3.rs:17:5
+    ///    |
+    /// LL | fn mk_add_bad1<'a,'b>(x: &'a ast<'a>, y: &'b ast<'b>) -> ast<'a> {
+    ///    |                -- -- lifetime `'b` defined here
+    ///    |                |
+    ///    |                lifetime `'a` defined here
+    /// LL |     ast::add(x, y)
+    ///    |     ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
+    ///    |                    is returning data with lifetime `'b`
+    /// ```
     fn report_general_error(
         &self,
         mir: &Mir<'tcx>,
@@ -358,7 +467,7 @@ fn report_general_error(
             _ => {
                 diag.span_label(span, format!(
                     "{}requires that `{}` must outlive `{}`",
-                    category, fr_name, outlived_fr_name,
+                    category.description(), fr_name, outlived_fr_name,
                 ));
             },
         }
@@ -370,6 +479,15 @@ fn report_general_error(
         diag.buffer(errors_buffer);
     }
 
+    /// Adds a suggestion to errors where a `impl Trait` is returned.
+    ///
+    /// ```text
+    /// help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as
+    ///       a constraint
+    ///    |
+    /// LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + 'a {
+    ///    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    /// ```
     fn add_static_impl_trait_suggestion(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
@@ -470,8 +588,42 @@ fn add_static_impl_trait_suggestion(
         mir: &Mir<'tcx>,
         fr1: RegionVid,
         fr2: RegionVid,
-    ) -> Span {
-        let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
-        span
+    ) -> (ConstraintCategory, Span) {
+        let (category, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
+        (category, span)
+    }
+
+    fn retrieve_closure_constraint_info(
+        &self,
+        mir: &Mir<'tcx>,
+        constraint: &OutlivesConstraint
+    ) -> (ConstraintCategory, Span) {
+        let loc = match constraint.locations {
+            Locations::All(span) => return (constraint.category, span),
+            Locations::Single(loc) => loc,
+        };
+
+        let opt_span_category = self
+            .closure_bounds_mapping[&loc]
+            .get(&(constraint.sup, constraint.sub));
+        *opt_span_category.unwrap_or(&(constraint.category, mir.source_info(loc).span))
+    }
+
+    /// Returns `true` if a closure is inferred to be an `FnMut` closure.
+    crate fn is_closure_fn_mut(
+        &self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        fr: RegionVid,
+    ) -> bool {
+        if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
+            if let ty::BoundRegion::BrEnv = free_region.bound_region {
+                if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty {
+                    let closure_kind_ty = substs.closure_kind_ty(def_id, infcx.tcx);
+                    return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind();
+                }
+            }
+        }
+
+        false
     }
 }
index 3a545d9adbfcee457a062295a505d9f1803f9f83..65ba2f537bf214c98982c05ce815e9b02bde5652 100644 (file)
@@ -27,8 +27,8 @@
 
 #[derive(Debug)]
 crate struct RegionName {
-    name: InternedString,
-    source: RegionNameSource,
+    crate name: InternedString,
+    crate source: RegionNameSource,
 }
 
 #[derive(Debug)]
index 57ff0f4c10a4b3bf1a36f08ee64a270f606d5fe5..73fa1b0cfb78de79251ef241b0e46355b3f502f6 100644 (file)
@@ -50,11 +50,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             .defining_ty
             .upvar_tys(tcx)
             .position(|upvar_ty| {
-                debug!(
-                    "get_upvar_index_for_region: upvar_ty = {:?}",
-                    upvar_ty,
-                );
-                tcx.any_free_region_meets(&upvar_ty, |r| r.to_region_vid() == fr)
+                debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty);
+                tcx.any_free_region_meets(&upvar_ty, |r| {
+                    let r = r.to_region_vid();
+                    debug!("get_upvar_index_for_region: r={:?} fr={:?}", r, fr);
+                    r == fr
+                })
             })?;
 
         let upvar_ty = self
index 34e893d2a59f24970b9c92ff46c12ca5bc475143..e2e19a85bec879bd06b1ef1cee474edbf9238d2c 100644 (file)
@@ -14,7 +14,7 @@
 
 use super::*;
 use borrow_check::nll::constraints::OutlivesConstraint;
-use dot::{self, IntoCow};
+use dot;
 use std::borrow::Cow;
 use std::io::{self, Write};
 
@@ -49,7 +49,7 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
     type Edge = OutlivesConstraint;
 
     fn graph_id(&'this self) -> dot::Id<'this> {
-        dot::Id::new("RegionInferenceContext".to_string()).unwrap()
+        dot::Id::new("RegionInferenceContext").unwrap()
     }
     fn node_id(&'this self, n: &RegionVid) -> dot::Id<'this> {
         dot::Id::new(format!("r{}", n.index())).unwrap()
@@ -58,10 +58,10 @@ fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
         Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
     }
     fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
-        dot::LabelText::LabelStr(format!("{:?}", n).into_cow())
+        dot::LabelText::LabelStr(format!("{:?}", n).into())
     }
     fn edge_label(&'this self, e: &OutlivesConstraint) -> dot::LabelText<'this> {
-        dot::LabelText::LabelStr(format!("{:?}", e.locations).into_cow())
+        dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
     }
 }
 
@@ -71,10 +71,10 @@ impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
 
     fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
         let vids: Vec<RegionVid> = self.regioncx.definitions.indices().collect();
-        vids.into_cow()
+        vids.into()
     }
     fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
-        (&self.regioncx.constraints.raw[..]).into_cow()
+        (&self.regioncx.constraints.raw[..]).into()
     }
 
     // Render `a: b` as `a -> b`, indicating the flow
@@ -109,7 +109,7 @@ fn node_shape(&'this self, _node: &ConstraintSccIndex) -> Option<dot::LabelText<
     }
     fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
         let nodes = &self.nodes_per_scc[*n];
-        dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into_cow())
+        dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into())
     }
 }
 
@@ -119,7 +119,7 @@ impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for SccConstraints<'a, 'tcx> {
 
     fn nodes(&'this self) -> dot::Nodes<'this, ConstraintSccIndex> {
         let vids: Vec<ConstraintSccIndex> = self.regioncx.constraint_sccs.all_sccs().collect();
-        vids.into_cow()
+        vids.into()
     }
     fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccIndex)> {
         let edges: Vec<_> = self.regioncx
@@ -134,7 +134,7 @@ fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccInd
             })
             .collect();
 
-        edges.into_cow()
+        edges.into()
     }
 
     // Render `a: b` as `a -> b`, indicating the flow
index 4a8f011b606b739e6796223498abd09180c41431..56bb6a87d44fa7d51fa613599d8f0d4a1e625ea7 100644 (file)
 use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
 use rustc::mir::{
-    ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location,
-    Mir,
+    ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
+    ConstraintCategory, Local, Location, Mir,
 };
 use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common;
 use rustc_data_structures::bit_set::BitSet;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use syntax_pos::Span;
 
 use std::rc::Rc;
 
@@ -60,10 +62,16 @@ pub struct RegionInferenceContext<'tcx> {
     /// the SCC (see `constraint_sccs`) and for error reporting.
     constraint_graph: Rc<NormalConstraintGraph>,
 
-    /// The SCC computed from `constraints` and the constraint graph. Used to compute the values
-    /// of each region.
+    /// The SCC computed from `constraints` and the constraint graph. Used to
+    /// compute the values of each region.
     constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
+    /// Map closure bounds to a `Span` that should be used for error reporting.
+    closure_bounds_mapping: FxHashMap<
+        Location,
+        FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
+    >,
+
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
     /// visible from this index.
@@ -187,6 +195,10 @@ pub(crate) fn new(
         universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
         _mir: &Mir<'tcx>,
         outlives_constraints: ConstraintSet,
+        closure_bounds_mapping: FxHashMap<
+            Location,
+            FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
+        >,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues<RegionVid>,
         elements: &Rc<RegionValueElements>,
@@ -220,6 +232,7 @@ pub(crate) fn new(
             constraints,
             constraint_graph,
             constraint_sccs,
+            closure_bounds_mapping,
             scc_universes,
             scc_representatives,
             scc_values,
@@ -727,6 +740,7 @@ fn try_promote_type_test<'gcx>(
                 subject,
                 outlived_free_region: non_local_ub,
                 blame_span: locations.span(mir),
+                category: ConstraintCategory::Boring,
             };
             debug!("try_promote_type_test: pushing {:#?}", requirement);
             propagated_outlives_requirements.push(requirement);
@@ -1125,7 +1139,7 @@ fn check_universal_region<'gcx>(
                 longer_fr, shorter_fr,
             );
 
-            let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
+            let blame_span_category = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
 
             if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
                 // Shrink `fr` until we find a non-local region (if we do).
@@ -1150,7 +1164,8 @@ fn check_universal_region<'gcx>(
                     propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                         subject: ClosureOutlivesSubject::Region(fr_minus),
                         outlived_free_region: shorter_fr_plus,
-                        blame_span: blame_span,
+                        blame_span: blame_span_category.1,
+                        category: blame_span_category.0,
                     });
                     return;
                 }
@@ -1213,7 +1228,7 @@ fn check_bound_universal_region<'gcx>(
         };
 
         // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
-        let span = self.find_outlives_blame_span(mir, longer_fr, error_region);
+        let (_, span) = self.find_outlives_blame_span(mir, longer_fr, error_region);
 
         // Obviously, this error message is far from satisfactory.
         // At present, though, it only appears in unit tests --
index d77863d598f663792fd9a7f0edd0b6779c5bb7f6..15a60badc93e2b50ec4ae8e84585c31ec5a46459 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
-use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
+use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
@@ -65,6 +65,14 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
         debug!("visit_ty: ty={:?}", ty);
     }
 
+    fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) {
+        // `user_ty` annotations represent the types that the user
+        // wrote in the progarm. We don't want to erase the regions
+        // from these types: rather, we want to add them as
+        // constraints at type-check time.
+        debug!("visit_user_ty: skipping renumber");
+    }
+
     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
         debug!("visit_substs(substs={:?}, location={:?})", substs, location);
 
@@ -112,19 +120,6 @@ fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: L
         debug!("visit_closure_substs: substs={:?}", substs);
     }
 
-    fn visit_ascribe_user_ty(
-        &mut self,
-        _place: &mut Place<'tcx>,
-        _variance: &mut ty::Variance,
-        _c_ty: &mut CanonicalTy<'tcx>,
-        _location: Location,
-    ) {
-        // User-assert-ty statements represent types that the user added explicitly.
-        // We don't want to erase the regions from these types: rather, we want to
-        // add them as constraints at type-check time.
-        debug!("visit_user_assert_ty: skipping renumber");
-    }
-
     fn visit_statement(
         &mut self,
         block: BasicBlock,
index dabf669eca65f0de63169e9584a4e8ae08a8df5f..4ab0f952bdee94fe41bbd252076be0267a4324a5 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::region_infer::TypeTest;
 use borrow_check::nll::type_check::Locations;
 use borrow_check::nll::universal_regions::UniversalRegions;
@@ -17,6 +17,7 @@
 use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc::infer::region_constraints::{GenericKind, VerifyBound};
 use rustc::infer::{self, SubregionOrigin};
+use rustc::mir::ConstraintCategory;
 use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, TyCtxt};
 use syntax_pos::DUMMY_SP;
index f33909db78f9fe2cdb92c8d23fe2674442ed6ec3..35342b2129e6e752a83d036a7eb9ccddba4a604f 100644 (file)
 use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use borrow_check::nll::ToRegionVid;
-use borrow_check::nll::constraints::ConstraintCategory;
 use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::free_region_map::FreeRegionRelations;
 use rustc::infer::region_constraints::GenericKind;
 use rustc::infer::InferCtxt;
+use rustc::mir::ConstraintCategory;
 use rustc::traits::query::outlives_bounds::{self, OutlivesBound};
 use rustc::traits::query::type_op::{self, TypeOp};
 use rustc::ty::{self, RegionVid, Ty};
index 942f19965bf375d75402e94541a29d57f3edc521..a4665984d3e0b0448d36c6f0cabdd74f139bce7e 100644 (file)
@@ -24,7 +24,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 
-use super::{ConstraintCategory, Locations, TypeChecker};
+use super::{Locations, TypeChecker};
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     pub(super) fn equate_inputs_and_outputs(
index 6c1252fc73d8bc0da81997add09880c99cbe2ed6..bc4e0ca235139c63ab7e5aa54623982a8407ec5d 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use borrow_check::location::LocationTable;
-use borrow_check::nll::constraints::ConstraintCategory;
 use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
 use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
 use borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
@@ -19,7 +18,7 @@
 use dataflow::move_paths::MoveData;
 use dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
 use rustc::infer::canonical::QueryRegionConstraint;
-use rustc::mir::{BasicBlock, Local, Location, Mir};
+use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Mir};
 use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc::traits::query::type_op::outlives::DropckOutlives;
 use rustc::traits::query::type_op::TypeOp;
index 99ac80862b13e695a28ac1990bfcc41b9adb0cff..36eb695186c67da0fc328ca7c2eba9de668a45a1 100644 (file)
@@ -13,7 +13,7 @@
 
 use borrow_check::borrow_set::BorrowSet;
 use borrow_check::location::LocationTable;
-use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::values::LivenessValues;
 use borrow_check::nll::region_infer::values::PlaceholderIndices;
@@ -42,7 +42,7 @@
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Subst;
+use rustc::ty::subst::{Subst, UnpackedKind};
 use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
@@ -50,7 +50,7 @@
 use transform::{MirPass, MirSource};
 
 use either::Either;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
@@ -128,6 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     let mut constraints = MirTypeckRegionConstraints {
         liveness_constraints: LivenessValues::new(elements),
         outlives_constraints: ConstraintSet::default(),
+        closure_bounds_mapping: FxHashMap(),
         type_tests: Vec::default(),
     };
     let mut placeholder_indices = PlaceholderIndices::default();
@@ -752,6 +753,11 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
 
     crate outlives_constraints: ConstraintSet,
 
+    crate closure_bounds_mapping: FxHashMap<
+        Location,
+        FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
+    >,
+
     crate type_tests: Vec<TypeTest<'tcx>>,
 }
 
@@ -860,7 +866,7 @@ fn fully_perform_op<R>(
         &mut self,
         locations: Locations,
         category: ConstraintCategory,
-        op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
+        op: impl type_op::TypeOp<'gcx, 'tcx, Output=R>,
     ) -> Fallible<R> {
         let (r, opt_data) = op.fully_perform(self.infcx)?;
 
@@ -1103,9 +1109,9 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                 let place_ty = place.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = rv.ty(mir, tcx);
                 if let Err(terr) =
-                    self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
-                {
-                    span_mirbug!(
+                self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
+                    {
+                        span_mirbug!(
                         self,
                         stmt,
                         "bad assignment ({:?} = {:?}): {:?}",
@@ -1113,7 +1119,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                         rv_ty,
                         terr
                     );
-                }
+                    }
 
                 if let Some(user_ty) = self.rvalue_user_ty(rv) {
                     if let Err(terr) = self.relate_type_and_user_type(
@@ -1233,9 +1239,9 @@ fn check_terminator(
 
                 let locations = term_location.to_locations();
                 if let Err(terr) =
-                    self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
-                {
-                    span_mirbug!(
+                self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
+                    {
+                        span_mirbug!(
                         self,
                         term,
                         "bad DropAndReplace ({:?} = {:?}): {:?}",
@@ -1243,7 +1249,7 @@ fn check_terminator(
                         rv_ty,
                         terr
                     );
-                }
+                    }
             }
             TerminatorKind::SwitchInt {
                 ref discr,
@@ -1387,9 +1393,9 @@ fn check_call_dest(
                 let locations = term_location.to_locations();
 
                 if let Err(terr) =
-                    self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
-                {
-                    span_mirbug!(
+                self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
+                    {
+                        span_mirbug!(
                         self,
                         term,
                         "call dest mismatch ({:?} <- {:?}): {:?}",
@@ -1397,7 +1403,7 @@ fn check_call_dest(
                         sig.output(),
                         terr
                     );
-                }
+                    }
 
                 // When `#![feature(unsized_locals)]` is not enabled,
                 // this check is done at `check_local`.
@@ -2038,7 +2044,7 @@ fn prove_aggregate_predicates(
             aggregate_kind, location
         );
 
-        let instantiated_predicates = match aggregate_kind {
+        let instantiated_predicates = match aggregate_kind  {
             AggregateKind::Adt(def, _, substs, _, _) => {
                 tcx.predicates_of(def.did).instantiate(tcx, substs)
             }
@@ -2064,24 +2070,7 @@ fn prove_aggregate_predicates(
             // these extra requirements are basically like where
             // clauses on the struct.
             AggregateKind::Closure(def_id, substs) => {
-                if let Some(closure_region_requirements) =
-                    tcx.mir_borrowck(*def_id).closure_requirements
-                {
-                    let closure_constraints = closure_region_requirements.apply_requirements(
-                        self.infcx.tcx,
-                        location,
-                        *def_id,
-                        *substs,
-                    );
-
-                    self.push_region_constraints(
-                        location.to_locations(),
-                        ConstraintCategory::ClosureBounds,
-                        &closure_constraints,
-                    );
-                }
-
-                tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
+                self.prove_closure_bounds(tcx, *def_id, *substs, location)
             }
 
             AggregateKind::Generator(def_id, substs, _) => {
@@ -2097,6 +2086,72 @@ fn prove_aggregate_predicates(
         );
     }
 
+    fn prove_closure_bounds(
+        &mut self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        def_id: DefId,
+        substs: ty::ClosureSubsts<'tcx>,
+        location: Location,
+    ) -> ty::InstantiatedPredicates<'tcx> {
+        if let Some(closure_region_requirements) =
+            tcx.mir_borrowck(def_id).closure_requirements
+        {
+            let closure_constraints = closure_region_requirements.apply_requirements(
+                tcx,
+                location,
+                def_id,
+                substs,
+            );
+
+            if let Some(ref mut borrowck_context) = self.borrowck_context {
+                let bounds_mapping = closure_constraints
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(idx, constraint)| {
+                        let ty::OutlivesPredicate(k1, r2) =
+                            constraint.no_late_bound_regions().unwrap_or_else(|| {
+                                bug!(
+                                    "query_constraint {:?} contained bound regions",
+                                    constraint,
+                                );
+                            });
+
+                        match k1.unpack() {
+                            UnpackedKind::Lifetime(r1) => {
+                                // constraint is r1: r2
+                                let r1_vid = borrowck_context.universal_regions.to_region_vid(r1);
+                                let r2_vid = borrowck_context.universal_regions.to_region_vid(r2);
+                                let outlives_requirements = &closure_region_requirements
+                                    .outlives_requirements[idx];
+                                Some((
+                                    (r1_vid, r2_vid),
+                                    (
+                                        outlives_requirements.category,
+                                        outlives_requirements.blame_span,
+                                    ),
+                                ))
+                            }
+                            UnpackedKind::Type(_) => None,
+                        }
+                    })
+                    .collect();
+
+                let existing = borrowck_context.constraints
+                    .closure_bounds_mapping
+                    .insert(location, bounds_mapping);
+                assert!(existing.is_none(), "Multiple closures at the same location.");
+            }
+
+            self.push_region_constraints(
+                location.to_locations(),
+                ConstraintCategory::ClosureBounds,
+                &closure_constraints,
+            );
+        }
+
+        tcx.predicates_of(def_id).instantiate(tcx, substs.substs)
+    }
+
     fn prove_trait_ref(
         &mut self,
         trait_ref: ty::TraitRef<'tcx>,
index 4e8dbf8498e2a643b421333590d132e72f04ff37..41aab02d1e8266f3b9c8a478663995a38e6fc933 100644 (file)
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::constraints::{ConstraintCategory, OutlivesConstraint};
+use borrow_check::nll::constraints::OutlivesConstraint;
 use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
 use rustc::infer::canonical::{Canonical, CanonicalVarInfos};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
+use rustc::mir::ConstraintCategory;
 use rustc::traits::query::Fallible;
 use rustc::ty::fold::{TypeFoldable, TypeVisitor};
 use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
index 656c78a46ed78c84d75ce5366cdc21c004fec938..c2a7172d54cca22cf2a105366bf4d27a510d2c67 100644 (file)
@@ -1307,6 +1307,14 @@ fn ascribe_types<'pat>(
     ) {
         for ascription in ascriptions {
             let source_info = self.source_info(ascription.span);
+
+            debug!(
+                "adding user ascription at span {:?} of place {:?} and {:?}",
+                source_info.span,
+                ascription.source,
+                ascription.user_ty,
+            );
+
             self.cfg.push(
                 block,
                 Statement {
index 3b1eba51aaf45fbb34ebd4e67ccf7d223245cc9f..fd18d9feeea91e12b123b30dd2ad23fef05843f2 100644 (file)
@@ -12,6 +12,9 @@
 
 use std::fmt;
 use std::error::Error;
+use std::borrow::{Borrow, Cow};
+use std::hash::Hash;
+use std::collections::hash_map::Entry;
 
 use rustc::hir::{self, def_id::DefId};
 use rustc::mir::interpret::ConstEvalErr;
 use rustc::ty::layout::{self, LayoutOf, TyLayout};
 use rustc::ty::subst::Subst;
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::fx::FxHashMap;
 
 use syntax::ast::Mutability;
 use syntax::source_map::{Span, DUMMY_SP};
 
 use rustc::mir::interpret::{
     EvalResult, EvalError, EvalErrorKind, GlobalId,
-    Scalar, Allocation, ConstValue,
+    Scalar, Allocation, AllocId, ConstValue,
 };
 use interpret::{self,
     Place, PlaceTy, MemPlace, OpTy, Operand, Value,
@@ -118,9 +122,9 @@ pub fn op_to_const<'tcx>(
         }
     };
     let val = match normalized_op {
-        Err(MemPlace { ptr, align, extra }) => {
+        Err(MemPlace { ptr, align, meta }) => {
             // extract alloc-offset pair
-            assert!(extra.is_none());
+            assert!(meta.is_none());
             let ptr = ptr.to_ptr()?;
             let alloc = ecx.memory.get(ptr.alloc_id)?;
             assert!(alloc.align.abi() >= align.abi());
@@ -264,6 +268,67 @@ fn new() -> Self {
     }
 }
 
+impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
+    #[inline(always)]
+    fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
+        where K: Borrow<Q>
+    {
+        FxHashMap::contains_key(self, k)
+    }
+
+    #[inline(always)]
+    fn insert(&mut self, k: K, v: V) -> Option<V>
+    {
+        FxHashMap::insert(self, k, v)
+    }
+
+    #[inline(always)]
+    fn remove<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> Option<V>
+        where K: Borrow<Q>
+    {
+        FxHashMap::remove(self, k)
+    }
+
+    #[inline(always)]
+    fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> {
+        self.iter()
+            .filter_map(move |(k, v)| f(k, &*v))
+            .collect()
+    }
+
+    #[inline(always)]
+    fn get_or<E>(
+        &self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&V, E>
+    {
+        match self.get(&k) {
+            Some(v) => Ok(v),
+            None => {
+                vacant()?;
+                bug!("The CTFE machine shouldn't ever need to extend the alloc_map when reading")
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn get_mut_or<E>(
+        &mut self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&mut V, E>
+    {
+        match self.entry(k) {
+            Entry::Occupied(e) => Ok(e.into_mut()),
+            Entry::Vacant(e) => {
+                let v = vacant()?;
+                Ok(e.insert(v))
+            }
+        }
+    }
+}
+
 type CompileTimeEvalContext<'a, 'mir, 'tcx> =
     EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
 
@@ -272,8 +337,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
 {
     type MemoryData = ();
     type MemoryKinds = !;
+    type PointerTag = ();
+
+    type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation<()>)>;
 
-    const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
+    const STATIC_KIND: Option<!> = None; // no copying of statics allowed
+    const ENFORCE_VALIDITY: bool = false; // for now, we don't
 
     fn find_fn(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
@@ -338,10 +407,18 @@ fn ptr_op(
     fn find_foreign_static(
         _tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         _def_id: DefId,
-    ) -> EvalResult<'tcx, &'tcx Allocation> {
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
         err!(ReadForeignStatic)
     }
 
+    #[inline(always)]
+    fn static_with_default_tag(
+        alloc: &'_ Allocation
+    ) -> Cow<'_, Allocation<Self::PointerTag>> {
+        // We do not use a tag so we can just cheaply forward the reference
+        Cow::Borrowed(alloc)
+    }
+
     fn box_alloc(
         _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         _dest: PlaceTy<'tcx>,
index 1fbeb66be304fd56cf742839ff17393f82e34eff..6896c91352fdd04340a7430297750ad405a05a43 100644 (file)
@@ -14,7 +14,6 @@
 use rustc::mir::{BasicBlock, Mir};
 
 use dot;
-use dot::IntoCow;
 
 use std::fs;
 use std::io;
@@ -257,7 +256,7 @@ fn nodes(&self) -> dot::Nodes<Node> {
             .basic_blocks()
             .indices()
             .collect::<Vec<_>>()
-            .into_cow()
+            .into()
     }
 
     fn edges(&self) -> dot::Edges<Edge> {
@@ -267,7 +266,7 @@ fn edges(&self) -> dot::Edges<Edge> {
            .indices()
            .flat_map(|bb| outgoing(mir, bb))
            .collect::<Vec<_>>()
-           .into_cow()
+           .into()
     }
 
     fn source(&self, edge: &Edge) -> Node {
index 75745849290eb7cc40aaa768bb43e20d5b551b94..56031054b918387e762f3a2ec3b83534ce110537 100644 (file)
@@ -665,24 +665,6 @@ fn main() {
 ```
 "##,
 
-E0022: r##"
-Constant functions are not allowed to mutate anything. Thus, binding to an
-argument with a mutable pattern is not allowed. For example,
-
-```compile_fail
-const fn foo(mut x: u8) {
-    // do stuff
-}
-```
-
-Is incorrect because the function body may not mutate `x`.
-
-Remove any mutable bindings from the argument list to fix this error. In case
-you need to mutate the argument, try lazily initializing a global variable
-instead of using a `const fn`, or refactoring the code to a functional style to
-avoid mutation if possible.
-"##,
-
 E0133: r##"
 Unsafe code was used outside of an unsafe function or block.
 
index 8d50fbbdc6b35dd3d23ebd1591d61193986a0344..c969a3ef3485ff1fabe2c221add74a8473b596ca 100644 (file)
@@ -13,6 +13,7 @@
 use hair::cx::Cx;
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
+use hair::util::UserAnnotatedTyHelpers;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::mir::interpret::GlobalId;
 use rustc::ty::{self, AdtKind, Ty};
@@ -475,7 +476,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 adt_def: adt,
                                 variant_index: 0,
                                 substs,
-                                user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
+                                user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
                                 fields: field_refs(cx, fields),
                                 base: base.as_ref().map(|base| {
                                     FruInfo {
@@ -501,7 +502,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                         adt_def: adt,
                                         variant_index: index,
                                         substs,
-                                        user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
+                                        user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
                                         fields: field_refs(cx, fields),
                                         base: None,
                                     }
@@ -787,48 +788,17 @@ fn user_annotated_ty_for_def(
         // user.
         Def::StructCtor(_def_id, CtorKind::Const) |
         Def::VariantCtor(_def_id, CtorKind::Const) =>
-            match &cx.tables().node_id_to_type(hir_id).sty {
-                ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
-                sty => bug!("unexpected sty: {:?}", sty),
-            },
+            cx.user_substs_applied_to_ty_of_hir_id(hir_id),
 
         // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
-        Def::SelfCtor(_) => {
-            let sty = &cx.tables().node_id_to_type(hir_id).sty;
-            match sty {
-                ty::FnDef(ref def_id, _) => {
-                    Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
-                        // Here, we just pair a `DefId` with the
-                        // `user_substs`, so no new types etc are introduced.
-                        cx.tcx().mk_fn_def(*def_id, user_substs)
-                    }))
-                }
-                ty::Adt(ref adt_def, _) => {
-                    user_annotated_ty_for_adt(cx, hir_id, adt_def)
-                }
-                _ => {
-                    bug!("unexpected sty: {:?}", sty)
-                }
-            }
-        }
+        Def::SelfCtor(_) =>
+            cx.user_substs_applied_to_ty_of_hir_id(hir_id),
+
         _ =>
             bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
     }
 }
 
-fn user_annotated_ty_for_adt(
-    cx: &mut Cx<'a, 'gcx, 'tcx>,
-    hir_id: hir::HirId,
-    adt_def: &'tcx AdtDef,
-) -> Option<CanonicalTy<'tcx>> {
-    let user_substs = cx.tables().user_substs(hir_id)?;
-    Some(user_substs.unchecked_map(|user_substs| {
-        // Here, we just pair an `AdtDef` with the
-        // `user_substs`, so no new types etc are introduced.
-        cx.tcx().mk_adt(adt_def, user_substs)
-    }))
-}
-
 fn method_callee<'a, 'gcx, 'tcx>(
     cx: &mut Cx<'a, 'gcx, 'tcx>,
     expr: &hir::Expr,
@@ -943,7 +913,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         adt_def,
                         variant_index: adt_def.variant_index_with_id(def_id),
                         substs,
-                        user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
+                        user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def),
                         fields: vec![],
                         base: None,
                     }
index 4d4a89fca8b83b77023d08daad411e14c32ff178..5f798135966d49c25068313a533e628e215dc51f 100644 (file)
@@ -15,6 +15,7 @@
 //!
 
 use hair::*;
+use hair::util::UserAnnotatedTyHelpers;
 
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
@@ -272,6 +273,16 @@ pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
     }
 }
 
+impl UserAnnotatedTyHelpers<'gcx, 'tcx> for Cx<'_, 'gcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
+        self.tcx()
+    }
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx> {
+        self.tables()
+    }
+}
+
 fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
     // Right now we insert a `with_ignore` node in the dep graph here to
     // ignore the fact that `lint_levels` below depends on the entire crate.
index eb73a2021484b0f7a5ad60b20b38ff130b50dd05..e4f88e4fcc3ba2e6238314ee14aa63d813707ca8 100644 (file)
@@ -29,6 +29,8 @@
 pub mod pattern;
 pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
 
+mod util;
+
 #[derive(Copy, Clone, Debug)]
 pub enum LintLevel {
     Inherited,
index b22cc4a1a42b50d14c1d139f99a9044c334b13b9..04090e5087ffc47c21a579d03e231bc195909447 100644 (file)
@@ -18,6 +18,8 @@
 
 use const_eval::{const_field, const_variant_index};
 
+use hair::util::UserAnnotatedTyHelpers;
+
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
@@ -529,8 +531,9 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                        field: Field::new(i),
                                        pattern: self.lower_pattern(field),
                                    })
-                                   .collect();
-                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+                    .collect();
+
+                self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
             }
 
             PatKind::Struct(ref qpath, ref fields, _) => {
@@ -546,7 +549,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                           })
                           .collect();
 
-                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+                self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
             }
         };
 
@@ -637,12 +640,12 @@ fn slice_or_array_pattern(
     fn lower_variant_or_leaf(
         &mut self,
         def: Def,
+        hir_id: hir::HirId,
         span: Span,
         ty: Ty<'tcx>,
-        subpatterns: Vec<FieldPattern<'tcx>>)
-        -> PatternKind<'tcx>
-    {
-        match def {
+        subpatterns: Vec<FieldPattern<'tcx>>,
+    ) -> PatternKind<'tcx> {
+        let mut kind = match def {
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
                 let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
@@ -675,7 +678,24 @@ fn lower_variant_or_leaf(
                 self.errors.push(PatternError::NonConstPath(span));
                 PatternKind::Wild
             }
+        };
+
+        if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
+            let subpattern = Pattern {
+                span,
+                ty,
+                kind: Box::new(kind),
+            };
+
+            debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);
+
+            kind = PatternKind::AscribeUserType {
+                subpattern,
+                user_ty,
+            };
         }
+
+        kind
     }
 
     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
@@ -729,7 +749,7 @@ fn lower_path(&mut self,
                     },
                 }
             }
-            _ => self.lower_variant_or_leaf(def, span, ty, vec![]),
+            _ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
         };
 
         Pattern {
@@ -894,6 +914,17 @@ fn const_to_pat(
     }
 }
 
+impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
+        self.tcx
+    }
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx> {
+        self.tables
+    }
+}
+
+
 pub trait PatternFoldable<'tcx> : Sized {
     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.super_fold_with(folder)
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs
new file mode 100644 (file)
index 0000000..48a2e67
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir;
+use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt};
+
+crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx>;
+
+    fn user_substs_applied_to_adt(
+        &self,
+        hir_id: hir::HirId,
+        adt_def: &'tcx AdtDef,
+    ) -> Option<CanonicalTy<'tcx>> {
+        let user_substs = self.tables().user_substs(hir_id)?;
+        Some(user_substs.unchecked_map(|user_substs| {
+            // Here, we just pair an `AdtDef` with the
+            // `user_substs`, so no new types etc are introduced.
+            self.tcx().mk_adt(adt_def, user_substs)
+        }))
+    }
+
+    /// Looks up the type associated with this hir-id and applies the
+    /// user-given substitutions; the hir-id must map to a suitable
+    /// type.
+    fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> {
+        let user_substs = self.tables().user_substs(hir_id)?;
+        match &self.tables().node_id_to_type(hir_id).sty {
+            ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| {
+                // Ok to call `unchecked_map` because we just pair an
+                // `AdtDef` with the `user_substs`, so no new types
+                // etc are introduced.
+                self.tcx().mk_adt(adt_def, user_substs)
+            })),
+            ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| {
+                // Here, we just pair a `DefId` with the
+                // `user_substs`, so no new types etc are introduced.
+                self.tcx().mk_fn_def(*def_id, user_substs)
+            })),
+            sty => bug!(
+                "sty: {:?} should not have user-substs {:?} recorded ",
+                sty,
+                user_substs
+            ),
+        }
+    }
+}
index c6b527f42294c1134535272da53f0774ca17338b..bfc7e6801fc463fe39fd778fef7e4bdeede63d63 100644 (file)
@@ -33,9 +33,9 @@ fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
 
     pub fn cast(
         &mut self,
-        src: OpTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
         kind: CastKind,
-        dest: PlaceTy<'tcx>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let src_layout = src.layout;
         let dst_layout = dest.layout;
@@ -143,10 +143,10 @@ pub fn cast(
 
     pub(super) fn cast_scalar(
         &self,
-        val: Scalar,
+        val: Scalar<M::PointerTag>,
         src_layout: TyLayout<'tcx>,
         dest_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
         trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
 
@@ -182,7 +182,7 @@ fn cast_from_int(
         v: u128,
         src_layout: TyLayout<'tcx>,
         dest_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         let signed = src_layout.abi.is_signed();
         let v = if signed {
             self.sign_extend(v, src_layout)
@@ -239,7 +239,7 @@ fn cast_from_float(
         bits: u128,
         fty: FloatTy,
         dest_ty: Ty<'tcx>
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
         use rustc_apfloat::FloatConvert;
         match dest_ty.sty {
@@ -283,7 +283,11 @@ fn cast_from_float(
         }
     }
 
-    fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
+    fn cast_from_ptr(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        ty: Ty<'tcx>
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
         match ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc,
@@ -298,8 +302,8 @@ fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar>
 
     fn unsize_into_ptr(
         &mut self,
-        src: OpTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
         // The pointee types
         sty: Ty<'tcx>,
         dty: Ty<'tcx>,
@@ -339,8 +343,8 @@ fn unsize_into_ptr(
 
     fn unsize_into(
         &mut self,
-        src: OpTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         match (&src.layout.ty.sty, &dest.layout.ty.sty) {
             (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) |
index ff059e7d1853b0c8592d3af9bd8edf2d9700b198..f6944b2a9ae8555b73b0cbf6573697663137f044 100644 (file)
@@ -49,12 +49,12 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
     pub memory: Memory<'a, 'mir, 'tcx, M>,
 
     /// The virtual call stack.
-    pub(crate) stack: Vec<Frame<'mir, 'tcx>>,
+    pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag>>,
 }
 
 /// A stack frame.
 #[derive(Clone)]
-pub struct Frame<'mir, 'tcx: 'mir> {
+pub struct Frame<'mir, 'tcx: 'mir, Tag=()> {
     ////////////////////////////////////////////////////////////////////////////////
     // Function and callsite information
     ////////////////////////////////////////////////////////////////////////////////
@@ -74,14 +74,14 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     pub return_to_block: StackPopCleanup,
 
     /// The location where the result of the current stack frame should be written to.
-    pub return_place: Place,
+    pub return_place: Place<Tag>,
 
     /// The list of locals for this stack frame, stored in order as
     /// `[return_ptr, arguments..., variables..., temporaries...]`.
     /// 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<AllocId>>,
+    pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -108,24 +108,24 @@ pub enum StackPopCleanup {
 
 // State of a local variable
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalValue<Id=AllocId> {
+pub enum LocalValue<Tag=(), 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<Id>),
+    Live(Operand<Tag, Id>),
 }
 
-impl<'tcx> LocalValue {
-    pub fn access(&self) -> EvalResult<'tcx, &Operand> {
+impl<'tcx, Tag> LocalValue<Tag> {
+    pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
         match self {
             LocalValue::Dead => err!(DeadLocal),
             LocalValue::Live(ref val) => Ok(val),
         }
     }
 
-    pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand> {
+    pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
         match self {
             LocalValue::Dead => err!(DeadLocal),
             LocalValue::Live(ref mut val) => Ok(val),
@@ -218,7 +218,7 @@ pub fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
         &mut self.memory
     }
 
-    pub fn stack(&self) -> &[Frame<'mir, 'tcx>] {
+    pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag>] {
         &self.stack
     }
 
@@ -230,7 +230,11 @@ pub fn cur_frame(&self) -> usize {
 
     /// Mark a storage as live, killing the previous content and returning it.
     /// Remember to deallocate that!
-    pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue> {
+    pub fn storage_live(
+        &mut self,
+        local: mir::Local
+    ) -> EvalResult<'tcx, LocalValue<M::PointerTag>> {
+        assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
         let layout = self.layout_of_local(self.cur_frame(), local)?;
@@ -241,13 +245,14 @@ pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue
 
     /// Returns the old value of the local.
     /// Remember to deallocate that!
-    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue {
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
+        assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
 
         mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
     }
 
-    pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
+    pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value<M::PointerTag>> {
         let ptr = self.memory.allocate_static_bytes(s.as_bytes());
         Ok(Value::new_slice(Scalar::Ptr(ptr), s.len() as u64, self.tcx.tcx))
     }
@@ -325,10 +330,10 @@ pub fn layout_of_local(
     }
 
     /// Return the actual dynamic size and alignment of the place at the given type.
-    /// Only the "extra" (metadata) part of the place matters.
+    /// Only the `meta` part of the place matters.
     pub(super) fn size_and_align_of(
         &self,
-        metadata: Option<Scalar>,
+        metadata: Option<Scalar<M::PointerTag>>,
         layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, (Size, Align)> {
         let metadata = match metadata {
@@ -409,9 +414,9 @@ pub(super) fn size_and_align_of(
     #[inline]
     pub fn size_and_align_of_mplace(
         &self,
-        mplace: MPlaceTy<'tcx>
+        mplace: MPlaceTy<'tcx, M::PointerTag>
     ) -> EvalResult<'tcx, (Size, Align)> {
-        self.size_and_align_of(mplace.extra, mplace.layout)
+        self.size_and_align_of(mplace.meta, mplace.layout)
     }
 
     pub fn push_stack_frame(
@@ -419,7 +424,7 @@ pub fn push_stack_frame(
         instance: ty::Instance<'tcx>,
         span: source_map::Span,
         mir: &'mir mir::Mir<'tcx>,
-        return_place: Place,
+        return_place: Place<M::PointerTag>,
         return_to_block: StackPopCleanup,
     ) -> EvalResult<'tcx> {
         ::log_settings::settings().indentation += 1;
@@ -446,6 +451,9 @@ pub fn push_stack_frame(
             let dummy =
                 LocalValue::Live(Operand::Immediate(Value::Scalar(ScalarMaybeUndef::Undef)));
             let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
+            // Return place is handled specially by the `eval_place` functions, and the
+            // entry in `locals` should never be used. Make it dead, to be sure.
+            locals[mir::RETURN_PLACE] = LocalValue::Dead;
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
@@ -514,7 +522,10 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    pub(super) fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> {
+    pub(super) fn deallocate_local(
+        &mut self,
+        local: LocalValue<M::PointerTag>,
+    ) -> EvalResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
         if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             trace!("deallocating local");
@@ -536,12 +547,12 @@ pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Cons
     }
 
     #[inline(always)]
-    pub fn frame(&self) -> &Frame<'mir, 'tcx> {
+    pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag> {
         self.stack.last().expect("no call frames exist")
     }
 
     #[inline(always)]
-    pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> {
+    pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag> {
         self.stack.last_mut().expect("no call frames exist")
     }
 
@@ -557,7 +568,7 @@ pub fn substs(&self) -> &'tcx Substs<'tcx> {
         }
     }
 
-    pub fn dump_place(&self, place: Place) {
+    pub fn dump_place(&self, place: Place<M::PointerTag>) {
         // Debug output
         if !log_enabled!(::log::Level::Trace) {
             return;
index 5fee49ba2fcf2ddb5bca8745a35b1bfc72510055..a669b2aafc2b8868a0a743e8372208bd270c4cbb 100644 (file)
 };
 
 
-fn numeric_intrinsic<'tcx>(
+fn numeric_intrinsic<'tcx, Tag>(
     name: &str,
     bits: u128,
     kind: Primitive,
-) -> EvalResult<'tcx, Scalar> {
+) -> EvalResult<'tcx, Scalar<Tag>> {
     let size = match kind {
         Primitive::Int(integer, _) => integer.size(),
         _ => bug!("invalid `{}` argument: {:?}", name, bits),
@@ -51,8 +51,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     pub fn emulate_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: PlaceTy<'tcx>,
+        args: &[OpTy<'tcx, M::PointerTag>],
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, bool> {
         let substs = instance.substs;
 
@@ -169,8 +169,8 @@ pub fn emulate_intrinsic(
     pub fn hook_fn(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: Option<PlaceTy<'tcx>>,
+        args: &[OpTy<'tcx, M::PointerTag>],
+        dest: Option<PlaceTy<'tcx, M::PointerTag>>,
     ) -> EvalResult<'tcx, bool> {
         let def_id = instance.def_id();
         // Some fn calls are actually BinOp intrinsics
index 1eb0280409527cec262f2bcf527bfde73c5d829a..a444f0bafd23c1f3d7d7b24de03ead89bb79923f 100644 (file)
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
+use std::borrow::{Borrow, Cow};
+use std::hash::Hash;
+
 use rustc::hir::def_id::DefId;
-use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
+use rustc::mir::interpret::{Allocation, AllocId, EvalResult, Scalar};
 use rustc::mir;
 use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
 
-use super::{EvalContext, PlaceTy, OpTy};
+use super::{EvalContext, PlaceTy, OpTy, MemoryKind};
+
+/// The functionality needed by memory to manage its allocations
+pub trait AllocMap<K: Hash + Eq, V> {
+    /// Test if the map contains the given key.
+    /// Deliberately takes `&mut` because that is sufficient, and some implementations
+    /// can be more efficient then (using `RefCell::get_mut`).
+    fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
+        where K: Borrow<Q>;
+
+    /// Insert new entry into the map.
+    fn insert(&mut self, k: K, v: V) -> Option<V>;
+
+    /// Remove entry from the map.
+    fn remove<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> Option<V>
+        where K: Borrow<Q>;
+
+    /// Return data based the keys and values in the map.
+    fn filter_map_collect<T>(&self, f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T>;
+
+    /// Return a reference to entry `k`.  If no such entry exists, call
+    /// `vacant` and either forward its error, or add its result to the map
+    /// and return a reference to *that*.
+    fn get_or<E>(
+        &self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&V, E>;
+
+    /// Return a mutable reference to entry `k`.  If no such entry exists, call
+    /// `vacant` and either forward its error, or add its result to the map
+    /// and return a reference to *that*.
+    fn get_mut_or<E>(
+        &mut self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&mut V, E>;
+}
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
 /// and some use case dependent behaviour can instead be applied.
-/// FIXME: We should be able to get rid of the 'a here if we can get rid of the 'a in
-/// `snapshot::EvalSnapshot`.
 pub trait Machine<'a, 'mir, 'tcx>: Sized {
     /// Additional data that can be accessed via the Memory
     type MemoryData;
@@ -30,8 +68,25 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     type MemoryKinds: ::std::fmt::Debug + Copy + Eq;
 
-    /// The memory kind to use for mutated statics -- or None if those are not supported.
-    const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
+    /// Memory's allocation map
+    type MemoryMap:
+        AllocMap<AllocId, (MemoryKind<Self::MemoryKinds>, Allocation<Self::PointerTag>)> +
+        Default +
+        Clone;
+
+    /// Tag tracked alongside every pointer.  This is inert for now, in preparation for
+    /// a future implementation of "Stacked Borrows"
+    /// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
+    type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
+
+    /// The memory kind to use for copied statics -- or None if those are not supported.
+    /// Statics are copied under two circumstances: When they are mutated, and when
+    /// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation
+    /// that is added to the memory so that the work is not done twice.
+    const STATIC_KIND: Option<Self::MemoryKinds>;
+
+    /// Whether to enforce the validity invariant
+    const ENFORCE_VALIDITY: bool;
 
     /// Called before a basic block terminator is executed.
     /// You can use this to detect endlessly running programs.
@@ -50,8 +105,8 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     fn find_fn(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: Option<PlaceTy<'tcx>>,
+        args: &[OpTy<'tcx, Self::PointerTag>],
+        dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
         ret: Option<mir::BasicBlock>,
     ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>;
 
@@ -60,18 +115,30 @@ fn find_fn(
     fn call_intrinsic(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: PlaceTy<'tcx>,
+        args: &[OpTy<'tcx, Self::PointerTag>],
+        dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx>;
 
     /// Called for read access to a foreign static item.
-    /// This can be called multiple times for the same static item and should return consistent
-    /// results.  Once the item is *written* the first time, as usual for statics a copy is
-    /// made and this function is not called again.
+    ///
+    /// This will only be called once per static and machine; the result is cached in
+    /// the machine memory. (This relies on `AllocMap::get_or` being able to add the
+    /// owned allocation to the map even when the map is shared.)
     fn find_foreign_static(
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         def_id: DefId,
-    ) -> EvalResult<'tcx, &'tcx Allocation>;
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>>;
+
+    /// Called to turn an allocation obtained from the `tcx` into one that has
+    /// the appropriate tags on each pointer.
+    ///
+    /// This should avoid copying if no work has to be done! If this returns an owned
+    /// allocation (because a copy had to be done to add the tags), machine memory will
+    /// cache the result. (This relies on `AllocMap::get_or` being able to add the
+    /// owned allocation to the map even when the map is shared.)
+    fn static_with_default_tag(
+        alloc: &'_ Allocation
+    ) -> Cow<'_, Allocation<Self::PointerTag>>;
 
     /// 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.
@@ -80,18 +147,18 @@ fn find_foreign_static(
     fn ptr_op(
         ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
-        left: Scalar,
+        left: Scalar<Self::PointerTag>,
         left_layout: TyLayout<'tcx>,
-        right: Scalar,
+        right: Scalar<Self::PointerTag>,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)>;
+    ) -> EvalResult<'tcx, (Scalar<Self::PointerTag>, bool)>;
 
     /// Heap allocations via the `box` keyword
     ///
     /// Returns a pointer to the allocated memory
     fn box_alloc(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        dest: PlaceTy<'tcx>,
+        dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx>;
 
     /// Execute a validation operation
index 222d1164667d360177ac0a612d4fb8eaeea85a33..7d3ae19e1a30c69cf519d60f633a86c17c779616 100644 (file)
 
 use std::collections::VecDeque;
 use std::ptr;
+use std::borrow::Cow;
 
-use rustc::ty::{self, Instance, query::TyCtxtAt};
+use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
-use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, GlobalId,
-                            EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
-                            truncate};
+use rustc::mir::interpret::{
+    Pointer, AllocId, Allocation, ConstValue, 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};
 
 use syntax::ast::Mutability;
 
-use super::{Machine, ScalarMaybeUndef};
+use super::{Machine, AllocMap, ScalarMaybeUndef};
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
 pub enum MemoryKind<T> {
     /// Error if deallocated except during a stack pop
     Stack,
+    /// Error if ever deallocated
+    Vtable,
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     Machine(T),
 }
@@ -48,9 +53,13 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
     /// Allocations local to this instance of the miri engine.  The kind
     /// helps ensure that the same mechanism is used for allocation and
     /// deallocation.  When an allocation is not found here, it is a
-    /// static and looked up in the `tcx` for read access.  Writing to
-    /// a static creates a copy here, in the machine.
-    alloc_map: FxHashMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
+    /// static and looked up in the `tcx` for read access.  Some machines may
+    /// have to mutate this map even on a read-only access to a static (because
+    /// they do pointer provenance tracking and the allocations in `tcx` have
+    /// the wrong type), so we let the machine override this type.
+    /// Either way, if the machine allows writing to a static, doing so will
+    /// create a copy of the static allocation here.
+    alloc_map: M::MemoryMap,
 
     /// To be able to compare pointers with NULL, and to check alignment for accesses
     /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
@@ -98,23 +107,23 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
         Memory {
             data,
-            alloc_map: FxHashMap::default(),
+            alloc_map: Default::default(),
             dead_alloc_map: FxHashMap::default(),
             tcx,
         }
     }
 
-    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer {
-        self.tcx.alloc_map.lock().create_fn_alloc(instance).into()
+    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer<M::PointerTag> {
+        Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance)).with_default_tag()
     }
 
-    pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer {
-        self.tcx.allocate_bytes(bytes).into()
+    pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer<M::PointerTag> {
+        Pointer::from(self.tcx.allocate_bytes(bytes)).with_default_tag()
     }
 
     pub fn allocate_with(
         &mut self,
-        alloc: Allocation,
+        alloc: Allocation<M::PointerTag>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx, AllocId> {
         let id = self.tcx.alloc_map.lock().reserve();
@@ -127,19 +136,20 @@ pub fn allocate(
         size: Size,
         align: Align,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx, Pointer> {
-        self.allocate_with(Allocation::undef(size, align), kind).map(Pointer::from)
+    ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
+        let ptr = Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?);
+        Ok(ptr.with_default_tag())
     }
 
     pub fn reallocate(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         old_size: Size,
         old_align: Align,
         new_size: Size,
         new_align: Align,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx, Pointer> {
+    ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
         if ptr.offset.bytes() != 0 {
             return err!(ReallocateNonBasePtr);
         }
@@ -160,7 +170,7 @@ pub fn reallocate(
     }
 
     /// Deallocate a local, or do nothing if that local has been made into a static
-    pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> {
+    pub fn deallocate_local(&mut self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx> {
         // The allocation might be already removed by static interning.
         // This can only really happen in the CTFE instance, not in miri.
         if self.alloc_map.contains_key(&ptr.alloc_id) {
@@ -172,7 +182,7 @@ pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> {
 
     pub fn deallocate(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx> {
@@ -231,16 +241,20 @@ pub fn deallocate(
 
     /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
     /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
-    pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> {
+    pub fn check_align(
+        &self,
+        ptr: Scalar<M::PointerTag>,
+        required_align: Align
+    ) -> EvalResult<'tcx> {
         // Check non-NULL/Undef, extract offset
         let (offset, alloc_align) = match ptr {
             Scalar::Ptr(ptr) => {
-                let (size, align) = self.get_size_and_align(ptr.alloc_id)?;
+                let (size, align) = self.get_size_and_align(ptr.alloc_id);
                 // check this is not NULL -- which we can ensure only if this is in-bounds
                 // of some (potentially dead) allocation.
                 if ptr.offset > size {
                     return err!(PointerOutOfBounds {
-                        ptr,
+                        ptr: ptr.erase_tag(),
                         access: true,
                         allocation_size: size,
                     });
@@ -284,31 +298,49 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
     /// 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> {
+    pub fn check_bounds_ptr(&self, ptr: Pointer<M::PointerTag>, access: bool) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         let allocation_size = alloc.bytes.len() as u64;
         if ptr.offset.bytes() > allocation_size {
             return err!(PointerOutOfBounds {
-                ptr,
+                ptr: ptr.erase_tag(),
                 access,
                 allocation_size: Size::from_bytes(allocation_size),
             });
         }
         Ok(())
     }
+
+    /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
+    #[inline(always)]
+    pub fn check_bounds(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        size: Size,
+        access: bool
+    ) -> EvalResult<'tcx> {
+        // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
+        self.check_bounds_ptr(ptr.offset(size, &*self)?, access)
+    }
 }
 
 /// Allocation accessors
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    /// Helper function to obtain the global (tcx) allocation for a static
+    /// Helper function to obtain the global (tcx) allocation for a static.
+    /// This attempts to return a reference to an existing allocation if
+    /// one can be found in `tcx`. That, however, is only possible if `tcx` and
+    /// this machine use the same pointer tag, so it is indirected through
+    /// `M::static_with_default_tag`.
     fn get_static_alloc(
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         id: AllocId,
-    ) -> EvalResult<'tcx, &'tcx Allocation> {
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<M::PointerTag>>> {
         let alloc = tcx.alloc_map.lock().get(id);
         let def_id = match alloc {
             Some(AllocType::Memory(mem)) => {
-                return Ok(mem)
+                // We got tcx memory. Let the machine figure out whether and how to
+                // turn that into memory with the right pointer tag.
+                return Ok(M::static_with_default_tag(mem))
             }
             Some(AllocType::Function(..)) => {
                 return err!(DerefFunctionPointer)
@@ -335,63 +367,101 @@ fn get_static_alloc(
             EvalErrorKind::ReferencedConstant(err).into()
         }).map(|const_val| {
             if let ConstValue::ByRef(_, allocation, _) = const_val.val {
-                allocation
+                // We got tcx memory. Let the machine figure out whether and how to
+                // turn that into memory with the right pointer tag.
+                M::static_with_default_tag(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 => Self::get_static_alloc(self.tcx, id),
-        }
-    }
-
-    pub fn get_size_and_align(&self, id: AllocId) -> EvalResult<'tcx, (Size, Align)> {
-        Ok(match self.get(id) {
-            Ok(alloc) => (Size::from_bytes(alloc.bytes.len() as u64), alloc.align),
-            Err(err) => match err.kind {
-                EvalErrorKind::DanglingPointerDeref =>
-                    // This should be in the dead allocation map
-                    *self.dead_alloc_map.get(&id).expect(
-                        "allocation missing in dead_alloc_map"
-                    ),
-                // E.g. a function ptr allocation
-                _ => return Err(err)
+    pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation<M::PointerTag>> {
+        // The error type of the inner closure here is somewhat funny.  We have two
+        // ways of "erroring": An actual error, or because we got a reference from
+        // `get_static_alloc` that we can actually use directly without inserting anything anywhere.
+        // So the error type is `EvalResult<'tcx, &Allocation<M::PointerTag>>`.
+        let a = self.alloc_map.get_or(id, || {
+            let alloc = Self::get_static_alloc(self.tcx, id).map_err(Err)?;
+            match alloc {
+                Cow::Borrowed(alloc) => {
+                    // We got a ref, cheaply return that as an "error" so that the
+                    // map does not get mutated.
+                    Err(Ok(alloc))
+                }
+                Cow::Owned(alloc) => {
+                    // Need to put it into the map and return a ref to that
+                    let kind = M::STATIC_KIND.expect(
+                        "I got an owned allocation that I have to copy but the machine does \
+                            not expect that to happen"
+                    );
+                    Ok((MemoryKind::Machine(kind), alloc))
+                }
             }
-        })
+        });
+        // Now unpack that funny error type
+        match a {
+            Ok(a) => Ok(&a.1),
+            Err(a) => a
+        }
     }
 
     pub fn get_mut(
         &mut self,
         id: AllocId,
-    ) -> EvalResult<'tcx, &mut Allocation> {
-        // Static?
-        if !self.alloc_map.contains_key(&id) {
-            // Ask the machine for what to do
-            if let Some(kind) = M::MUT_STATIC_KIND {
-                // The machine supports mutating statics.  Make a copy, use that.
-                self.deep_copy_static(id, MemoryKind::Machine(kind))?;
-            } else {
-                return err!(ModifiedConstantMemory)
+    ) -> EvalResult<'tcx, &mut Allocation<M::PointerTag>> {
+        let tcx = self.tcx;
+        let a = self.alloc_map.get_mut_or(id, || {
+            // Need to make a copy, even if `get_static_alloc` is able
+            // to give us a cheap reference.
+            let alloc = Self::get_static_alloc(tcx, id)?;
+            if alloc.mutability == Mutability::Immutable {
+                return err!(ModifiedConstantMemory);
+            }
+            let kind = M::STATIC_KIND.expect(
+                "An allocation is being mutated but the machine does not expect that to happen"
+            );
+            Ok((MemoryKind::Machine(kind), alloc.into_owned()))
+        });
+        // Unpack the error type manually because type inference doesn't
+        // work otherwise (and we cannot help it because `impl Trait`)
+        match a {
+            Err(e) => Err(e),
+            Ok(a) => {
+                let a = &mut a.1;
+                if a.mutability == Mutability::Immutable {
+                    return err!(ModifiedConstantMemory);
+                }
+                Ok(a)
             }
         }
-        // If we come here, we know the allocation is in our map
-        let alloc = &mut self.alloc_map.get_mut(&id).unwrap().1;
-        // See if we are allowed to mutate this
-        if alloc.mutability == Mutability::Immutable {
-            err!(ModifiedConstantMemory)
-        } else {
-            Ok(alloc)
+    }
+
+    pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) {
+        if let Ok(alloc) = self.get(id) {
+            return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align);
+        }
+        // Could also be a fn ptr or extern static
+        match self.tcx.alloc_map.lock().get(id) {
+            Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1, 1).unwrap()),
+            Some(AllocType::Static(did)) => {
+                // The only way `get` couldn't have worked here is if this is an extern static
+                assert!(self.tcx.is_foreign_item(did));
+                // Use size and align of the type
+                let ty = self.tcx.type_of(did);
+                let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
+                (layout.size, layout.align)
+            }
+            _ => {
+                // Must be a deallocated pointer
+                *self.dead_alloc_map.get(&id).expect(
+                    "allocation missing in dead_alloc_map"
+                )
+            }
         }
     }
 
-    pub fn get_fn(&self, ptr: Pointer) -> EvalResult<'tcx, Instance<'tcx>> {
+    pub fn get_fn(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, Instance<'tcx>> {
         if ptr.offset.bytes() != 0 {
             return err!(InvalidFunctionPointer);
         }
@@ -402,108 +472,132 @@ pub fn get_fn(&self, ptr: Pointer) -> EvalResult<'tcx, Instance<'tcx>> {
         }
     }
 
+    pub fn mark_immutable(&mut self, id: AllocId) -> EvalResult<'tcx> {
+        self.get_mut(id)?.mutability = Mutability::Immutable;
+        Ok(())
+    }
+
     /// For debugging, print an allocation and all allocations it points to, recursively.
     pub fn dump_alloc(&self, id: AllocId) {
-        if !log_enabled!(::log::Level::Trace) {
-            return;
-        }
         self.dump_allocs(vec![id]);
     }
 
+    fn dump_alloc_helper<Tag>(
+        &self,
+        allocs_seen: &mut FxHashSet<AllocId>,
+        allocs_to_print: &mut VecDeque<AllocId>,
+        mut msg: String,
+        alloc: &Allocation<Tag>,
+        extra: String,
+    ) {
+        use std::fmt::Write;
+
+        let prefix_len = msg.len();
+        let mut relocations = vec![];
+
+        for i in 0..(alloc.bytes.len() as u64) {
+            let i = Size::from_bytes(i);
+            if let Some(&(_, target_id)) = alloc.relocations.get(&i) {
+                if allocs_seen.insert(target_id) {
+                    allocs_to_print.push_back(target_id);
+                }
+                relocations.push((i, target_id));
+            }
+            if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
+                // this `as usize` is fine, since `i` came from a `usize`
+                write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
+            } else {
+                msg.push_str("__ ");
+            }
+        }
+
+        trace!(
+            "{}({} bytes, alignment {}){}",
+            msg,
+            alloc.bytes.len(),
+            alloc.align.abi(),
+            extra
+        );
+
+        if !relocations.is_empty() {
+            msg.clear();
+            write!(msg, "{:1$}", "", prefix_len).unwrap(); // Print spaces.
+            let mut pos = Size::ZERO;
+            let relocation_width = (self.pointer_size().bytes() - 1) * 3;
+            for (i, target_id) in relocations {
+                // this `as usize` is fine, since we can't print more chars than `usize::MAX`
+                write!(msg, "{:1$}", "", ((i - pos) * 3).bytes() as usize).unwrap();
+                let target = format!("({})", target_id);
+                // this `as usize` is fine, since we can't print more chars than `usize::MAX`
+                write!(msg, "└{0:─^1$}┘ ", target, relocation_width as usize).unwrap();
+                pos = i + self.pointer_size();
+            }
+            trace!("{}", msg);
+        }
+    }
+
     /// For debugging, print a list of allocations and all allocations they point to, recursively.
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
         if !log_enabled!(::log::Level::Trace) {
             return;
         }
-        use std::fmt::Write;
         allocs.sort();
         allocs.dedup();
         let mut allocs_to_print = VecDeque::from(allocs);
         let mut allocs_seen = FxHashSet::default();
 
         while let Some(id) = allocs_to_print.pop_front() {
-            let mut msg = format!("Alloc {:<5} ", format!("{}:", id));
-            let prefix_len = msg.len();
-            let mut relocations = vec![];
-
-            let (alloc, immutable) =
-                // normal alloc?
-                match self.alloc_map.get(&id) {
-                    Some((kind, alloc)) => (alloc, match kind {
+            let msg = format!("Alloc {:<5} ", format!("{}:", id));
+
+            // normal alloc?
+            match self.alloc_map.get_or(id, || Err(())) {
+                Ok((kind, alloc)) => {
+                    let extra = match kind {
                         MemoryKind::Stack => " (stack)".to_owned(),
+                        MemoryKind::Vtable => " (vtable)".to_owned(),
                         MemoryKind::Machine(m) => format!(" ({:?})", m),
-                    }),
-                    None => {
-                        // static alloc?
-                        match self.tcx.alloc_map.lock().get(id) {
-                            Some(AllocType::Memory(a)) => (a, " (immutable)".to_owned()),
-                            Some(AllocType::Function(func)) => {
-                                trace!("{} {}", msg, func);
-                                continue;
-                            }
-                            Some(AllocType::Static(did)) => {
-                                trace!("{} {:?}", msg, did);
-                                continue;
-                            }
-                            None => {
-                                trace!("{} (deallocated)", msg);
-                                continue;
-                            }
+                    };
+                    self.dump_alloc_helper(
+                        &mut allocs_seen, &mut allocs_to_print,
+                        msg, alloc, extra
+                    );
+                },
+                Err(()) => {
+                    // static alloc?
+                    match self.tcx.alloc_map.lock().get(id) {
+                        Some(AllocType::Memory(alloc)) => {
+                            self.dump_alloc_helper(
+                                &mut allocs_seen, &mut allocs_to_print,
+                                msg, alloc, " (immutable)".to_owned()
+                            );
+                        }
+                        Some(AllocType::Function(func)) => {
+                            trace!("{} {}", msg, func);
+                        }
+                        Some(AllocType::Static(did)) => {
+                            trace!("{} {:?}", msg, did);
+                        }
+                        None => {
+                            trace!("{} (deallocated)", msg);
                         }
-                    },
-                };
-
-            for i in 0..(alloc.bytes.len() as u64) {
-                let i = Size::from_bytes(i);
-                if let Some(&target_id) = alloc.relocations.get(&i) {
-                    if allocs_seen.insert(target_id) {
-                        allocs_to_print.push_back(target_id);
                     }
-                    relocations.push((i, target_id));
-                }
-                if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
-                    // this `as usize` is fine, since `i` came from a `usize`
-                    write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
-                } else {
-                    msg.push_str("__ ");
-                }
-            }
+                },
+            };
 
-            trace!(
-                "{}({} bytes, alignment {}){}",
-                msg,
-                alloc.bytes.len(),
-                alloc.align.abi(),
-                immutable
-            );
-
-            if !relocations.is_empty() {
-                msg.clear();
-                write!(msg, "{:1$}", "", prefix_len).unwrap(); // Print spaces.
-                let mut pos = Size::ZERO;
-                let relocation_width = (self.pointer_size().bytes() - 1) * 3;
-                for (i, target_id) in relocations {
-                    // this `as usize` is fine, since we can't print more chars than `usize::MAX`
-                    write!(msg, "{:1$}", "", ((i - pos) * 3).bytes() as usize).unwrap();
-                    let target = format!("({})", target_id);
-                    // this `as usize` is fine, since we can't print more chars than `usize::MAX`
-                    write!(msg, "└{0:─^1$}┘ ", target, relocation_width as usize).unwrap();
-                    pos = i + self.pointer_size();
-                }
-                trace!("{}", msg);
-            }
         }
     }
 
     pub fn leak_report(&self) -> usize {
         trace!("### LEAK REPORT ###");
-        let mut_static_kind = M::MUT_STATIC_KIND.map(|k| MemoryKind::Machine(k));
-        let leaks: Vec<_> = self.alloc_map
-            .iter()
-            .filter_map(|(&id, &(kind, _))|
-                // exclude mutable statics
-                if Some(kind) == mut_static_kind { None } else { Some(id) } )
-            .collect();
+        let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| {
+            // exclude statics and vtables
+            let exclude = match kind {
+                MemoryKind::Stack => false,
+                MemoryKind::Vtable => true,
+                MemoryKind::Machine(k) => Some(k) == M::STATIC_KIND,
+            };
+            if exclude { None } else { Some(id) }
+        });
         let n = leaks.len();
         self.dump_allocs(leaks);
         n
@@ -515,17 +609,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     /// 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,
+    ///
+    /// This function also guarantees that the resulting pointer will remain stable
+    /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies
+    /// on that.
     fn get_bytes_internal(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         align: Align,
         check_defined_and_ptr: bool,
     ) -> EvalResult<'tcx, &[u8]> {
         assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        // 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, size, true)?;
 
         if check_defined_and_ptr {
             self.check_defined(ptr, size)?;
@@ -543,7 +640,12 @@ fn get_bytes_internal(
     }
 
     #[inline]
-    fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
+    fn get_bytes(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        size: Size,
+        align: Align
+    ) -> EvalResult<'tcx, &[u8]> {
         self.get_bytes_internal(ptr, size, align, true)
     }
 
@@ -552,7 +654,7 @@ fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx,
     #[inline]
     fn get_bytes_with_undef_and_ptr(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         align: Align
     ) -> EvalResult<'tcx, &[u8]> {
@@ -563,14 +665,13 @@ fn get_bytes_with_undef_and_ptr(
     /// so be sure to actually put data there!
     fn get_bytes_mut(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &mut [u8]> {
         assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        // 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, size, true)?;
 
         self.mark_definedness(ptr, size, true)?;
         self.clear_relocations(ptr, size)?;
@@ -583,8 +684,12 @@ fn get_bytes_mut(
     }
 }
 
-/// Reading and writing
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
+/// Interning (for CTFE)
+impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M>
+where
+    M: Machine<'a, 'mir, 'tcx, PointerTag=()>,
+    M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<()>)>,
+{
     /// mark an allocation as static and initialized, either mutable or not
     pub fn intern_static(
         &mut self,
@@ -600,14 +705,14 @@ pub fn intern_static(
         let (kind, mut alloc) = self.alloc_map.remove(&alloc_id).unwrap();
         match kind {
             MemoryKind::Machine(_) => bug!("Static cannot refer to machine memory"),
-            MemoryKind::Stack => {},
+            MemoryKind::Stack | MemoryKind::Vtable => {},
         }
         // ensure llvm knows not to put this into immutable memory
         alloc.mutability = mutability;
         let alloc = self.tcx.intern_const_alloc(alloc);
         self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc);
         // recurse into inner allocations
-        for &alloc in alloc.relocations.values() {
+        for &(_, alloc) in alloc.relocations.values() {
             // FIXME: Reusing the mutability here is likely incorrect.  It is originally
             // determined via `is_freeze`, and data is considered frozen if there is no
             // `UnsafeCell` *immediately* in that data -- however, this search stops
@@ -621,28 +726,15 @@ pub fn intern_static(
         }
         Ok(())
     }
+}
 
-    /// The alloc_id must refer to a (mutable) static; a deep copy of that
-    /// static is made into this memory.
-    fn deep_copy_static(
-        &mut self,
-        id: AllocId,
-        kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx> {
-        let alloc = Self::get_static_alloc(self.tcx, id)?;
-        if alloc.mutability == Mutability::Immutable {
-            return err!(ModifiedConstantMemory);
-        }
-        let old = self.alloc_map.insert(id, (kind, alloc.clone()));
-        assert!(old.is_none(), "deep_copy_static: must not overwrite existing memory");
-        Ok(())
-    }
-
+/// Reading and writing
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     pub fn copy(
         &mut self,
-        src: Scalar,
+        src: Scalar<M::PointerTag>,
         src_align: Align,
-        dest: Scalar,
+        dest: Scalar<M::PointerTag>,
         dest_align: Align,
         size: Size,
         nonoverlapping: bool,
@@ -652,9 +744,9 @@ pub fn copy(
 
     pub fn copy_repeatedly(
         &mut self,
-        src: Scalar,
+        src: Scalar<M::PointerTag>,
         src_align: Align,
-        dest: Scalar,
+        dest: Scalar<M::PointerTag>,
         dest_align: Align,
         size: Size,
         length: u64,
@@ -681,9 +773,9 @@ pub fn copy_repeatedly(
                 new_relocations.extend(
                     relocations
                     .iter()
-                    .map(|&(offset, alloc_id)| {
+                    .map(|&(offset, reloc)| {
                     (offset + dest.offset - src.offset + (i * size * relocations.len() as u64),
-                    alloc_id)
+                     reloc)
                     })
                 );
             }
@@ -698,6 +790,8 @@ pub fn copy_repeatedly(
         // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
         // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
         // `dest` could possibly overlap.
+        // The pointers above remain valid even if the `HashMap` table is moved around because they
+        // point into the `Vec` storing the bytes.
         unsafe {
             assert_eq!(size.bytes() as usize as u64, size.bytes());
             if src.alloc_id == dest.alloc_id {
@@ -733,7 +827,7 @@ pub fn copy_repeatedly(
         Ok(())
     }
 
-    pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
+    pub fn read_c_str(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, &[u8]> {
         let alloc = self.get(ptr.alloc_id)?;
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         let offset = ptr.offset.bytes() as usize;
@@ -744,11 +838,11 @@ pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
                 self.check_defined(ptr, p1)?;
                 Ok(&alloc.bytes[offset..offset + size])
             }
-            None => err!(UnterminatedCString(ptr)),
+            None => err!(UnterminatedCString(ptr.erase_tag())),
         }
     }
 
-    pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
+    pub fn read_bytes(&self, ptr: Scalar<M::PointerTag>, size: Size) -> EvalResult<'tcx, &[u8]> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         if size.bytes() == 0 {
@@ -758,7 +852,7 @@ pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
         self.get_bytes(ptr.to_ptr()?, size, align)
     }
 
-    pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
+    pub fn write_bytes(&mut self, ptr: Scalar<M::PointerTag>, src: &[u8]) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         if src.is_empty() {
@@ -770,7 +864,12 @@ pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<'tcx> {
+    pub fn write_repeat(
+        &mut self,
+        ptr: Scalar<M::PointerTag>,
+        val: u8,
+        count: Size
+    ) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         if count.bytes() == 0 {
@@ -787,10 +886,10 @@ pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<
     /// Read a *non-ZST* scalar
     pub fn read_scalar(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         ptr_align: Align,
         size: Size
-    ) -> EvalResult<'tcx, ScalarMaybeUndef> {
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
         // 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))
@@ -811,8 +910,8 @@ pub fn read_scalar(
         } else {
             let alloc = self.get(ptr.alloc_id)?;
             match alloc.relocations.get(&ptr.offset) {
-                Some(&alloc_id) => {
-                    let ptr = Pointer::new(alloc_id, Size::from_bytes(bits as u64));
+                Some(&(tag, alloc_id)) => {
+                    let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag);
                     return Ok(ScalarMaybeUndef::Scalar(ptr.into()))
                 }
                 None => {},
@@ -822,17 +921,20 @@ pub fn read_scalar(
         Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
     }
 
-    pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align)
-        -> EvalResult<'tcx, ScalarMaybeUndef> {
+    pub fn read_ptr_sized(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
         self.read_scalar(ptr, ptr_align, self.pointer_size())
     }
 
     /// Write a *non-ZST* scalar
     pub fn write_scalar(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         ptr_align: Align,
-        val: ScalarMaybeUndef,
+        val: ScalarMaybeUndef<M::PointerTag>,
         type_size: Size,
     ) -> EvalResult<'tcx> {
         let val = match val {
@@ -866,7 +968,7 @@ pub fn write_scalar(
             Scalar::Ptr(val) => {
                 self.get_mut(ptr.alloc_id)?.relocations.insert(
                     ptr.offset,
-                    val.alloc_id,
+                    (val.tag, val.alloc_id),
                 );
             }
             _ => {}
@@ -875,8 +977,12 @@ pub fn write_scalar(
         Ok(())
     }
 
-    pub fn write_ptr_sized(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef)
-        -> EvalResult<'tcx> {
+    pub fn write_ptr_sized(
+        &mut self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align,
+        val: ScalarMaybeUndef<M::PointerTag>
+    ) -> EvalResult<'tcx> {
         let ptr_size = self.pointer_size();
         self.write_scalar(ptr.into(), ptr_align, val, ptr_size)
     }
@@ -901,9 +1007,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     /// Return all relocations overlapping with the given ptr-offset pair.
     fn relocations(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
-    ) -> EvalResult<'tcx, &[(Size, AllocId)]> {
+    ) -> EvalResult<'tcx, &[(Size, (M::PointerTag, 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);
@@ -913,7 +1019,7 @@ fn relocations(
 
     /// Check that there ar eno relocations overlapping with the given range.
     #[inline(always)]
-    fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn check_relocations(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         if self.relocations(ptr, size)?.len() != 0 {
             err!(ReadPointerAsBytes)
         } else {
@@ -927,7 +1033,7 @@ fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
     /// 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> {
+    fn clear_relocations(&mut self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         // Find the start and end of the given range and its outermost relocations.
         let (first, last) = {
             // Find all relocations overlapping the given range.
@@ -962,7 +1068,7 @@ fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
     /// 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> {
+    fn check_relocation_edges(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         self.check_relocations(ptr, Size::ZERO)?;
         self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?;
         Ok(())
@@ -974,8 +1080,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     // FIXME: Add a fast version for the common, nonoverlapping case
     fn copy_undef_mask(
         &mut self,
-        src: Pointer,
-        dest: Pointer,
+        src: Pointer<M::PointerTag>,
+        dest: Pointer<M::PointerTag>,
         size: Size,
         repeat: u64,
     ) -> EvalResult<'tcx> {
@@ -1002,7 +1108,7 @@ fn copy_undef_mask(
     /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes`
     /// error which will report the first byte which is undefined.
     #[inline]
-    fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn check_defined(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         alloc.undef_mask.is_range_defined(
             ptr.offset,
@@ -1012,7 +1118,7 @@ fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
 
     pub fn mark_definedness(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         new_state: bool,
     ) -> EvalResult<'tcx> {
index b840af193b64a7d87c4fb3c4a40664d93e19a26f..39628598ef31cd1d1172d9fa35e16e0ce22bb964 100644 (file)
@@ -32,6 +32,8 @@
 
 pub use self::memory::{Memory, MemoryKind};
 
-pub use self::machine::Machine;
+pub use self::machine::{Machine, AllocMap};
 
 pub use self::operand::{ScalarMaybeUndef, Value, ValTy, Operand, OpTy};
+
+pub use self::validity::RefTracking;
index b53bcfa993d53d9ecb389c9347e442afe73eb363..039a92cee2ca2fcfba65f06617ece23d6de56141 100644 (file)
 use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind};
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum ScalarMaybeUndef<Id=AllocId> {
-    Scalar(Scalar<Id>),
+pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
+    Scalar(Scalar<Tag, Id>),
     Undef,
 }
 
-impl From<Scalar> for ScalarMaybeUndef {
+impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
     #[inline(always)]
-    fn from(s: Scalar) -> Self {
+    fn from(s: Scalar<Tag>) -> Self {
         ScalarMaybeUndef::Scalar(s)
     }
 }
 
-impl<'tcx> ScalarMaybeUndef {
+impl<'tcx> ScalarMaybeUndef<()> {
     #[inline]
-    pub fn not_undef(self) -> EvalResult<'static, Scalar> {
+    pub fn with_default_tag<Tag>(self) -> ScalarMaybeUndef<Tag>
+        where Tag: Default
+    {
+        match self {
+            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_default_tag()),
+            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
+        }
+    }
+}
+
+impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> ScalarMaybeUndef
+    {
+        match self {
+            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
+            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
+        }
+    }
+
+    #[inline]
+    pub fn not_undef(self) -> EvalResult<'static, Scalar<Tag>> {
         match self {
             ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
             ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
@@ -47,7 +68,7 @@ pub fn not_undef(self) -> EvalResult<'static, Scalar> {
     }
 
     #[inline(always)]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         self.not_undef()?.to_ptr()
     }
 
@@ -126,26 +147,49 @@ pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
 /// 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<Id=AllocId> {
-    Scalar(ScalarMaybeUndef<Id>),
-    ScalarPair(ScalarMaybeUndef<Id>, ScalarMaybeUndef<Id>),
+pub enum Value<Tag=(), Id=AllocId> {
+    Scalar(ScalarMaybeUndef<Tag, Id>),
+    ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
 }
 
-impl<'tcx> Value {
+impl Value {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> Value<Tag>
+        where Tag: Default
+    {
+        match self {
+            Value::Scalar(x) => Value::Scalar(x.with_default_tag()),
+            Value::ScalarPair(x, y) =>
+                Value::ScalarPair(x.with_default_tag(), y.with_default_tag()),
+        }
+    }
+}
+
+impl<'tcx, Tag> Value<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> Value
+    {
+        match self {
+            Value::Scalar(x) => Value::Scalar(x.erase_tag()),
+            Value::ScalarPair(x, y) =>
+                Value::ScalarPair(x.erase_tag(), y.erase_tag()),
+        }
+    }
+
     pub fn new_slice(
-        val: Scalar,
+        val: Scalar<Tag>,
         len: u64,
         cx: impl HasDataLayout
     ) -> Self {
         Value::ScalarPair(val.into(), Scalar::from_uint(len, cx.data_layout().pointer_size).into())
     }
 
-    pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
+    pub fn new_dyn_trait(val: Scalar<Tag>, vtable: Pointer<Tag>) -> Self {
         Value::ScalarPair(val.into(), Scalar::Ptr(vtable).into())
     }
 
     #[inline]
-    pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef {
+    pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef<Tag> {
         match self {
             Value::Scalar(val) => val,
             Value::ScalarPair(..) => bug!("Got a fat pointer where a scalar was expected"),
@@ -153,12 +197,12 @@ pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef {
     }
 
     #[inline]
-    pub fn to_scalar(self) -> EvalResult<'tcx, Scalar> {
+    pub fn to_scalar(self) -> EvalResult<'tcx, Scalar<Tag>> {
         self.to_scalar_or_undef().not_undef()
     }
 
     #[inline]
-    pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar, Scalar)> {
+    pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar<Tag>, Scalar<Tag>)> {
         match self {
             Value::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"),
             Value::ScalarPair(a, b) => Ok((a.not_undef()?, b.not_undef()?))
@@ -168,7 +212,7 @@ pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar, Scalar)> {
     /// Convert the value into a pointer (or a pointer-sized integer).
     /// Throws away the second half of a ScalarPair!
     #[inline]
-    pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
+    pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar<Tag>> {
         match self {
             Value::Scalar(ptr) |
             Value::ScalarPair(ptr, _) => ptr.not_undef(),
@@ -179,15 +223,15 @@ pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
 // 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> {
-    value: Value,
+pub struct ValTy<'tcx, Tag=()> {
+    value: Value<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for ValTy<'tcx> {
-    type Target = Value;
+impl<'tcx, Tag> ::std::ops::Deref for ValTy<'tcx, Tag> {
+    type Target = Value<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &Value {
+    fn deref(&self) -> &Value<Tag> {
         &self.value
     }
 }
@@ -196,14 +240,37 @@ 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<Id=AllocId> {
-    Immediate(Value<Id>),
-    Indirect(MemPlace<Id>),
+pub enum Operand<Tag=(), Id=AllocId> {
+    Immediate(Value<Tag, Id>),
+    Indirect(MemPlace<Tag, Id>),
 }
 
 impl Operand {
     #[inline]
-    pub fn to_mem_place(self) -> MemPlace {
+    pub fn with_default_tag<Tag>(self) -> Operand<Tag>
+        where Tag: Default
+    {
+        match self {
+            Operand::Immediate(x) => Operand::Immediate(x.with_default_tag()),
+            Operand::Indirect(x) => Operand::Indirect(x.with_default_tag()),
+        }
+    }
+}
+
+impl<Tag> Operand<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> Operand
+    {
+        match self {
+            Operand::Immediate(x) => Operand::Immediate(x.erase_tag()),
+            Operand::Indirect(x) => Operand::Indirect(x.erase_tag()),
+        }
+    }
+
+    #[inline]
+    pub fn to_mem_place(self) -> MemPlace<Tag>
+        where Tag: ::std::fmt::Debug
+    {
         match self {
             Operand::Indirect(mplace) => mplace,
             _ => bug!("to_mem_place: expected Operand::Indirect, got {:?}", self),
@@ -212,7 +279,9 @@ pub fn to_mem_place(self) -> MemPlace {
     }
 
     #[inline]
-    pub fn to_immediate(self) -> Value {
+    pub fn to_immediate(self) -> Value<Tag>
+        where Tag: ::std::fmt::Debug
+    {
         match self {
             Operand::Immediate(val) => val,
             _ => bug!("to_immediate: expected Operand::Immediate, got {:?}", self),
@@ -222,22 +291,22 @@ pub fn to_immediate(self) -> Value {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub struct OpTy<'tcx> {
-    crate op: Operand, // ideally we'd make this private, but const_prop needs this
+pub struct OpTy<'tcx, Tag=()> {
+    crate op: Operand<Tag>, // ideally we'd make this private, but const_prop needs this
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for OpTy<'tcx> {
-    type Target = Operand;
+impl<'tcx, Tag> ::std::ops::Deref for OpTy<'tcx, Tag> {
+    type Target = Operand<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &Operand {
+    fn deref(&self) -> &Operand<Tag> {
         &self.op
     }
 }
 
-impl<'tcx> From<MPlaceTy<'tcx>> for OpTy<'tcx> {
+impl<'tcx, Tag: Copy> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
-    fn from(mplace: MPlaceTy<'tcx>) -> Self {
+    fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
         OpTy {
             op: Operand::Indirect(*mplace),
             layout: mplace.layout
@@ -245,9 +314,9 @@ fn from(mplace: MPlaceTy<'tcx>) -> Self {
     }
 }
 
-impl<'tcx> From<ValTy<'tcx>> for OpTy<'tcx> {
+impl<'tcx, Tag> From<ValTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
-    fn from(val: ValTy<'tcx>) -> Self {
+    fn from(val: ValTy<'tcx, Tag>) -> Self {
         OpTy {
             op: Operand::Immediate(val.value),
             layout: val.layout
@@ -256,18 +325,36 @@ fn from(val: ValTy<'tcx>) -> Self {
 }
 
 // Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type
-impl<'tcx> Hash for OpTy<'tcx> {
+impl<'tcx, Tag> Hash for OpTy<'tcx, Tag>
+    where Tag: Hash
+{
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.op.hash(state);
         self.layout.ty.hash(state);
     }
 }
-impl<'tcx> PartialEq for OpTy<'tcx> {
+impl<'tcx, Tag> PartialEq for OpTy<'tcx, Tag>
+    where Tag: PartialEq
+{
     fn eq(&self, other: &Self) -> bool {
         self.op == other.op && self.layout.ty == other.layout.ty
     }
 }
-impl<'tcx> Eq for OpTy<'tcx> {}
+impl<'tcx, Tag> Eq for OpTy<'tcx, Tag>
+    where Tag: Eq
+{}
+
+impl<'tcx, Tag> OpTy<'tcx, Tag>
+{
+    #[inline]
+    pub fn erase_tag(self) -> OpTy<'tcx>
+    {
+        OpTy {
+            op: self.op.erase_tag(),
+            layout: self.layout,
+        }
+    }
+}
 
 // Use the existing layout if given (but sanity check in debug mode),
 // or compute the layout.
@@ -295,8 +382,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     /// Return None if the layout does not permit loading this as a value.
     pub(super) fn try_read_value_from_mplace(
         &self,
-        mplace: MPlaceTy<'tcx>,
-    ) -> EvalResult<'tcx, Option<Value>> {
+        mplace: MPlaceTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, Option<Value<M::PointerTag>>> {
         if mplace.layout.is_unsized() {
             // Dont touch unsized
             return Ok(None);
@@ -339,8 +426,8 @@ pub(super) fn try_read_value_from_mplace(
     /// in a `Value`, not on which data is stored there currently.
     pub(crate) fn try_read_value(
         &self,
-        src: OpTy<'tcx>,
-    ) -> EvalResult<'tcx, Result<Value, MemPlace>> {
+        src: OpTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, Result<Value<M::PointerTag>, MemPlace<M::PointerTag>>> {
         Ok(match src.try_as_mplace() {
             Ok(mplace) => {
                 if let Some(val) = self.try_read_value_from_mplace(mplace)? {
@@ -355,7 +442,10 @@ pub(crate) fn try_read_value(
 
     /// Read a value from a place, asserting that that is possible with the given layout.
     #[inline(always)]
-    pub fn read_value(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
+    pub fn read_value(
+        &self,
+        op: OpTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, ValTy<'tcx, M::PointerTag>> {
         if let Ok(value) = self.try_read_value(op)? {
             Ok(ValTy { value, layout: op.layout })
         } else {
@@ -364,7 +454,10 @@ pub fn read_value(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
     }
 
     /// Read a scalar from a place
-    pub fn read_scalar(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ScalarMaybeUndef> {
+    pub fn read_scalar(
+        &self,
+        op: OpTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
         match *self.read_value(op)? {
             Value::ScalarPair(..) => bug!("got ScalarPair for type: {:?}", op.layout.ty),
             Value::Scalar(val) => Ok(val),
@@ -374,7 +467,7 @@ pub fn read_scalar(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ScalarMaybeUndef>
     // Turn the MPlace into a string (must already be dereferenced!)
     pub fn read_str(
         &self,
-        mplace: MPlaceTy<'tcx>,
+        mplace: MPlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, &str> {
         let len = mplace.len(self)?;
         let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
@@ -383,7 +476,10 @@ pub fn read_str(
         Ok(str)
     }
 
-    pub fn uninit_operand(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Operand> {
+    pub fn uninit_operand(
+        &mut self,
+        layout: TyLayout<'tcx>
+    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
         // This decides which types we will use the Immediate optimization for, and hence should
         // match what `try_read_value` and `eval_place_to_op` support.
         if layout.is_zst() {
@@ -410,9 +506,9 @@ pub fn uninit_operand(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Ope
     /// Projection functions
     pub fn operand_field(
         &self,
-        op: OpTy<'tcx>,
+        op: OpTy<'tcx, M::PointerTag>,
         field: u64,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let base = match op.try_as_mplace() {
             Ok(mplace) => {
                 // The easy case
@@ -445,9 +541,9 @@ pub fn operand_field(
 
     pub fn operand_downcast(
         &self,
-        op: OpTy<'tcx>,
+        op: OpTy<'tcx, M::PointerTag>,
         variant: usize,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
         Ok(match op.try_as_mplace() {
             Ok(mplace) => {
@@ -464,8 +560,8 @@ pub fn operand_downcast(
     // will always be a MemPlace.
     pub(super) fn deref_operand(
         &self,
-        src: OpTy<'tcx>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        src: OpTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let val = self.read_value(src)?;
         trace!("deref to {} on {:?}", val.layout.ty, *val);
         Ok(self.ref_to_mplace(val)?)
@@ -473,9 +569,9 @@ pub(super) fn deref_operand(
 
     pub fn operand_projection(
         &self,
-        base: OpTy<'tcx>,
+        base: OpTy<'tcx, M::PointerTag>,
         proj_elem: &mir::PlaceElem<'tcx>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
             Field(field, _) => self.operand_field(base, field.index() as u64)?,
@@ -503,7 +599,7 @@ fn eval_place_to_op(
         &self,
         mir_place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let op = match *mir_place {
             Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
@@ -533,7 +629,7 @@ pub fn eval_operand(
         &self,
         mir_op: &mir::Operand<'tcx>,
         layout: Option<TyLayout<'tcx>>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Operand::*;
         let op = match *mir_op {
             // FIXME: do some more logic on `move` to invalidate the old location
@@ -558,7 +654,7 @@ pub fn eval_operand(
     pub(super) fn eval_operands(
         &self,
         ops: &[mir::Operand<'tcx>],
-    ) -> EvalResult<'tcx, Vec<OpTy<'tcx>>> {
+    ) -> EvalResult<'tcx, Vec<OpTy<'tcx, M::PointerTag>>> {
         ops.into_iter()
             .map(|op| self.eval_operand(op, None))
             .collect()
@@ -568,7 +664,7 @@ pub(super) fn eval_operands(
     pub(super) fn const_value_to_op(
         &self,
         val: ConstValue<'tcx>,
-    ) -> EvalResult<'tcx, Operand> {
+    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
         trace!("const_value_to_op: {:?}", val);
         match val {
             ConstValue::Unevaluated(def_id, substs) => {
@@ -581,23 +677,28 @@ 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::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)))
+                Ok(Operand::Indirect(
+                    MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)
+                ).with_default_tag())
             },
             ConstValue::ScalarPair(a, b) =>
-                Ok(Operand::Immediate(Value::ScalarPair(a.into(), b.into()))),
+                Ok(Operand::Immediate(Value::ScalarPair(a.into(), b.into())).with_default_tag()),
             ConstValue::Scalar(x) =>
-                Ok(Operand::Immediate(Value::Scalar(x.into()))),
+                Ok(Operand::Immediate(Value::Scalar(x.into())).with_default_tag()),
         }
     }
     pub fn const_to_op(
         &self,
         cnst: &ty::Const<'tcx>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let op = self.const_value_to_op(cnst.val)?;
         Ok(OpTy { op, layout: self.layout_of(cnst.ty)? })
     }
 
-    pub(super) fn global_to_op(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Operand> {
+    pub(super) fn global_to_op(
+        &self,
+        gid: GlobalId<'tcx>
+    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
         let cv = self.const_eval(gid)?;
         self.const_value_to_op(cv.val)
     }
@@ -605,7 +706,7 @@ pub(super) fn global_to_op(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Opera
     /// Read discriminant, return the runtime value as well as the variant index.
     pub fn read_discriminant(
         &self,
-        rval: OpTy<'tcx>,
+        rval: OpTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, (u128, usize)> {
         trace!("read_discriminant_value {:#?}", rval.layout);
         if rval.layout.abi.is_uninhabited() {
index dd6ee374c0facc9f4b4370f5577fb62f8c7b6636..5f4bafc39f3deec8aa57efb12157d67c36fd7a14 100644 (file)
@@ -24,9 +24,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     pub fn binop_with_overflow(
         &mut self,
         op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        left: ValTy<'tcx, M::PointerTag>,
+        right: ValTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let (val, overflowed) = self.binary_op_val(op, left, right)?;
         let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
@@ -38,9 +38,9 @@ pub fn binop_with_overflow(
     pub fn binop_ignore_overflow(
         &mut self,
         op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        left: ValTy<'tcx, M::PointerTag>,
+        right: ValTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let (val, _overflowed) = self.binary_op_val(op, left, right)?;
         self.write_scalar(val, dest)
@@ -53,7 +53,7 @@ fn binary_char_op(
         bin_op: mir::BinOp,
         l: char,
         r: char,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         let res = match bin_op {
@@ -73,7 +73,7 @@ fn binary_bool_op(
         bin_op: mir::BinOp,
         l: bool,
         r: bool,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         let res = match bin_op {
@@ -98,7 +98,7 @@ fn binary_float_op(
         // passing in raw bits
         l: u128,
         r: u128,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         macro_rules! float_math {
@@ -138,7 +138,7 @@ fn binary_int_op(
         left_layout: TyLayout<'tcx>,
         r: u128,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         // Shift ops can have an RHS with a different numeric type.
@@ -288,9 +288,9 @@ fn binary_int_op(
     pub fn binary_op_val(
         &self,
         bin_op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        left: ValTy<'tcx, M::PointerTag>,
+        right: ValTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         self.binary_op(
             bin_op,
             left.to_scalar()?, left.layout,
@@ -302,11 +302,11 @@ pub fn binary_op_val(
     pub fn binary_op(
         &self,
         bin_op: mir::BinOp,
-        left: Scalar,
+        left: Scalar<M::PointerTag>,
         left_layout: TyLayout<'tcx>,
-        right: Scalar,
+        right: Scalar<M::PointerTag>,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})",
             bin_op, left, left_layout.ty, right, right_layout.ty);
 
@@ -352,9 +352,9 @@ pub fn binary_op(
     pub fn unary_op(
         &self,
         un_op: mir::UnOp,
-        val: Scalar,
+        val: Scalar<M::PointerTag>,
         layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::mir::UnOp::*;
         use rustc_apfloat::ieee::{Single, Double};
         use rustc_apfloat::Float;
index 8878e5ca83f41f05ca770d22f78b756fa03b0316..8b9c6a5a270537fdaec0cff1e9e4c4c711ccf876 100644 (file)
 //! All high-level functions to write to memory work on places as destinations.
 
 use std::convert::TryFrom;
+use std::hash::Hash;
 
 use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
 
 use rustc::mir::interpret::{
-    GlobalId, AllocId, Scalar, EvalResult, Pointer, PointerArithmetic
+    GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
+};
+use super::{
+    EvalContext, Machine, AllocMap,
+    Value, ValTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
 };
-use super::{EvalContext, Machine, Value, ValTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind};
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub struct MemPlace<Id=AllocId> {
+pub struct MemPlace<Tag=(), 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<Id>,
+    pub ptr: Scalar<Tag, 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<Id>>,
+    pub meta: Option<Scalar<Tag, Id>>,
 }
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Place<Id=AllocId> {
+pub enum Place<Tag=(), Id=AllocId> {
     /// A place referring to a value allocated in the `Memory` system.
-    Ptr(MemPlace<Id>),
+    Ptr(MemPlace<Tag, 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,37 +54,37 @@ pub enum Place<Id=AllocId> {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub struct PlaceTy<'tcx> {
-    place: Place,
+pub struct PlaceTy<'tcx, Tag=()> {
+    place: Place<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for PlaceTy<'tcx> {
-    type Target = Place;
+impl<'tcx, Tag> ::std::ops::Deref for PlaceTy<'tcx, Tag> {
+    type Target = Place<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &Place {
+    fn deref(&self) -> &Place<Tag> {
         &self.place
     }
 }
 
 /// A MemPlace with its layout. Constructing it is only possible in this module.
 #[derive(Copy, Clone, Debug)]
-pub struct MPlaceTy<'tcx> {
-    mplace: MemPlace,
+pub struct MPlaceTy<'tcx, Tag=()> {
+    mplace: MemPlace<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for MPlaceTy<'tcx> {
-    type Target = MemPlace;
+impl<'tcx, Tag> ::std::ops::Deref for MPlaceTy<'tcx, Tag> {
+    type Target = MemPlace<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &MemPlace {
+    fn deref(&self) -> &MemPlace<Tag> {
         &self.mplace
     }
 }
 
-impl<'tcx> From<MPlaceTy<'tcx>> for PlaceTy<'tcx> {
+impl<'tcx, Tag> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
     #[inline(always)]
-    fn from(mplace: MPlaceTy<'tcx>) -> Self {
+    fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
         PlaceTy {
             place: Place::Ptr(mplace.mplace),
             layout: mplace.layout
@@ -89,29 +93,52 @@ fn from(mplace: MPlaceTy<'tcx>) -> Self {
 }
 
 impl MemPlace {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> MemPlace<Tag>
+        where Tag: Default
+    {
+        MemPlace {
+            ptr: self.ptr.with_default_tag(),
+            align: self.align,
+            meta: self.meta.map(Scalar::with_default_tag),
+        }
+    }
+}
+
+impl<Tag> MemPlace<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> MemPlace
+    {
+        MemPlace {
+            ptr: self.ptr.erase_tag(),
+            align: self.align,
+            meta: self.meta.map(Scalar::erase_tag),
+        }
+    }
+
     #[inline(always)]
-    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
         MemPlace {
             ptr,
             align,
-            extra: None,
+            meta: None,
         }
     }
 
     #[inline(always)]
-    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
+    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
         Self::from_scalar_ptr(ptr.into(), align)
     }
 
     #[inline(always)]
-    pub fn to_scalar_ptr_align(self) -> (Scalar, Align) {
-        assert_eq!(self.extra, None);
+    pub fn to_scalar_ptr_align(self) -> (Scalar<Tag>, Align) {
+        assert!(self.meta.is_none());
         (self.ptr, self.align)
     }
 
-    /// Extract the ptr part of the mplace
+    /// metact the ptr part of the mplace
     #[inline(always)]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         // At this point, we forget about the alignment information --
         // the place has been turned into a reference, and no matter where it came from,
         // it now must be aligned.
@@ -120,29 +147,41 @@ pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
 
     /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space.
     /// This is the inverse of `ref_to_mplace`.
-    pub fn to_ref(self) -> Value {
+    pub fn to_ref(self) -> Value<Tag> {
         // We ignore the alignment of the place here -- special handling for packed structs ends
         // at the `&` operator.
-        match self.extra {
+        match self.meta {
             None => Value::Scalar(self.ptr.into()),
-            Some(extra) => Value::ScalarPair(self.ptr.into(), extra.into()),
+            Some(meta) => Value::ScalarPair(self.ptr.into(), meta.into()),
         }
     }
 }
 
-impl<'tcx> MPlaceTy<'tcx> {
+impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
+    /// Produces a MemPlace that works for ZST but nothing else
     #[inline]
-    fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
+    pub fn dangling(layout: TyLayout<'tcx>, cx: impl HasDataLayout) -> Self {
+        MPlaceTy {
+            mplace: MemPlace::from_scalar_ptr(
+                Scalar::from_uint(layout.align.abi(), cx.pointer_size()),
+                layout.align
+            ),
+            layout
+        }
+    }
+
+    #[inline]
+    fn from_aligned_ptr(ptr: Pointer<Tag>, layout: TyLayout<'tcx>) -> Self {
         MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout }
     }
 
     #[inline]
     pub(super) fn len(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
         if self.layout.is_unsized() {
-            // We need to consult `extra` metadata
+            // We need to consult `meta` metadata
             match self.layout.ty.sty {
                 ty::Slice(..) | ty::Str =>
-                    return self.extra.unwrap().to_usize(cx),
+                    return self.mplace.meta.unwrap().to_usize(cx),
                 _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
             }
         } else {
@@ -156,30 +195,30 @@ pub(super) fn len(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
     }
 
     #[inline]
-    pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer> {
+    pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer<Tag>> {
         match self.layout.ty.sty {
-            ty::Dynamic(..) => self.extra.unwrap().to_ptr(),
+            ty::Dynamic(..) => self.mplace.meta.unwrap().to_ptr(),
             _ => bug!("vtable not supported on type {:?}", self.layout.ty),
         }
     }
 }
 
-impl<'tcx> OpTy<'tcx> {
+impl<'tcx, Tag: ::std::fmt::Debug> OpTy<'tcx, Tag> {
     #[inline(always)]
-    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx>, Value> {
-        match *self {
+    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx, Tag>, Value<Tag>> {
+        match self.op {
             Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
             Operand::Immediate(value) => Err(value),
         }
     }
 
     #[inline(always)]
-    pub fn to_mem_place(self) -> MPlaceTy<'tcx> {
+    pub fn to_mem_place(self) -> MPlaceTy<'tcx, Tag> {
         self.try_as_mplace().unwrap()
     }
 }
 
-impl<'tcx> Place {
+impl<'tcx, Tag: ::std::fmt::Debug> Place<Tag> {
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline]
     pub fn null(cx: impl HasDataLayout) -> Self {
@@ -187,17 +226,17 @@ pub fn null(cx: impl HasDataLayout) -> Self {
     }
 
     #[inline]
-    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
         Place::Ptr(MemPlace::from_scalar_ptr(ptr, align))
     }
 
     #[inline]
-    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
+    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
         Place::Ptr(MemPlace::from_ptr(ptr, align))
     }
 
     #[inline]
-    pub fn to_mem_place(self) -> MemPlace {
+    pub fn to_mem_place(self) -> MemPlace<Tag> {
         match self {
             Place::Ptr(mplace) => mplace,
             _ => bug!("to_mem_place: expected Place::Ptr, got {:?}", self),
@@ -206,17 +245,17 @@ pub fn to_mem_place(self) -> MemPlace {
     }
 
     #[inline]
-    pub fn to_scalar_ptr_align(self) -> (Scalar, Align) {
+    pub fn to_scalar_ptr_align(self) -> (Scalar<Tag>, Align) {
         self.to_mem_place().to_scalar_ptr_align()
     }
 
     #[inline]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         self.to_mem_place().to_ptr()
     }
 }
 
-impl<'tcx> PlaceTy<'tcx> {
+impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> {
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline]
     pub fn null(cx: impl HasDataLayout, layout: TyLayout<'tcx>) -> Self {
@@ -224,25 +263,31 @@ pub fn null(cx: impl HasDataLayout, layout: TyLayout<'tcx>) -> Self {
     }
 
     #[inline]
-    pub fn to_mem_place(self) -> MPlaceTy<'tcx> {
+    pub fn to_mem_place(self) -> MPlaceTy<'tcx, Tag> {
         MPlaceTy { mplace: self.place.to_mem_place(), layout: self.layout }
     }
 }
 
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
+impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
+where
+    Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static,
+    M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>,
+    M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag>)>,
+{
     /// Take a value, which represents a (thin or fat) reference, and make it a place.
     /// Alignment is just based on the type.  This is the inverse of `MemPlace::to_ref`.
     pub fn ref_to_mplace(
-        &self, val: ValTy<'tcx>
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        &self, val: ValTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty;
         let layout = self.layout_of(pointee_type)?;
         let align = layout.align;
         let mplace = match *val {
             Value::Scalar(ptr) =>
-                MemPlace { ptr: ptr.not_undef()?, align, extra: None },
-            Value::ScalarPair(ptr, extra) =>
-                MemPlace { ptr: ptr.not_undef()?, align, extra: Some(extra.not_undef()?) },
+                MemPlace { ptr: ptr.not_undef()?, align, meta: None },
+            Value::ScalarPair(ptr, meta) =>
+                MemPlace { ptr: ptr.not_undef()?, align, meta: Some(meta.not_undef()?) },
         };
         Ok(MPlaceTy { mplace, layout })
     }
@@ -253,9 +298,9 @@ pub fn ref_to_mplace(
     #[inline(always)]
     pub fn mplace_field(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         field: u64,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Not using the layout method because we want to compute on u64
         let offset = match base.layout.fields {
             layout::FieldPlacement::Arbitrary { ref offsets, .. } =>
@@ -278,13 +323,13 @@ pub fn mplace_field(
         let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?;
 
         // Offset may need adjustment for unsized fields
-        let (extra, offset) = if field_layout.is_unsized() {
+        let (meta, offset) = if field_layout.is_unsized() {
             // re-use parent metadata to determine dynamic field layout
-            let (_, align) = self.size_and_align_of(base.extra, field_layout)?;
-            (base.extra, offset.abi_align(align))
+            let (_, align) = self.size_and_align_of(base.meta, field_layout)?;
+            (base.meta, offset.abi_align(align))
 
         } else {
-            // base.extra could be present; we might be accessing a sized field of an unsized
+            // base.meta could be present; we might be accessing a sized field of an unsized
             // struct.
             (None, offset)
         };
@@ -295,15 +340,17 @@ pub fn mplace_field(
             // codegen -- mostly to see if we can get away with that
             .restrict_for_offset(offset); // must be last thing that happens
 
-        Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout })
+        Ok(MPlaceTy { mplace: MemPlace { ptr, align, meta }, layout: field_layout })
     }
 
     // Iterates over all fields of an array. Much more efficient than doing the
     // same by repeatedly calling `mplace_array`.
     pub fn mplace_array_fields(
         &self,
-        base: MPlaceTy<'tcx>,
-    ) -> EvalResult<'tcx, impl Iterator<Item=EvalResult<'tcx, MPlaceTy<'tcx>>> + 'a> {
+        base: MPlaceTy<'tcx, Tag>,
+    ) ->
+        EvalResult<'tcx, impl Iterator<Item=EvalResult<'tcx, MPlaceTy<'tcx, Tag>>> + 'a>
+    {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let stride = match base.layout.fields {
             layout::FieldPlacement::Array { stride, .. } => stride,
@@ -314,7 +361,7 @@ pub fn mplace_array_fields(
         Ok((0..len).map(move |i| {
             let ptr = base.ptr.ptr_offset(i * stride, dl)?;
             Ok(MPlaceTy {
-                mplace: MemPlace { ptr, align: base.align, extra: None },
+                mplace: MemPlace { ptr, align: base.align, meta: None },
                 layout
             })
         }))
@@ -322,10 +369,10 @@ pub fn mplace_array_fields(
 
     pub fn mplace_subslice(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         from: u64,
         to: u64,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         assert!(from <= len - to);
 
@@ -338,9 +385,9 @@ pub fn mplace_subslice(
         };
         let ptr = base.ptr.ptr_offset(from_offset, self)?;
 
-        // Compute extra and new layout
+        // Compute meta and new layout
         let inner_len = len - to - from;
-        let (extra, ty) = match base.layout.ty.sty {
+        let (meta, ty) = match base.layout.ty.sty {
             // It is not nice to match on the type, but that seems to be the only way to
             // implement this.
             ty::Array(inner, _) =>
@@ -355,27 +402,27 @@ pub fn mplace_subslice(
         let layout = self.layout_of(ty)?;
 
         Ok(MPlaceTy {
-            mplace: MemPlace { ptr, align: base.align, extra },
+            mplace: MemPlace { ptr, align: base.align, meta },
             layout
         })
     }
 
     pub fn mplace_downcast(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         variant: usize,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        assert_eq!(base.extra, None);
+        assert!(base.meta.is_none());
         Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..base })
     }
 
     /// Project into an mplace
     pub fn mplace_projection(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         proj_elem: &mir::PlaceElem<'tcx>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
             Field(field, _) => self.mplace_field(base, field.index() as u64)?,
@@ -416,9 +463,9 @@ pub fn mplace_projection(
     /// Just a convenience function, but used quite a bit.
     pub fn place_field(
         &mut self,
-        base: PlaceTy<'tcx>,
+        base: PlaceTy<'tcx, M::PointerTag>,
         field: u64,
-    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         // FIXME: We could try to be smarter and avoid allocation for fields that span the
         // entire place.
         let mplace = self.force_allocation(base)?;
@@ -427,9 +474,9 @@ pub fn place_field(
 
     pub fn place_downcast(
         &mut self,
-        base: PlaceTy<'tcx>,
+        base: PlaceTy<'tcx, M::PointerTag>,
         variant: usize,
-    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         // Downcast just changes the layout
         Ok(match base.place {
             Place::Ptr(mplace) =>
@@ -444,9 +491,9 @@ pub fn place_downcast(
     /// Project into a place
     pub fn place_projection(
         &mut self,
-        base: PlaceTy<'tcx>,
+        base: PlaceTy<'tcx, M::PointerTag>,
         proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
-    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
             Field(field, _) =>  self.place_field(base, field.index() as u64)?,
@@ -466,7 +513,7 @@ pub fn place_projection(
     pub(super) fn eval_place_to_mplace(
         &self,
         mir_place: &mir::Place<'tcx>
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         Ok(match *mir_place {
             Promoted(ref promoted) => {
@@ -503,7 +550,7 @@ pub(super) fn eval_place_to_mplace(
                 // and miri: They use the same query to eventually obtain a `ty::Const`
                 // and use that for further computation.
                 let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
-                MPlaceTy::from_aligned_ptr(alloc.into(), layout)
+                MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
             }
 
             _ => bug!("eval_place_to_mplace called on {:?}", mir_place),
@@ -512,7 +559,10 @@ pub(super) fn eval_place_to_mplace(
 
     /// Compute a place.  You should only use this if you intend to write into this
     /// place; for reading, a more efficient alternative is `eval_place_for_read`.
-    pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    pub fn eval_place(
+        &mut self,
+        mir_place: &mir::Place<'tcx>
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let place = match *mir_place {
             Local(mir::RETURN_PLACE) => PlaceTy {
@@ -542,8 +592,8 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
     /// Write a scalar to a place
     pub fn write_scalar(
         &mut self,
-        val: impl Into<ScalarMaybeUndef>,
-        dest: PlaceTy<'tcx>,
+        val: impl Into<ScalarMaybeUndef<M::PointerTag>>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         self.write_value(Value::Scalar(val.into()), dest)
     }
@@ -551,10 +601,17 @@ pub fn write_scalar(
     /// Write a value to a place
     pub fn write_value(
         &mut self,
-        src_val: Value,
-        dest: PlaceTy<'tcx>,
+        src_val: Value<M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         trace!("write_value: {:?} <- {:?}", *dest, src_val);
+        // Check that the value actually is okay for that type
+        if M::ENFORCE_VALIDITY {
+            // Something changed somewhere, better make sure it matches the type!
+            let op = OpTy { op: Operand::Immediate(src_val), layout: dest.layout };
+            self.validate_operand(op, &mut vec![], None, /*const_mode*/false)?;
+        }
+
         // See if we can avoid an allocation. This is the counterpart to `try_read_value`,
         // but not factored as a separate function.
         let mplace = match dest.place {
@@ -576,11 +633,12 @@ pub fn write_value(
         self.write_value_to_mplace(src_val, dest)
     }
 
-    /// Write a value to memory
+    /// Write a value to memory. This does NOT do validation, so you better had already
+    /// done that before calling this!
     fn write_value_to_mplace(
         &mut self,
-        value: Value,
-        dest: MPlaceTy<'tcx>,
+        value: Value<M::PointerTag>,
+        dest: MPlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let (ptr, ptr_align) = dest.to_scalar_ptr_align();
         // Note that it is really important that the type here is the right one, and matches the
@@ -621,8 +679,8 @@ fn write_value_to_mplace(
     /// Copy the data from an operand to a place
     pub fn copy_op(
         &mut self,
-        src: OpTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
             "Cannot copy unsized data");
@@ -640,20 +698,26 @@ pub fn copy_op(
         };
         // Slow path, this does not fit into an immediate. Just memcpy.
         trace!("copy_op: {:?} <- {:?}", *dest, *src);
-        let (dest_ptr, dest_align) = self.force_allocation(dest)?.to_scalar_ptr_align();
+        let dest = self.force_allocation(dest)?;
+        let (dest_ptr, dest_align) = dest.to_scalar_ptr_align();
         self.memory.copy(
             src_ptr, src_align,
             dest_ptr, dest_align,
             src.layout.size, false
-        )
+        )?;
+        if M::ENFORCE_VALIDITY {
+            // Something changed somewhere, better make sure it matches the type!
+            self.validate_operand(dest.into(), &mut vec![], None, /*const_mode*/false)?;
+        }
+        Ok(())
     }
 
     /// Make sure that a place is in memory, and return where it is.
     /// This is essentially `force_to_memplace`.
     pub fn force_allocation(
         &mut self,
-        place: PlaceTy<'tcx>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        place: PlaceTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let mplace = match place.place {
             Place::Local { frame, local } => {
                 match *self.stack[frame].locals[local].access()? {
@@ -668,6 +732,8 @@ pub fn force_allocation(
                         // that has different alignment than the outer field.
                         let local_layout = self.layout_of_local(frame, local)?;
                         let ptr = self.allocate(local_layout, MemoryKind::Stack)?;
+                        // We don't have to validate as we can assume the local
+                        // was already valid for its type.
                         self.write_value_to_mplace(value, ptr)?;
                         let mplace = ptr.mplace;
                         // Update the local
@@ -687,7 +753,7 @@ pub fn allocate(
         &mut self,
         layout: TyLayout<'tcx>,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
         let ptr = self.memory.allocate(layout.size, layout.align, kind)?;
         Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
@@ -696,7 +762,7 @@ pub fn allocate(
     pub fn write_discriminant_index(
         &mut self,
         variant_index: usize,
-        dest: PlaceTy<'tcx>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         match dest.layout.variants {
             layout::Variants::Single { index } => {
@@ -744,7 +810,10 @@ pub fn write_discriminant_index(
 
     /// Every place can be read from, so we can turm them into an operand
     #[inline(always)]
-    pub fn place_to_op(&self, place: PlaceTy<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>> {
+    pub fn place_to_op(
+        &self,
+        place: PlaceTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let op = match place.place {
             Place::Ptr(mplace) => {
                 Operand::Indirect(mplace)
@@ -757,8 +826,8 @@ pub fn place_to_op(&self, place: PlaceTy<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>>
 
     /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
     /// Also return some more information so drop doesn't have to run the same code twice.
-    pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>)
-    -> EvalResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx>)> {
+    pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx, M::PointerTag>)
+    -> EvalResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> {
         let vtable = mplace.vtable()?; // also sanity checks the type
         let (instance, ty) = self.read_drop_type_from_vtable(vtable)?;
         let layout = self.layout_of(ty)?;
@@ -771,7 +840,7 @@ pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>)
         }
 
         let mplace = MPlaceTy {
-            mplace: MemPlace { extra: None, ..*mplace },
+            mplace: MemPlace { meta: None, ..*mplace },
             layout
         };
         Ok((instance, mplace))
index 9b507eca3633b1cf16f771dd4ae16f0c05ce86e5..06aee8605c6e10cc05fadee13a6503f3e0f3959e 100644 (file)
@@ -99,6 +99,8 @@ macro_rules! __impl_snapshot_field {
     ($field:ident, $ctx:expr, $delegate:expr) => ($delegate);
 }
 
+// This assumes the type has two type parameters, first for the tag (set to `()`),
+// then for the id
 macro_rules! impl_snapshot_for {
     // FIXME(mark-i-m): Some of these should be `?` rather than `*`.
     (enum $enum_name:ident {
@@ -108,7 +110,7 @@ macro_rules! impl_snapshot_for {
         impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name
             where Ctx: self::SnapshotContext<'a>,
         {
-            type Item = $enum_name<AllocIdSnapshot<'a>>;
+            type Item = $enum_name<(), AllocIdSnapshot<'a>>;
 
             #[inline]
             fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
@@ -129,7 +131,7 @@ fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
         impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name
             where Ctx: self::SnapshotContext<'a>,
         {
-            type Item = $struct_name<AllocIdSnapshot<'a>>;
+            type Item = $struct_name<(), AllocIdSnapshot<'a>>;
 
             #[inline]
             fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
@@ -175,12 +177,13 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 impl_snapshot_for!(struct Pointer {
     alloc_id,
     offset -> *offset, // just copy offset verbatim
+    tag -> *tag, // just copy tag
 });
 
 impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = Scalar<AllocIdSnapshot<'a>>;
+    type Item = Scalar<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
         match self {
@@ -206,11 +209,11 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 impl_stable_hash_for!(struct ::interpret::MemPlace {
     ptr,
     align,
-    extra,
+    meta,
 });
 impl_snapshot_for!(struct MemPlace {
     ptr,
-    extra,
+    meta,
     align -> *align, // just copy alignment verbatim
 });
 
@@ -234,7 +237,7 @@ fn hash_stable<W: StableHasherResult>(
 impl<'a, Ctx> Snapshot<'a, Ctx> for Place
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = Place<AllocIdSnapshot<'a>>;
+    type Item = Place<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
         match self {
@@ -278,11 +281,11 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = Relocations<AllocIdSnapshot<'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)))
+            .map(|(size, ((), id))| (*size, ((), id.snapshot(ctx))))
             .collect())
     }
 }
@@ -290,7 +293,7 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 #[derive(Eq, PartialEq)]
 struct AllocationSnapshot<'a> {
     bytes: &'a [u8],
-    relocations: Relocations<AllocIdSnapshot<'a>>,
+    relocations: Relocations<(), AllocIdSnapshot<'a>>,
     undef_mask: &'a UndefMask,
     align: &'a Align,
     mutability: &'a Mutability,
@@ -334,8 +337,8 @@ 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>>>,
+    return_place: Place<(), AllocIdSnapshot<'a>>,
+    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
     block: &'a mir::BasicBlock,
     stmt: usize,
 }
index c7ed69e0cb66d882a01ba78fc599b96d9bc675ba..e599608b2dac99d875218f4f98c7e9ce6240d57d 100644 (file)
@@ -205,8 +205,8 @@ fn check_argument_compat(
     fn pass_argument(
         &mut self,
         skip_zst: bool,
-        caller_arg: &mut impl Iterator<Item=OpTy<'tcx>>,
-        callee_arg: PlaceTy<'tcx>,
+        caller_arg: &mut impl Iterator<Item=OpTy<'tcx, M::PointerTag>>,
+        callee_arg: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         if skip_zst && callee_arg.layout.is_zst() {
             // Nothing to do.
@@ -231,8 +231,8 @@ fn eval_fn_call(
         instance: ty::Instance<'tcx>,
         span: Span,
         caller_abi: Abi,
-        args: &[OpTy<'tcx>],
-        dest: Option<PlaceTy<'tcx>>,
+        args: &[OpTy<'tcx, M::PointerTag>],
+        dest: Option<PlaceTy<'tcx, M::PointerTag>>,
         ret: Option<mir::BasicBlock>,
     ) -> EvalResult<'tcx> {
         trace!("eval_fn_call: {:#?}", instance);
@@ -287,7 +287,7 @@ fn eval_fn_call(
 
                 let return_place = match dest {
                     Some(place) => *place,
-                    None => Place::null(&self),
+                    None => Place::null(&self), // any access will error. good!
                 };
                 self.push_stack_frame(
                     instance,
@@ -330,7 +330,7 @@ fn eval_fn_call(
                     // 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>]> =
+                    let caller_args : Cow<[OpTy<'tcx, M::PointerTag>]> =
                         if caller_abi == Abi::RustCall && !args.is_empty() {
                             // Untuple
                             let (&untuple_arg, args) = args.split_last().unwrap();
@@ -339,7 +339,7 @@ fn eval_fn_call(
                                 .chain((0..untuple_arg.layout.fields.count()).into_iter()
                                     .map(|i| self.operand_field(untuple_arg, i as u64))
                                 )
-                                .collect::<EvalResult<Vec<OpTy<'tcx>>>>()?)
+                                .collect::<EvalResult<Vec<OpTy<'tcx, M::PointerTag>>>>()?)
                         } else {
                             // Plain arg passing
                             Cow::from(args)
@@ -373,6 +373,20 @@ fn eval_fn_call(
                         trace!("Caller has too many args over");
                         return err!(FunctionArgCountMismatch);
                     }
+                    // Don't forget to check the return type!
+                    if let Some(caller_ret) = dest {
+                        let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
+                        if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) {
+                            return err!(FunctionRetMismatch(
+                                caller_ret.layout.ty, callee_ret.layout.ty
+                            ));
+                        }
+                    } else {
+                        // FIXME: The caller thinks this function cannot return. How do
+                        // we verify that the callee agrees?
+                        // On the plus side, the the callee ever writes to its return place,
+                        // that will be detected as UB (because we set that to NULL above).
+                    }
                     Ok(())
                 })();
                 match res {
@@ -412,7 +426,7 @@ fn eval_fn_call(
 
     fn drop_in_place(
         &mut self,
-        place: PlaceTy<'tcx>,
+        place: PlaceTy<'tcx, M::PointerTag>,
         instance: ty::Instance<'tcx>,
         span: Span,
         target: mir::BasicBlock,
index 5ea588b957a4ffed98f4a25d3424e301b2d1f2a4..227c85772d228aa22f5179c0726fb0f22e5164c0 100644 (file)
@@ -12,8 +12,6 @@
 use rustc::ty::layout::{Size, Align, LayoutOf};
 use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
 
-use syntax::ast::Mutability;
-
 use super::{EvalContext, Machine, MemoryKind};
 
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -27,9 +25,11 @@ pub fn get_vtable(
         &mut self,
         ty: Ty<'tcx>,
         trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> EvalResult<'tcx, Pointer> {
+    ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
         debug!("get_vtable(trait_ref={:?})", trait_ref);
 
+        // FIXME: Cache this!
+
         let layout = self.layout_of(trait_ref.self_ty())?;
         assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
         let size = layout.size.bytes();
@@ -41,7 +41,7 @@ pub fn get_vtable(
         let vtable = self.memory.allocate(
             ptr_size * (3 + methods.len() as u64),
             ptr_align,
-            MemoryKind::Stack,
+            MemoryKind::Vtable,
         )?;
 
         let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
@@ -63,10 +63,7 @@ pub fn get_vtable(
             }
         }
 
-        self.memory.intern_static(
-            vtable.alloc_id,
-            Mutability::Immutable,
-        )?;
+        self.memory.mark_immutable(vtable.alloc_id)?;
 
         Ok(vtable)
     }
@@ -74,7 +71,7 @@ pub fn get_vtable(
     /// Return the drop fn instance as well as the actual dynamic type
     pub fn read_drop_type_from_vtable(
         &self,
-        vtable: Pointer,
+        vtable: Pointer<M::PointerTag>,
     ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> {
         // we don't care about the pointee type, we just want a pointer
         let pointer_align = self.tcx.data_layout.pointer_align;
@@ -90,7 +87,7 @@ pub fn read_drop_type_from_vtable(
 
     pub fn read_size_and_align_from_vtable(
         &self,
-        vtable: Pointer,
+        vtable: Pointer<M::PointerTag>,
     ) -> EvalResult<'tcx, (Size, Align)> {
         let pointer_size = self.pointer_size();
         let pointer_align = self.tcx.data_layout.pointer_align;
index c5238d24cf7eddcbb8db0934fa74490205210541..9dc035a3e20b81d115f4680e87ac6a59ae15bb09 100644 (file)
@@ -9,20 +9,21 @@
 // except according to those terms.
 
 use std::fmt::Write;
+use std::hash::Hash;
 
 use syntax_pos::symbol::Symbol;
-use rustc::ty::layout::{self, Size, Primitive};
-use rustc::ty::{self, Ty};
+use rustc::ty::layout::{self, Size, Align, TyLayout};
+use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
-    Scalar, AllocType, EvalResult, EvalErrorKind, PointerArithmetic
+    Scalar, AllocType, EvalResult, EvalErrorKind
 };
 
 use super::{
-    OpTy, Machine, EvalContext, ScalarMaybeUndef
+    ValTy, OpTy, MPlaceTy, Machine, EvalContext, ScalarMaybeUndef
 };
 
-macro_rules! validation_failure{
+macro_rules! validation_failure {
     ($what:expr, $where:expr, $details:expr) => {{
         let where_ = path_format($where);
         let where_ = if where_.is_empty() {
@@ -49,6 +50,22 @@ macro_rules! validation_failure{
     }};
 }
 
+macro_rules! try_validation {
+    ($e:expr, $what:expr, $where:expr, $details:expr) => {{
+        match $e {
+            Ok(x) => x,
+            Err(_) => return validation_failure!($what, $where, $details),
+        }
+    }};
+
+    ($e:expr, $what:expr, $where:expr) => {{
+        match $e {
+            Ok(x) => x,
+            Err(_) => return validation_failure!($what, $where),
+        }
+    }}
+}
+
 /// We want to show a nice path to the invalid field for diagnotsics,
 /// but avoid string operations in the happy case where no error happens.
 /// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
@@ -63,6 +80,23 @@ pub enum PathElem {
     Tag,
 }
 
+/// State for tracking recursive validation of references
+pub struct RefTracking<'tcx, Tag> {
+    pub seen: FxHashSet<(OpTy<'tcx, Tag>)>,
+    pub todo: Vec<(OpTy<'tcx, Tag>, Vec<PathElem>)>,
+}
+
+impl<'tcx, Tag: Copy+Eq+Hash> RefTracking<'tcx, Tag> {
+    pub fn new(op: OpTy<'tcx, Tag>) -> Self {
+        let mut ref_tracking = RefTracking {
+            seen: FxHashSet(),
+            todo: vec![(op, Vec::new())],
+        };
+        ref_tracking.seen.insert(op);
+        ref_tracking
+    }
+}
+
 // Adding a Deref and making a copy of the path to be put into the queue
 // always go together.  This one does it with only new allocation.
 fn path_clone_and_deref(path: &Vec<PathElem>) -> Vec<PathElem> {
@@ -95,133 +129,251 @@ fn path_format(path: &Vec<PathElem>) -> String {
     out
 }
 
+fn scalar_format<Tag>(value: ScalarMaybeUndef<Tag>) -> String {
+    match value {
+        ScalarMaybeUndef::Undef =>
+            "uninitialized bytes".to_owned(),
+        ScalarMaybeUndef::Scalar(Scalar::Ptr(_)) =>
+            "a pointer".to_owned(),
+        ScalarMaybeUndef::Scalar(Scalar::Bits { bits, .. }) =>
+            bits.to_string(),
+    }
+}
+
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    fn validate_scalar(
+    /// Make sure that `value` is valid for `ty`, *assuming* `ty` is a primitive type.
+    fn validate_primitive_type(
         &self,
-        value: ScalarMaybeUndef,
-        size: Size,
-        scalar: &layout::Scalar,
+        value: ValTy<'tcx, M::PointerTag>,
         path: &Vec<PathElem>,
-        ty: Ty,
+        ref_tracking: Option<&mut RefTracking<'tcx, M::PointerTag>>,
+        const_mode: bool,
     ) -> EvalResult<'tcx> {
-        trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
-        let (lo, hi) = scalar.valid_range.clone().into_inner();
-
-        let value = match value {
-            ScalarMaybeUndef::Scalar(scalar) => scalar,
-            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
-        };
-
-        let bits = match value {
-            Scalar::Bits { bits, size: value_size } => {
-                assert_eq!(value_size as u64, size.bytes());
-                bits
+        // Go over all the primitive types
+        let ty = value.layout.ty;
+        match ty.sty {
+            ty::Bool => {
+                let value = value.to_scalar_or_undef();
+                try_validation!(value.to_bool(),
+                    scalar_format(value), path, "a boolean");
             },
-            Scalar::Ptr(_) => {
-                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::Char => {
+                let value = value.to_scalar_or_undef();
+                try_validation!(value.to_char(),
+                    scalar_format(value), path, "a valid unicode codepoint");
+            },
+            ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
+                let size = value.layout.size;
+                let value = value.to_scalar_or_undef();
+                if const_mode {
+                    // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
+                    try_validation!(value.to_bits(size),
+                        scalar_format(value), path, "initialized plain bits");
+                } else {
+                    // At run-time, for now, we accept *anything* for these types, including
+                    // undef. We should fix that, but let's start low.
+                }
+            }
+            _ if ty.is_box() || ty.is_region_ptr() || ty.is_unsafe_ptr() => {
+                // Handle fat pointers. We also check fat raw pointers,
+                // their metadata must be valid!
+                // This also checks that the ptr itself is initialized, which
+                // seems reasonable even for raw pointers.
+                let place = try_validation!(self.ref_to_mplace(value),
+                    "undefined data in pointer", path);
+                // Check metadata early, for better diagnostics
+                if place.layout.is_unsized() {
+                    let tail = self.tcx.struct_tail(place.layout.ty);
+                    match tail.sty {
+                        ty::Dynamic(..) => {
+                            let vtable = try_validation!(place.meta.unwrap().to_ptr(),
+                                "non-pointer vtable in fat pointer", path);
+                            try_validation!(self.read_drop_type_from_vtable(vtable),
+                                "invalid drop fn in vtable", path);
+                            try_validation!(self.read_size_and_align_from_vtable(vtable),
+                                "invalid size or align in vtable", path);
+                            // FIXME: More checks for the vtable.
+                        }
+                        ty::Slice(..) | ty::Str => {
+                            try_validation!(place.meta.unwrap().to_usize(self),
+                                "non-integer slice length in fat pointer", path);
+                        }
+                        ty::Foreign(..) => {
+                            // Unsized, but not fat.
+                        }
+                        _ =>
+                            bug!("Unexpected unsized type tail: {:?}", tail),
                     }
-                    ty::RawPtr(_) |
-                    ty::Ref(_, _, _) |
-                    ty::FnPtr(_) => {}
-                    _ => { unreachable!(); }
                 }
+                // for safe ptrs, also check the ptr values itself
+                if !ty.is_unsafe_ptr() {
+                    // Make sure this is non-NULL and aligned
+                    let (size, align) = self.size_and_align_of(place.meta, place.layout)?;
+                    match self.memory.check_align(place.ptr, align) {
+                        Ok(_) => {},
+                        Err(err) => match err.kind {
+                            EvalErrorKind::InvalidNullPointerUsage =>
+                                return validation_failure!("NULL reference", path),
+                            EvalErrorKind::AlignmentCheckFailed { .. } =>
+                                return validation_failure!("unaligned reference", path),
+                            _ =>
+                                return validation_failure!(
+                                    "dangling (deallocated) reference", path
+                                ),
+                        }
+                    }
+                    // non-ZST also have to be dereferencable
+                    if size != Size::ZERO {
+                        let ptr = try_validation!(place.ptr.to_ptr(),
+                            "integer pointer in non-ZST reference", path);
+                        if const_mode {
+                            // Skip validation entirely for some external statics
+                            let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
+                            if let Some(AllocType::Static(did)) = alloc_kind {
+                                // `extern static` cannot be validated as they have no body.
+                                // FIXME: Statics from other crates are also skipped.
+                                // They might be checked at a different type, but for now we
+                                // want to avoid recursing too deeply.  This is not sound!
+                                if !did.is_local() || self.tcx.is_foreign_item(did) {
+                                    return Ok(());
+                                }
+                            }
+                        }
+                        try_validation!(self.memory.check_bounds(ptr, size, false),
+                            "dangling (not entirely in bounds) reference", path);
+                    }
+                    if let Some(ref_tracking) = ref_tracking {
+                        // Check if we have encountered this pointer+layout combination
+                        // before.  Proceed recursively even for integer pointers, no
+                        // reason to skip them! They are (recursively) valid for some ZST,
+                        // but not for others (e.g. `!` is a ZST).
+                        let op = place.into();
+                        if ref_tracking.seen.insert(op) {
+                            trace!("Recursing below ptr {:#?}", *op);
+                            ref_tracking.todo.push((op, path_clone_and_deref(path)));
+                        }
+                    }
+                }
+            }
+            ty::FnPtr(_sig) => {
+                let value = value.to_scalar_or_undef();
+                let ptr = try_validation!(value.to_ptr(),
+                    scalar_format(value), path, "a pointer");
+                let _fn = try_validation!(self.memory.get_fn(ptr),
+                    scalar_format(value), path, "a function pointer");
+                // FIXME: Check if the signature matches
+            }
+            // This should be all the primitive types
+            ty::Never => bug!("Uninhabited type should have been catched earlier"),
+            _ => bug!("Unexpected primitive type {}", value.layout.ty)
+        }
+        Ok(())
+    }
 
-                let ptr_size = self.pointer_size();
-                let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
-                return if lo > hi {
-                    if lo - hi == 1 {
-                        // no gap, all values are ok
-                        Ok(())
-                    } else if hi < ptr_max || lo > 1 {
-                        let max = u128::max_value() >> (128 - size.bits());
-                        validation_failure!(
-                            "pointer",
-                            path,
-                            format!("something in the range {:?} or {:?}", 0..=lo, hi..=max)
-                        )
-                    } else {
-                        Ok(())
+    /// Make sure that `value` matches the
+    fn validate_scalar_layout(
+        &self,
+        value: ScalarMaybeUndef<M::PointerTag>,
+        size: Size,
+        path: &Vec<PathElem>,
+        layout: &layout::Scalar,
+    ) -> EvalResult<'tcx> {
+        let (lo, hi) = layout.valid_range.clone().into_inner();
+        let max_hi = u128::max_value() >> (128 - size.bits()); // as big as the size fits
+        assert!(hi <= max_hi);
+        if lo == 0 && hi == max_hi {
+            // Nothing to check
+            return Ok(());
+        }
+        // At least one value is excluded. Get the bits.
+        let value = try_validation!(value.not_undef(),
+            scalar_format(value), path, format!("something in the range {:?}", layout.valid_range));
+        let bits = match value {
+            Scalar::Ptr(ptr) => {
+                if lo == 1 && hi == max_hi {
+                    // only NULL is not allowed.
+                    // We can call `check_align` to check non-NULL-ness, but have to also look
+                    // for function pointers.
+                    let non_null =
+                        self.memory.check_align(
+                            Scalar::Ptr(ptr), Align::from_bytes(1, 1).unwrap()
+                        ).is_ok() ||
+                        self.memory.get_fn(ptr).is_ok();
+                    if !non_null {
+                        // could be NULL
+                        return validation_failure!("a potentially NULL pointer", path);
                     }
-                } else if hi < ptr_max || lo > 1 {
-                    validation_failure!(
-                        "pointer",
-                        path,
-                        format!("something in the range {:?}", scalar.valid_range)
-                    )
+                    return Ok(());
                 } else {
-                    Ok(())
-                };
-            },
-        };
-
-        // char gets a special treatment, because its number space is not contiguous so `TyLayout`
-        // has no special checks for chars
-        match ty.sty {
-            ty::Char => {
-                debug_assert_eq!(size.bytes(), 4);
-                if ::std::char::from_u32(bits as u32).is_none() {
+                    // Conservatively, we reject, because the pointer *could* have this
+                    // value.
                     return validation_failure!(
-                        "character",
+                        "a pointer",
                         path,
-                        "a valid unicode codepoint"
+                        format!(
+                            "something that cannot possibly be outside the (wrapping) range {:?}",
+                            layout.valid_range
+                        )
                     );
                 }
             }
-            _ => {},
-        }
-
+            Scalar::Bits { bits, size: value_size } => {
+                assert_eq!(value_size as u64, size.bytes());
+                bits
+            }
+        };
+        // Now compare. This is slightly subtle because this is a special "wrap-around" range.
         use std::ops::RangeInclusive;
         let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
         if lo > hi {
-            if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
+            // wrapping around
+            if in_range(0..=hi) || in_range(lo..=max_hi) {
                 Ok(())
             } else {
                 validation_failure!(
                     bits,
                     path,
-                    format!("something in the range {:?} or {:?}", ..=hi, lo..)
+                    format!("something in the range {:?} or {:?}", 0..=hi, lo..=max_hi)
                 )
             }
         } else {
-            if in_range(scalar.valid_range.clone()) {
+            if in_range(layout.valid_range.clone()) {
                 Ok(())
             } else {
                 validation_failure!(
                     bits,
                     path,
-                    format!("something in the range {:?}", scalar.valid_range)
+                    if hi == max_hi {
+                        format!("something greater or equal to {}", lo)
+                    } else {
+                        format!("something in the range {:?}", layout.valid_range)
+                    }
                 )
             }
         }
     }
 
-    /// This function checks the data at `op`.
+    /// This function checks the data at `op`.  `op` is assumed to cover valid memory if it
+    /// is an indirect operand.
     /// It will error if the bits at the destination do not match the ones described by the layout.
     /// The `path` may be pushed to, but the part that is present when the function
     /// starts must not be changed!
+    ///
+    /// `ref_tracking` can be None to avoid recursive checking below references.
+    /// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
+    /// validation (e.g., pointer values are fine in integers at runtime).
     pub fn validate_operand(
         &self,
-        dest: OpTy<'tcx>,
+        dest: OpTy<'tcx, M::PointerTag>,
         path: &mut Vec<PathElem>,
-        seen: &mut FxHashSet<(OpTy<'tcx>)>,
-        todo: &mut Vec<(OpTy<'tcx>, Vec<PathElem>)>,
+        mut ref_tracking: Option<&mut RefTracking<'tcx, M::PointerTag>>,
+        const_mode: bool,
     ) -> EvalResult<'tcx> {
-        trace!("validate_operand: {:?}, {:#?}", *dest, dest.layout);
+        trace!("validate_operand: {:?}, {:?}", *dest, dest.layout.ty);
 
-        // Find the right variant.  We have to handle this as a prelude, not via
-        // proper recursion with the new inner layout, to be able to later nicely
-        // print the field names of the enum field that is being accessed.
-        let (variant, dest) = match dest.layout.variants {
+        // If this is a multi-variant layout, we have find the right one and proceed with that.
+        // (No good reasoning to make this recursion, but it is equivalent to that.)
+        let dest = match dest.layout.variants {
             layout::Variants::NicheFilling { .. } |
             layout::Variants::Tagged { .. } => {
                 let variant = match self.read_discriminant(dest) {
@@ -237,124 +389,104 @@ pub fn validate_operand(
                             ),
                     }
                 };
-                let inner_dest = self.operand_downcast(dest, variant)?;
                 // Put the variant projection onto the path, as a field
                 path.push(PathElem::Field(dest.layout.ty
                                           .ty_adt_def()
                                           .unwrap()
                                           .variants[variant].name));
+                // Proceed with this variant
+                let dest = self.operand_downcast(dest, variant)?;
                 trace!("variant layout: {:#?}", dest.layout);
-                (variant, inner_dest)
+                dest
             },
-            layout::Variants::Single { index } => {
-                // Pre-processing for trait objects: Treat them at their real type.
-                // (We do not do this for slices and strings: For slices it is not needed,
-                // `mplace_array_fields` does the right thing, and for strings there is no
-                // real type that would show the actual length.)
-                let dest = match dest.layout.ty.sty {
-                    ty::Dynamic(..) => {
-                        let dest = dest.to_mem_place(); // immediate trait objects are not a thing
-                        match self.unpack_dyn_trait(dest) {
-                            Ok(res) => res.1.into(),
-                            Err(_) =>
-                                return validation_failure!(
-                                    "invalid vtable in fat pointer", path
-                                ),
-                        }
-                    }
-                    _ => dest
-                };
-                (index, dest)
-            }
+            layout::Variants::Single { .. } => dest,
         };
 
-        // Remember the length, in case we need to truncate
-        let path_len = path.len();
+        // First thing, find the real type:
+        // If it is a trait object, switch to the actual type that was used to create it.
+        let dest = match dest.layout.ty.sty {
+            ty::Dynamic(..) => {
+                let dest = dest.to_mem_place(); // immediate trait objects are not a thing
+                self.unpack_dyn_trait(dest)?.1.into()
+            },
+            _ => dest
+        };
 
-        // Validate all fields
-        match dest.layout.fields {
-            // primitives are unions with zero fields
-            // We still check `layout.fields`, not `layout.abi`, because `layout.abi`
-            // is `Scalar` for newtypes around scalars, but we want to descend through the
-            // fields to get a proper `path`.
-            layout::FieldPlacement::Union(0) => {
-                match dest.layout.abi {
-                    // nothing to do, whatever the pointer points to, it is never going to be read
-                    layout::Abi::Uninhabited =>
-                        return validation_failure!("a value of an uninhabited type", path),
-                    // check that the scalar is a valid pointer or that its bit range matches the
-                    // expectation.
-                    layout::Abi::Scalar(ref scalar_layout) => {
-                        let size = scalar_layout.value.size(self);
-                        let value = match self.read_value(dest) {
-                            Ok(val) => val,
-                            Err(err) => match err.kind {
-                                EvalErrorKind::PointerOutOfBounds { .. } |
-                                EvalErrorKind::ReadUndefBytes(_) =>
-                                    return validation_failure!(
-                                        "uninitialized or out-of-bounds memory", path
-                                    ),
-                                _ =>
-                                    return validation_failure!(
-                                        "unrepresentable data", path
-                                    ),
-                            }
-                        };
-                        let scalar = value.to_scalar_or_undef();
-                        self.validate_scalar(scalar, size, scalar_layout, &path, dest.layout.ty)?;
-                        if scalar_layout.value == Primitive::Pointer {
-                            // ignore integer pointers, we can't reason about the final hardware
-                            if let Scalar::Ptr(ptr) = scalar.not_undef()? {
-                                let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
-                                if let Some(AllocType::Static(did)) = alloc_kind {
-                                    // statics from other crates are already checked.
-                                    // extern statics cannot be validated as they have no body.
-                                    if !did.is_local() || self.tcx.is_foreign_item(did) {
-                                        return Ok(());
-                                    }
-                                }
-                                if value.layout.ty.builtin_deref(false).is_some() {
-                                    let ptr_op = self.ref_to_mplace(value)?.into();
-                                    // we have not encountered this pointer+layout combination
-                                    // before.
-                                    if seen.insert(ptr_op) {
-                                        trace!("Recursing below ptr {:#?}", *value);
-                                        todo.push((ptr_op, path_clone_and_deref(path)));
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", dest.layout.abi),
-                }
+        // If this is a scalar, validate the scalar layout.
+        // Things can be aggregates and have scalar layout at the same time, and that
+        // is very relevant for `NonNull` and similar structs: We need to validate them
+        // at their scalar layout *before* descending into their fields.
+        // FIXME: We could avoid some redundant checks here. For newtypes wrapping
+        // scalars, we do the same check on every "level" (e.g. first we check
+        // MyNewtype and then the scalar in there).
+        match dest.layout.abi {
+            layout::Abi::Uninhabited =>
+                return validation_failure!("a value of an uninhabited type", path),
+            layout::Abi::Scalar(ref layout) => {
+                let value = try_validation!(self.read_scalar(dest),
+                            "uninitialized or unrepresentable data", path);
+                self.validate_scalar_layout(value, dest.layout.size, &path, layout)?;
             }
-            layout::FieldPlacement::Union(_) => {
+            // FIXME: Should we do something for ScalarPair? Vector?
+            _ => {}
+        }
+
+        // Check primitive types.  We do this after checking the scalar layout,
+        // just to have that done as well.  Primitives can have varying layout,
+        // so we check them separately and before aggregate handling.
+        // It is CRITICAL that we get this check right, or we might be
+        // validating the wrong thing!
+        let primitive = match dest.layout.fields {
+            // Primitives appear as Union with 0 fields -- except for fat pointers.
+            layout::FieldPlacement::Union(0) => true,
+            _ => dest.layout.ty.builtin_deref(true).is_some(),
+        };
+        if primitive {
+            let value = try_validation!(self.read_value(dest),
+                "uninitialized or unrepresentable data", path);
+            return self.validate_primitive_type(
+                value,
+                &path,
+                ref_tracking,
+                const_mode,
+            );
+        }
+
+        // Validate all fields of compound data structures
+        let path_len = path.len(); // Remember the length, in case we need to truncate
+        match dest.layout.fields {
+            layout::FieldPlacement::Union(..) => {
                 // We can't check unions, their bits are allowed to be anything.
                 // The fields don't need to correspond to any bit pattern of the union's fields.
                 // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
             },
-            layout::FieldPlacement::Array { stride, .. } if !dest.layout.is_zst() => {
-                let dest = dest.to_mem_place(); // non-ZST array/slice/str cannot be immediate
+            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
+                // Go look at all the fields
+                for i in 0..offsets.len() {
+                    let field = self.operand_field(dest, i as u64)?;
+                    path.push(self.aggregate_field_path_elem(dest.layout, i));
+                    self.validate_operand(
+                        field,
+                        path,
+                        ref_tracking.as_mut().map(|r| &mut **r),
+                        const_mode,
+                    )?;
+                    path.truncate(path_len);
+                }
+            }
+            layout::FieldPlacement::Array { stride, .. } => {
+                let dest = if dest.layout.is_zst() {
+                    // it's a ZST, the memory content cannot matter
+                    MPlaceTy::dangling(dest.layout, self)
+                } else {
+                    // non-ZST array/slice/str cannot be immediate
+                    dest.to_mem_place()
+                };
                 match dest.layout.ty.sty {
                     // Special handling for strings to verify UTF-8
                     ty::Str => {
-                        match self.read_str(dest) {
-                            Ok(_) => {},
-                            Err(err) => match err.kind {
-                                EvalErrorKind::PointerOutOfBounds { .. } |
-                                EvalErrorKind::ReadUndefBytes(_) =>
-                                    // The error here looks slightly different than it does
-                                    // for slices, because we do not report the index into the
-                                    // str at which we are OOB.
-                                    return validation_failure!(
-                                        "uninitialized or out-of-bounds memory", path
-                                    ),
-                                _ =>
-                                    return validation_failure!(
-                                        "non-UTF-8 data in str", path
-                                    ),
-                            }
-                        }
+                        try_validation!(self.read_str(dest),
+                            "uninitialized or non-UTF-8 data in str", path);
                     }
                     // Special handling for arrays/slices of builtin integer types
                     ty::Array(tys, ..) | ty::Slice(tys) if {
@@ -390,18 +522,9 @@ pub fn validate_operand(
                                             "undefined bytes", path
                                         )
                                     },
-                                    EvalErrorKind::PointerOutOfBounds { allocation_size, .. } => {
-                                        // If the array access is out-of-bounds, the first
-                                        // undefined access is the after the end of the array.
-                                        let i = (allocation_size.bytes() * ty_size) as usize;
-                                        path.push(PathElem::ArrayElem(i));
-                                    },
-                                    _ => (),
+                                    // Other errors shouldn't be possible
+                                    _ => return Err(err),
                                 }
-
-                                return validation_failure!(
-                                    "uninitialized or out-of-bounds memory", path
-                                )
                             }
                         }
                     },
@@ -411,83 +534,32 @@ pub fn validate_operand(
                         for (i, field) in self.mplace_array_fields(dest)?.enumerate() {
                             let field = field?;
                             path.push(PathElem::ArrayElem(i));
-                            self.validate_operand(field.into(), path, seen, todo)?;
+                            self.validate_operand(
+                                field.into(),
+                                path,
+                                ref_tracking.as_mut().map(|r| &mut **r),
+                                const_mode,
+                            )?;
                             path.truncate(path_len);
                         }
                     }
                 }
             },
-            layout::FieldPlacement::Array { .. } => {
-                // An empty array.  Nothing to do.
-            }
-            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
-                // Fat pointers are treated like pointers, not aggregates.
-                if dest.layout.ty.builtin_deref(true).is_some() {
-                    // This is a fat pointer.
-                    let ptr = match self.read_value(dest.into())
-                        .and_then(|val| self.ref_to_mplace(val))
-                    {
-                        Ok(ptr) => ptr,
-                        Err(_) =>
-                            return validation_failure!(
-                                "undefined location or metadata in fat pointer", path
-                            ),
-                    };
-                    // check metadata early, for better diagnostics
-                    match self.tcx.struct_tail(ptr.layout.ty).sty {
-                        ty::Dynamic(..) => {
-                            match ptr.extra.unwrap().to_ptr() {
-                                Ok(_) => {},
-                                Err(_) =>
-                                    return validation_failure!(
-                                        "non-pointer vtable in fat pointer", path
-                                    ),
-                            }
-                            // FIXME: More checks for the vtable.
-                        }
-                        ty::Slice(..) | ty::Str => {
-                            match ptr.extra.unwrap().to_usize(self) {
-                                Ok(_) => {},
-                                Err(_) =>
-                                    return validation_failure!(
-                                        "non-integer slice length in fat pointer", path
-                                    ),
-                            }
-                        }
-                        _ =>
-                            bug!("Unexpected unsized type tail: {:?}",
-                                self.tcx.struct_tail(ptr.layout.ty)
-                            ),
-                    }
-                    // for safe ptrs, recursively check it
-                    if !dest.layout.ty.is_unsafe_ptr() {
-                        let ptr = ptr.into();
-                        if seen.insert(ptr) {
-                            trace!("Recursing below fat ptr {:?}", ptr);
-                            todo.push((ptr, path_clone_and_deref(path)));
-                        }
-                    }
-                } else {
-                    // Not a pointer, perform regular aggregate handling below
-                    for i in 0..offsets.len() {
-                        let field = self.operand_field(dest, i as u64)?;
-                        path.push(self.aggregate_field_path_elem(dest.layout.ty, variant, i));
-                        self.validate_operand(field, path, seen, todo)?;
-                        path.truncate(path_len);
-                    }
-                }
-            }
         }
         Ok(())
     }
 
-    fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize) -> PathElem {
-        match ty.sty {
+    fn aggregate_field_path_elem(&self, layout: TyLayout<'tcx>, field: usize) -> PathElem {
+        match layout.ty.sty {
             // generators and closures.
             ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
-                let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
-                let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
-                PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
+                if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                    let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
+                    PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
+                } else {
+                    // The closure is not local, so we cannot get the name
+                    PathElem::ClosureVar(Symbol::intern(&field.to_string()))
+                }
             }
 
             // tuples
@@ -495,7 +567,10 @@ fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize)
 
             // enums
             ty::Adt(def, ..) if def.is_enum() => {
-                let variant = &def.variants[variant];
+                let variant = match layout.variants {
+                    layout::Variants::Single { index } => &def.variants[index],
+                    _ => bug!("aggregate_field_path_elem: got enum but not in a specific variant"),
+                };
                 PathElem::Field(variant.fields[field].ident.name)
             }
 
@@ -503,7 +578,7 @@ fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize)
             ty::Adt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].ident.name),
 
             // nothing else has an aggregate layout
-            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", ty),
+            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
         }
     }
 }
index b2fa83493849cf37f2dad731c8e11cadd67a59ba..29f167629441b964f2a2090649eb64a15eadc561 100644 (file)
@@ -1163,7 +1163,7 @@ fn collect_miri<'a, 'tcx>(
         }
         Some(AllocType::Memory(alloc)) => {
             trace!("collecting {:?} with {:#?}", alloc_id, alloc);
-            for &inner in alloc.relocations.values() {
+            for &((), inner) in alloc.relocations.values() {
                 collect_miri(tcx, inner, output);
             }
         },
@@ -1272,7 +1272,7 @@ fn collect_const<'a, 'tcx>(
         ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
         ConstValue::ByRef(_id, alloc, _offset) => {
-            for &id in alloc.relocations.values() {
+            for &((), id) in alloc.relocations.values() {
                 collect_miri(tcx, id, output);
             }
         }
index 70d50d589d1a041b1e24d827e70fffa07c3187b9..626baf207eebc0aa4871168e4a0a98fb0a6dbccc 100644 (file)
@@ -154,6 +154,7 @@ fn use_ecx<F, T>(
                     // FIXME: figure out the rules and start linting
                     | FunctionAbiMismatch(..)
                     | FunctionArgMismatch(..)
+                    | FunctionRetMismatch(..)
                     | FunctionArgCountMismatch
                     // fine at runtime, might be a register address or sth
                     | ReadBytesAsPointer
index 93d61b80847ecb876a10191d554f6f4503a9ac02..10ba27e38f47c7dc0e1662310dcb27648b678e51 100644 (file)
@@ -22,7 +22,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
-#![feature(min_const_fn)]
+#![cfg_attr(stage0, feature(min_const_fn))]
 #![feature(nll)]
 #![feature(slice_patterns)]
 
index 3f1e8ee55286b6bfd682894aa3bbbc5e29c9cb13..9c0f945326d148006c8f9cd54e7412d4ea9d92eb 100644 (file)
@@ -576,6 +576,9 @@ pub struct TargetOptions {
     /// the functions in the executable are not randomized and can be used
     /// during an exploit of a vulnerability in any code.
     pub position_independent_executables: bool,
+    /// Determines if the target always requires using the PLT for indirect
+    /// library calls or not. This controls the default value of the `-Z plt` flag.
+    pub needs_plt: bool,
     /// Either partial, full, or off. Full RELRO makes the dynamic linker
     /// resolve all symbols at startup and marks the GOT read-only before
     /// starting the program, preventing overwriting the GOT.
@@ -720,6 +723,7 @@ fn default() -> TargetOptions {
             has_rpath: false,
             no_default_libraries: true,
             position_independent_executables: false,
+            needs_plt: false,
             relro_level: RelroLevel::None,
             pre_link_objects_exe: Vec::new(),
             pre_link_objects_exe_crt: Vec::new(),
@@ -1009,6 +1013,7 @@ macro_rules! key {
         key!(has_rpath, bool);
         key!(no_default_libraries, bool);
         key!(position_independent_executables, bool);
+        key!(needs_plt, bool);
         try!(key!(relro_level, RelroLevel));
         key!(archive_format);
         key!(allow_asm, bool);
@@ -1217,6 +1222,7 @@ macro_rules! target_option_val {
         target_option_val!(has_rpath);
         target_option_val!(no_default_libraries);
         target_option_val!(position_independent_executables);
+        target_option_val!(needs_plt);
         target_option_val!(relro_level);
         target_option_val!(archive_format);
         target_option_val!(allow_asm);
index 72b5bd27c7dfe3b35f1069e0fdb87362bd87eb3f..fd61067ba5168cdd575c6ef826d11ef3e34b8ad0 100644 (file)
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
     base.stack_probes = true;
     base.has_elf_tls = false;
+    // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
+    // breaks code gen. See LLVM bug 36743
+    base.needs_plt = true;
 
     Ok(Target {
         llvm_target: "x86_64-unknown-linux-gnux32".to_string(),
index cd21ee601a7d2d47ffe0204b78cdfaac12bbb4a5..16f0f11757a1278661d0e67be407d28fd1eed9ca 100644 (file)
@@ -16,5 +16,5 @@ rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-chalk-engine = { version = "0.7.0", default-features=false }
+chalk-engine = { version = "0.8.0", default-features=false }
 smallvec = { version = "0.6.5", features = ["union"] }
index 4c28df97bdf50a5024907237b2699463f6ca45b0..dea3aa4372a332f6252cd7be466fa29edbfea7ed 100644 (file)
@@ -19,6 +19,7 @@
     ExClauseFold,
     ExClauseLift,
     Goal,
+    GoalKind,
     ProgramClause,
     QuantifierKind
 };
@@ -92,7 +93,7 @@ impl context::Context for ChalkArenas<'tcx> {
 
     type DomainGoal = DomainGoal<'tcx>;
 
-    type BindersGoal = ty::Binder<&'tcx Goal<'tcx>>;
+    type BindersGoal = ty::Binder<Goal<'tcx>>;
 
     type Parameter = Kind<'tcx>;
 
@@ -102,14 +103,6 @@ impl context::Context for ChalkArenas<'tcx> {
 
     type UnificationResult = InferOk<'tcx, ()>;
 
-    fn into_goal(domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
-        Goal::DomainGoal(domain_goal)
-    }
-
-    fn cannot_prove() -> Goal<'tcx> {
-        Goal::CannotProve
-    }
-
     fn goal_in_environment(
         env: &ty::ParamEnv<'tcx>,
         goal: Goal<'tcx>,
@@ -251,15 +244,23 @@ fn map_subst_from_canonical(
 impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
     for ChalkInferenceContext<'cx, 'gcx, 'tcx>
 {
+    fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
+        self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+    }
+
+    fn cannot_prove(&self) -> Goal<'tcx> {
+        self.infcx.tcx.mk_goal(GoalKind::CannotProve)
+    }
+
     fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
-        match goal {
-            Goal::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
-            Goal::And(left, right) => HhGoal::And(*left, *right),
-            Goal::Not(subgoal) => HhGoal::Not(*subgoal),
-            Goal::DomainGoal(d) => HhGoal::DomainGoal(d),
-            Goal::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
-            Goal::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
-            Goal::CannotProve => HhGoal::CannotProve,
+        match *goal {
+            GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
+            GoalKind::And(left, right) => HhGoal::And(left, right),
+            GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
+            GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
+            GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
+            GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
+            GoalKind::CannotProve => HhGoal::CannotProve,
         }
     }
 
@@ -363,21 +364,21 @@ fn program_clauses(
 
     fn instantiate_binders_universally(
         &mut self,
-        _arg: &ty::Binder<&'tcx Goal<'tcx>>,
+        _arg: &ty::Binder<Goal<'tcx>>,
     ) -> Goal<'tcx> {
         panic!("FIXME -- universal instantiation needs sgrif's branch")
     }
 
     fn instantiate_binders_existentially(
         &mut self,
-        arg: &ty::Binder<&'tcx Goal<'tcx>>,
+        arg: &ty::Binder<Goal<'tcx>>,
     ) -> Goal<'tcx> {
         let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var(
             DUMMY_SP,
             LateBoundRegionConversionTime::HigherRankedType,
             arg,
         );
-        *value
+        value
     }
 
     fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
index ad724babe49fb69aa7e4e7f426876df7f21650a0..181106d3f84bf19f9b4f371ff65edd1476ae162d 100644 (file)
 use rustc::hir::map::definitions::DefPathData;
 use rustc::hir::{self, ImplPolarity};
 use rustc::traits::{
-    Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed,
+    Clause,
+    Clauses,
+    DomainGoal,
+    FromEnv,
+    GoalKind,
+    PolyDomainGoal,
+    ProgramClause,
+    WellFormed,
     WhereClause,
 };
 use rustc::ty::query::Providers;
@@ -249,7 +256,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
     let impl_trait: DomainGoal = trait_pred.lower();
 
     // `FromEnv(Self: Trait<P1..Pn>)`
-    let from_env_goal = impl_trait.into_from_env_goal().into_goal();
+    let from_env_goal = tcx.mk_goal(impl_trait.into_from_env_goal().into_goal());
     let hypotheses = tcx.intern_goals(&[from_env_goal]);
 
     // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
@@ -308,7 +315,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
     let wf_clause = ProgramClause {
         goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)),
         hypotheses: tcx.mk_goals(
-            wf_conditions.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
+            wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
         ),
     };
     let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause)));
@@ -352,10 +359,10 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
         hypotheses: tcx.mk_goals(
             where_clauses
                 .into_iter()
-                .map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
+                .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
         ),
     };
-    tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
+    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
 }
 
 pub fn program_clauses_for_type_def<'a, 'tcx>(
@@ -388,7 +395,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
             where_clauses
                 .iter()
                 .cloned()
-                .map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
+                .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
         ),
     };
 
@@ -404,7 +411,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
     // ```
 
     // `FromEnv(Ty<...>)`
-    let from_env_goal = DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal();
+    let from_env_goal = tcx.mk_goal(DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal());
     let hypotheses = tcx.intern_goals(&[from_env_goal]);
 
     // For each where clause `WC`:
@@ -423,10 +430,86 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
 }
 
 pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
-    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    _item_id: DefId,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    item_id: DefId,
 ) -> Clauses<'tcx> {
-    unimplemented!()
+    // Rule ProjectionEq-Skolemize
+    //
+    // ```
+    // trait Trait<P1..Pn> {
+    //     type AssocType<Pn+1..Pm>;
+    // }
+    // ```
+    //
+    // `ProjectionEq` can succeed by skolemizing, see "associated type"
+    // chapter for more:
+    // ```
+    // forall<Self, P1..Pn, Pn+1..Pm> {
+    //     ProjectionEq(
+    //         <Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> =
+    //         (Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>
+    //     )
+    // }
+    // ```
+
+    let item = tcx.associated_item(item_id);
+    debug_assert_eq!(item.kind, ty::AssociatedKind::Type);
+    let trait_id = match item.container {
+        ty::AssociatedItemContainer::TraitContainer(trait_id) => trait_id,
+        _ => bug!("not an trait container"),
+    };
+    let trait_ref = ty::TraitRef::identity(tcx, trait_id);
+
+    let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
+    let placeholder_ty = tcx.mk_ty(ty::UnnormalizedProjection(projection_ty));
+    let projection_eq = WhereClause::ProjectionEq(ty::ProjectionPredicate {
+        projection_ty,
+        ty: placeholder_ty,
+    });
+
+    let projection_eq_clause = ProgramClause {
+        goal: DomainGoal::Holds(projection_eq),
+        hypotheses: &ty::List::empty(),
+    };
+
+    // Rule WellFormed-AssocTy
+    // ```
+    // forall<Self, P1..Pn, Pn+1..Pm> {
+    //     WellFormed((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
+    //         :- Implemented(Self: Trait<P1..Pn>)
+    // }
+    // ```
+
+    let trait_predicate = ty::TraitPredicate { trait_ref };
+    let hypothesis = tcx.mk_goal(
+        DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
+    );
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
+        hypotheses: tcx.mk_goals(iter::once(hypothesis)),
+    };
+
+    // Rule Implied-Trait-From-AssocTy
+    // ```
+    // forall<Self, P1..Pn, Pn+1..Pm> {
+    //     FromEnv(Self: Trait<P1..Pn>)
+    //         :- FromEnv((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
+    // }
+    // ```
+
+    let hypothesis = tcx.mk_goal(
+        DomainGoal::FromEnv(FromEnv::Ty(placeholder_ty)).into_goal()
+    );
+    let from_env_clause = ProgramClause {
+        goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)),
+        hypotheses: tcx.mk_goals(iter::once(hypothesis)),
+    };
+
+    let clauses = iter::once(projection_eq_clause)
+        .chain(iter::once(wf_clause))
+        .chain(iter::once(from_env_clause));
+    let clauses = clauses.map(|clause| Clause::ForAll(ty::Binder::dummy(clause)));
+    tcx.mk_clauses(clauses)
 }
 
 pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
@@ -435,10 +518,11 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
 ) -> Clauses<'tcx> {
     // Rule Normalize-From-Impl (see rustc guide)
     //
-    // ```impl<P0..Pn> Trait<A1..An> for A0
-    // {
+    // ```
+    // impl<P0..Pn> Trait<A1..An> for A0 {
     //     type AssocType<Pn+1..Pm> = T;
-    // }```
+    // }
+    // ```
     //
     // FIXME: For the moment, we don't account for where clauses written on the associated
     // ty definition (i.e. in the trait def, as in `type AssocType<T> where T: Sized`).
@@ -482,10 +566,10 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
         hypotheses: tcx.mk_goals(
             hypotheses
                 .into_iter()
-                .map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
+                .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
         ),
     };
-    tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
+    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
 }
 
 pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
index 28d2ae413de6d2375694cdf125c28ac7f9c8a2f5..e4ad02595d107df0f8f0499283db6f0dfa3ca042 100644 (file)
@@ -402,21 +402,44 @@ fn check_generic_arg_count(
     }
 
     /// Creates the relevant generic argument substitutions
-    /// corresponding to a set of generic parameters.
-    pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
+    /// corresponding to a set of generic parameters. This is a
+    /// rather complex little function. Let me try to explain the
+    /// role of each of its parameters:
+    ///
+    /// To start, we are given the `def_id` of the thing we are
+    /// creating the substitutions for, and a partial set of
+    /// substitutions `parent_substs`. In general, the substitutions
+    /// for an item begin with substitutions for all the "parents" of
+    /// that item -- so e.g. for a method it might include the
+    /// parameters from the impl.
+    ///
+    /// Therefore, the method begins by walking down these parents,
+    /// starting with the outermost parent and proceed inwards until
+    /// it reaches `def_id`. For each parent P, it will check `parent_substs`
+    /// first to see if the parent's substitutions are listed in there. If so,
+    /// we can append those and move on. Otherwise, it invokes the
+    /// three callback functions:
+    ///
+    /// - `args_for_def_id`: given the def-id P, supplies back the
+    ///   generic arguments that were given to that parent from within
+    ///   the path; so e.g. if you have `<T as Foo>::Bar`, the def-id
+    ///   might refer to the trait `Foo`, and the arguments might be
+    ///   `[T]`. The boolean value indicates whether to infer values
+    ///   for arguments whose values were not explicitly provided.
+    /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
+    ///   instantiate a `Kind`
+    /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
+    ///   creates a suitable inference variable.
+    pub fn create_substs_for_generic_args<'a, 'b>(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
         def_id: DefId,
         parent_substs: &[Kind<'tcx>],
         has_self: bool,
         self_ty: Option<Ty<'tcx>>,
-        args_for_def_id: A,
-        provided_kind: P,
-        inferred_kind: I,
-    ) -> &'tcx Substs<'tcx> where
-        A: Fn(DefId) -> (Option<&'b GenericArgs>, bool),
-        P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
-        I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>
-    {
+        args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs>, bool),
+        provided_kind: impl Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
+        inferred_kind: impl Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>,
+    ) -> &'tcx Substs<'tcx> {
         // Collect the segments of the path: we need to substitute arguments
         // for parameters throughout the entire path (wherever there are
         // generic parameters).
index 71c78e7f87c07613f09eb5537faa668ffb2074d2..85b6bcbd144fc7a8debf1e8d8444b1efdcb94f81 100644 (file)
@@ -309,11 +309,20 @@ pub fn check_ref(&self,
                 };
                 if self.can_coerce(ref_ty, expected) {
                     if let Ok(src) = cm.span_to_snippet(sp) {
-                        let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756)
+                        let needs_parens = match expr.node {
+                            // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) |
-                            hir::ExprKind::Binary(_, _, _) => format!("({})", src),
-                            _ => src,
+                            hir::ExprKind::Binary(_, _, _) => true,
+                            // parenthesize borrows of range literals (Issue #54505)
+                            _ if self.is_range_literal(expr) => true,
+                            _ => false,
                         };
+                        let sugg_expr = if needs_parens {
+                            format!("({})", src)
+                        } else {
+                            src
+                        };
+
                         if let Some(sugg) = self.can_use_as_ref(expr) {
                             return Some(sugg);
                         }
@@ -374,6 +383,66 @@ pub fn check_ref(&self,
         None
     }
 
+    /// This function checks if the specified expression is a built-in range literal.
+    /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`).
+    fn is_range_literal(&self, expr: &hir::Expr) -> bool {
+        use hir::{Path, QPath, ExprKind, TyKind};
+
+        // We support `::std::ops::Range` and `::core::ops::Range` prefixes
+        let is_range_path = |path: &Path| {
+            let mut segs = path.segments.iter()
+                .map(|seg| seg.ident.as_str());
+
+            if let (Some(root), Some(std_core), Some(ops), Some(range), None) =
+                (segs.next(), segs.next(), segs.next(), segs.next(), segs.next())
+            {
+                // "{{root}}" is the equivalent of `::` prefix in Path
+                root == "{{root}}" && (std_core == "std" || std_core == "core")
+                    && ops == "ops" && range.starts_with("Range")
+            } else {
+                false
+            }
+        };
+
+        let span_is_range_literal = |span: &Span| {
+            // Check whether a span corresponding to a range expression
+            // is a range literal, rather than an explicit struct or `new()` call.
+            let source_map = self.tcx.sess.source_map();
+            let end_point = source_map.end_point(*span);
+
+            if let Ok(end_string) = source_map.span_to_snippet(end_point) {
+                !(end_string.ends_with("}") || end_string.ends_with(")"))
+            } else {
+                false
+            }
+        };
+
+        match expr.node {
+            // All built-in range literals but `..=` and `..` desugar to Structs
+            ExprKind::Struct(QPath::Resolved(None, ref path), _, _) |
+            // `..` desugars to its struct path
+            ExprKind::Path(QPath::Resolved(None, ref path)) => {
+                return is_range_path(&path) && span_is_range_literal(&expr.span);
+            }
+
+            // `..=` desugars into `::std::ops::RangeInclusive::new(...)`
+            ExprKind::Call(ref func, _) => {
+                if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node {
+                    if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node {
+                        let call_to_new = segment.ident.as_str() == "new";
+
+                        return is_range_path(&path) && span_is_range_literal(&expr.span)
+                            && call_to_new;
+                    }
+                }
+            }
+
+            _ => {}
+        }
+
+        false
+    }
+
     pub fn check_for_cast(&self,
                       err: &mut DiagnosticBuilder<'tcx>,
                       expr: &hir::Expr,
index 529f1e6161be987dd9a429d0c9d173f8066b9a5b..be8b16dd2f577ca2deb5e1ccda5259434b3fc835 100644 (file)
@@ -2164,6 +2164,13 @@ pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
     /// occurred**, so that annotations like `Vec<_>` are preserved
     /// properly.
     pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
+        debug!(
+            "write_user_substs_from_substs({:?}, {:?}) in fcx {}",
+            hir_id,
+            substs,
+            self.tag(),
+        );
+
         if !substs.is_noop() {
             let user_substs = self.infcx.canonicalize_response(&substs);
             debug!("instantiate_value_path: user_substs = {:?}", user_substs);
@@ -3752,6 +3759,13 @@ fn check_expr_kind(
         expected: Expectation<'tcx>,
         needs: Needs
     ) -> Ty<'tcx> {
+        debug!(
+            "check_expr_kind(expr={:?}, expected={:?}, needs={:?})",
+            expr,
+            expected,
+            needs,
+        );
+
         let tcx = self.tcx;
         let id = expr.id;
         match expr.node {
@@ -4981,10 +4995,13 @@ pub fn instantiate_value_path(&self,
                                   span: Span,
                                   node_id: ast::NodeId)
                                   -> (Ty<'tcx>, Def) {
-        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
-               segments,
-               def,
-               node_id);
+        debug!(
+            "instantiate_value_path(segments={:?}, self_ty={:?}, def={:?}, node_id={})",
+            segments,
+            self_ty,
+            def,
+            node_id,
+        );
 
         let path_segs = self.def_ids_for_path_segments(segments, def);
 
@@ -5194,6 +5211,11 @@ pub fn instantiate_value_path(&self,
         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
         self.write_substs(hir_id, substs);
 
+        debug!(
+            "instantiate_value_path: id={:?} substs={:?}",
+            node_id,
+            substs,
+        );
         self.write_user_substs_from_substs(hir_id, substs);
 
         (ty_substituted, new_def)
index 845bfad7807d32734be3695cd9af68e3221b66d6..8bac007b748ac20a6376f2ceb58f0e41f5d04922 100644 (file)
@@ -9,6 +9,6 @@ path = "lib.rs"
 
 [dependencies]
 pulldown-cmark = { version = "0.1.2", default-features = false }
-minifier = "0.0.19"
+minifier = "0.0.20"
 tempfile = "3"
 parking_lot = "0.6.4"
index 5df4862290e3c0d990e980320e3d85570a5c1495..87b4527a2a73946629e53bd4ecf5e6b1f81d702b 100644 (file)
@@ -44,9 +44,21 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>,
     }
     write_header(class, &mut out).unwrap();
 
-    let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None),
-                                         sess.source_map());
+    let lexer = match lexer::StringReader::new_without_err(&sess, fm, None, "Output from rustc:") {
+        Ok(l) => l,
+        Err(_) => {
+            let first_line = src.lines().next().unwrap_or_else(|| "");
+            let mut err = sess.span_diagnostic
+                              .struct_warn(&format!("Invalid doc comment starting with: `{}`\n\
+                                                     (Ignoring this codeblock)",
+                                                    first_line));
+            err.emit();
+            return String::new();
+        }
+    };
+    let mut classifier = Classifier::new(lexer, sess.source_map());
     if classifier.write_source(&mut out).is_err() {
+        classifier.lexer.emit_fatal_errors();
         return format!("<pre>{}</pre>", src);
     }
 
@@ -162,11 +174,10 @@ fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
         match self.lexer.try_next_token() {
             Ok(tas) => Ok(tas),
             Err(_) => {
-                self.lexer.emit_fatal_errors();
-                self.lexer.sess.span_diagnostic
-                    .struct_warn("Backing out of syntax highlighting")
-                    .note("You probably did not intend to render this as a rust code-block")
-                    .emit();
+                let mut err = self.lexer.sess.span_diagnostic
+                                  .struct_warn("Backing out of syntax highlighting");
+                err.note("You probably did not intend to render this as a rust code-block");
+                err.emit();
                 Err(io::Error::new(io::ErrorKind::Other, ""))
             }
         }
index 1c61e73fae03cdd0f8346bee6244c05bfd517256..23f1e15de3c925c7c8acb3bebf9a68c2d840f875 100644 (file)
@@ -4098,12 +4098,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                         </div>",
                        version)?;
             }
+        }
 
+        write!(fmt, "<div class=\"sidebar-elems\">")?;
+        if it.is_crate() {
             write!(fmt, "<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
                    it.name.as_ref().expect("crates always have a name"))?;
         }
-
-        write!(fmt, "<div class=\"sidebar-elems\">")?;
         match it.inner {
             clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?,
             clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?,
index 58ac46d22717bc7dd0af46b28d11b7335a5ce9f1..91ff03a327df4b1c78d4f866eaf4c228dfae99dc 100644 (file)
@@ -908,10 +908,9 @@ span.since {
                padding-top: 0px;
        }
 
-       .sidebar {
+       body > .sidebar {
                height: 45px;
                min-height: 40px;
-               width: calc(100% + 30px);
                margin: 0;
                margin-left: -15px;
                padding: 0 15px;
@@ -1013,6 +1012,10 @@ span.since {
        .anchor {
                display: none !important;
        }
+
+       h1.fqn {
+               overflow: initial;
+       }
 }
 
 @media print {
@@ -1112,6 +1115,18 @@ h4 > .important-traits {
        top: 2px;
 }
 
+#all-types {
+       text-align: center;
+       border: 1px solid;
+       margin: 0 10px;
+       margin-bottom: 10px;
+       display: block;
+       border-radius: 7px;
+}
+#all-types > p {
+       margin: 5px 0;
+}
+
 @media (max-width: 700px) {
        h4 > .important-traits {
                position: absolute;
@@ -1135,6 +1150,9 @@ h4 > .important-traits {
                background-color: rgba(0,0,0,0);
                height: 100%;
        }
+       .sidebar {
+               width: calc(100% + 30px);
+       }
 
        .show-it {
                display: block;
@@ -1180,6 +1198,10 @@ h4 > .important-traits {
        .impl > .collapse-toggle {
                left: -10px;
        }
+
+       #all-types {
+               margin: 10px;
+       }
 }
 
 
@@ -1383,17 +1405,6 @@ kbd {
 #main > ul > li {
        list-style: none;
 }
-#all-types {
-       text-align: center;
-       border: 1px solid;
-       margin: 0 10px;
-       margin-bottom: 10px;
-       display: block;
-       border-radius: 7px;
-}
-#all-types > p {
-       margin: 5px 0;
-}
 
 .non-exhaustive {
        margin-bottom: 1em;
index 3e50988a68ba2e13fa34e29e17e3f902f6abfbaf..386de080b85f6d98b5312f43f1c371bf070aa1ab 100644 (file)
@@ -212,6 +212,19 @@ fn as_str(&self) -> &'static str {
 /// the heap (for normal construction via Error::new) is too costly.
 #[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
 impl From<ErrorKind> for Error {
+    /// Converts an [`ErrorKind`] into an [`Error`].
+    ///
+    /// This conversion allocates a new error with a simple representation of error kind.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{Error, ErrorKind};
+    ///
+    /// let not_found = ErrorKind::NotFound;
+    /// let error = Error::from(not_found);
+    /// assert_eq!("entity not found", format!("{}", error));
+    /// ```
     #[inline]
     fn from(kind: ErrorKind) -> Error {
         Error {
index c58bd364cedaba7857e9f607aedc464bcff11bab..a4db879680566d2a98634e675052e5ba52312b95 100644 (file)
 #![feature(cfg_target_vendor)]
 #![feature(char_error_internals)]
 #![feature(compiler_builtins_lib)]
-#![feature(min_const_fn)]
+#![cfg_attr(stage0, feature(min_const_fn))]
 #![feature(const_int_ops)]
 #![feature(const_ip)]
 #![feature(const_raw_ptr_deref)]
index 8d54728a75f42ff3e93918feeda1bf9c596e00c3..3b432d05132095adc8206d36e022275c51ebb321 100644 (file)
@@ -908,11 +908,36 @@ mod prim_usize { }
 /// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
 /// references with longer lifetimes can be freely coerced into references with shorter ones.
 ///
+/// Reference equality by address, instead of comparing the values pointed to, is accomplished via
+/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while
+/// [`PartialEq`] compares values.
+///
+/// [`ptr::eq`]: ptr/fn.eq.html
+/// [`PartialEq`]: cmp/trait.PartialEq.html
+///
+/// ```
+/// use std::ptr;
+///
+/// let five = 5;
+/// let other_five = 5;
+/// let five_ref = &five;
+/// let same_five_ref = &five;
+/// let other_five_ref = &other_five;
+///
+/// assert!(five_ref == same_five_ref);
+/// assert!(five_ref == other_five_ref);
+///
+/// assert!(ptr::eq(five_ref, same_five_ref));
+/// assert!(!ptr::eq(five_ref, other_five_ref));
+/// ```
+///
 /// For more information on how to use references, see [the book's section on "References and
 /// Borrowing"][book-refs].
 ///
 /// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html
 ///
+/// # Trait implementations
+///
 /// The following traits are implemented for all `&T`, regardless of the type of its referent:
 ///
 /// * [`Copy`]
index 3987ae83866e5c472fe6cebb13f1730c4e7d3768..c8d54a63946a94751c67795ed100409df5af36c8 100644 (file)
@@ -576,7 +576,7 @@ pub fn current() -> Thread {
 /// Thus the pattern of `yield`ing after a failed poll is rather common when
 /// implementing low-level shared resources or synchronization primitives.
 ///
-/// However programmers will usually prefer to use, [`channel`]s, [`Condvar`]s,
+/// However programmers will usually prefer to use [`channel`]s, [`Condvar`]s,
 /// [`Mutex`]es or [`join`] for their synchronization routines, as they avoid
 /// thinking about thread scheduling.
 ///
index f1cec422420ed87819f56816d77e7d72760f198b..1cc2e62a9c600e743710f209587f74ef1ebec371 100644 (file)
@@ -107,8 +107,7 @@ pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
     pub rustc_depr: Option<RustcDeprecation>,
-    /// `None` means the function is stable but needs to be allowed by the
-    /// `min_const_fn` feature
+    /// `None` means the function is stable but needs to be a stable const fn, too
     /// `Some` contains the feature gate required to be able to use the function
     /// as const fn
     pub const_stability: Option<Symbol>,
index a9ce23655777956dd32592f668dfb7e6307eccb8..e611eb86dc1b3214eb5637d5acb685f4a33881e2 100644 (file)
@@ -9,7 +9,14 @@
 // except according to those terms.
 
 use attr::HasAttrs;
-use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue};
+use feature_gate::{
+    feature_err,
+    EXPLAIN_STMT_ATTR_SYNTAX,
+    Features,
+    get_features,
+    GateIssue,
+    emit_feature_err,
+};
 use {fold, attr};
 use ast;
 use source_map::Spanned;
@@ -73,49 +80,103 @@ pub fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
         if self.in_cfg(node.attrs()) { Some(node) } else { None }
     }
 
+    /// Parse and expand all `cfg_attr` attributes into a list of attributes
+    /// that are within each `cfg_attr` that has a true configuration predicate.
+    ///
+    /// Gives compiler warnigns if any `cfg_attr` does not contain any
+    /// attributes and is in the original source code. Gives compiler errors if
+    /// the syntax of any `cfg_attr` is incorrect.
     pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: T) -> T {
         node.map_attrs(|attrs| {
-            attrs.into_iter().filter_map(|attr| self.process_cfg_attr(attr)).collect()
+            attrs.into_iter().flat_map(|attr| self.process_cfg_attr(attr)).collect()
         })
     }
 
-    fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
+    /// Parse and expand a single `cfg_attr` attribute into a list of attributes
+    /// when the configuration predicate is true, or otherwise expand into an
+    /// empty list of attributes.
+    ///
+    /// Gives a compiler warning when the `cfg_attr` contains no attribtes and
+    /// is in the original source file. Gives a compiler error if the syntax of
+    /// the attribute is incorrect
+    fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
         if !attr.check_name("cfg_attr") {
-            return Some(attr);
+            return vec![attr];
         }
 
-        let (cfg, path, tokens, span) = match attr.parse(self.sess, |parser| {
+        let gate_cfg_attr_multi = if let Some(ref features) = self.features {
+            !features.cfg_attr_multi
+        } else {
+            false
+        };
+        let cfg_attr_span = attr.span;
+
+        let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| {
             parser.expect(&token::OpenDelim(token::Paren))?;
-            let cfg = parser.parse_meta_item()?;
+
+            let cfg_predicate = parser.parse_meta_item()?;
             parser.expect(&token::Comma)?;
-            let lo = parser.span.lo();
-            let (path, tokens) = parser.parse_meta_item_unrestricted()?;
-            parser.eat(&token::Comma); // Optional trailing comma
+
+            // Presumably, the majority of the time there will only be one attr.
+            let mut expanded_attrs = Vec::with_capacity(1);
+
+            while !parser.check(&token::CloseDelim(token::Paren)) {
+                let lo = parser.span.lo();
+                let (path, tokens) = parser.parse_meta_item_unrestricted()?;
+                expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo)));
+                parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
+            }
+
             parser.expect(&token::CloseDelim(token::Paren))?;
-            Ok((cfg, path, tokens, parser.prev_span.with_lo(lo)))
+            Ok((cfg_predicate, expanded_attrs))
         }) {
             Ok(result) => result,
             Err(mut e) => {
                 e.emit();
-                return None;
+                return Vec::new();
             }
         };
 
-        if attr::cfg_matches(&cfg, self.sess, self.features) {
-            self.process_cfg_attr(ast::Attribute {
+        // Check feature gate and lint on zero attributes in source. Even if the feature is gated,
+        // we still compute as if it wasn't, since the emitted error will stop compilation futher
+        // along the compilation.
+        match (expanded_attrs.len(), gate_cfg_attr_multi) {
+            (0, false) => {
+                // FIXME: Emit unused attribute lint here.
+            },
+            (1, _) => {},
+            (_, true) => {
+                emit_feature_err(
+                    self.sess,
+                    "cfg_attr_multi",
+                    cfg_attr_span,
+                    GateIssue::Language,
+                    "cfg_attr with zero or more than one attributes is experimental",
+                );
+            },
+            (_, false) => {}
+        }
+
+        if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+            // We call `process_cfg_attr` recursively in case there's a
+            // `cfg_attr` inside of another `cfg_attr`. E.g.
+            //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
+            expanded_attrs.into_iter()
+            .flat_map(|(path, tokens, span)| self.process_cfg_attr(ast::Attribute {
                 id: attr::mk_attr_id(),
                 style: attr.style,
                 path,
                 tokens,
                 is_sugared_doc: false,
                 span,
-            })
+            }))
+            .collect()
         } else {
-            None
+            Vec::new()
         }
     }
 
-    // Determine if a node with the given attributes should be included in this configuration.
+    /// 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| {
             if !is_cfg(attr) {
@@ -165,7 +226,7 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
         })
     }
 
-    // Visit attributes on expression and statements (but not attributes on items in blocks).
+    /// Visit attributes on expression and statements (but not attributes on items in blocks).
     fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
         // flag the offending attributes
         for attr in attrs.iter() {
index 3b4e00a515d3ea305c5731441c5983b072f35502..b86b92fb29e60529d9a38f436d01d887c29c9832 100644 (file)
 use std::{env};
 
 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;
@@ -219,9 +209,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // 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),
 
@@ -446,9 +433,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // #[doc(alias = "...")]
     (active, doc_alias, "1.27.0", Some(50146), None),
 
-    // Scoped lints
-    (active, tool_lints, "1.28.0", Some(44690), None),
-
     // Allows irrefutable patterns in if-let and while-let statements (RFC 2086)
     (active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
 
@@ -512,6 +496,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // Allows `impl Trait` in bindings (`let`, `const`, `static`)
     (active, impl_trait_in_bindings, "1.30.0", Some(34511), None),
+
+    // #[cfg_attr(predicate, multiple, attributes, here)]
+    (active, cfg_attr_multi, "1.31.0", Some(54881), None),
 );
 
 declare_features! (
@@ -690,6 +677,10 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, extern_prelude, "1.30.0", Some(44660), None),
     // Parentheses in patterns
     (accepted, pattern_parentheses, "1.31.0", Some(51087), None),
+    // Allows the definition of `const fn` functions.
+    (accepted, min_const_fn, "1.31.0", Some(53555), None),
+    // Scoped lints
+    (accepted, tool_lints, "1.31.0", Some(44690), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -1807,9 +1798,6 @@ fn visit_fn(&mut self,
                 if header.asyncness.is_async() {
                     gate_feature_post!(&self, async_await, span, "async fn is unstable");
                 }
-                if header.constness.node == ast::Constness::Const {
-                    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
                 // because default methods don't pass through this
@@ -1864,11 +1852,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, min_const_fn, ii.span, "const fn is unstable");
-                }
-            }
+            ast::ImplItemKind::Method(..) => {}
             ast::ImplItemKind::Existential(..) => {
                 gate_feature_post!(
                     &self,
index aa47d5bf669bc0eb9f6015c78739094d9cb78951..a814c88ee78216babc4db391df90667d0efabcf7 100644 (file)
@@ -238,6 +238,19 @@ pub fn new(sess: &'a ParseSess,
         sr
     }
 
+    pub fn new_without_err(sess: &'a ParseSess,
+                           source_file: Lrc<syntax_pos::SourceFile>,
+                           override_span: Option<Span>,
+                           prepend_error_text: &str) -> Result<Self, ()> {
+        let mut sr = StringReader::new_raw(sess, source_file, override_span);
+        if sr.advance_token().is_err() {
+            eprintln!("{}", prepend_error_text);
+            sr.emit_fatal_errors();
+            return Err(());
+        }
+        Ok(sr)
+    }
+
     pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
         let begin = sess.source_map().lookup_byte_offset(span.lo());
         let end = sess.source_map().lookup_byte_offset(span.hi());
index d653ed819fddde9ed1f5549566312940f045f928..6c375799c38ad5cd83cbf1cc33e9bd5f8652318e 100644 (file)
@@ -678,7 +678,7 @@ pub fn expect(&mut self, t: &token::Token) -> PResult<'a,  ()> {
     /// Expect next token to be edible or inedible token.  If edible,
     /// then consume it; if inedible, then return without consuming
     /// anything.  Signal a fatal error if next token is unexpected.
-    fn expect_one_of(&mut self,
+    pub fn expect_one_of(&mut self,
                          edible: &[token::Token],
                          inedible: &[token::Token]) -> PResult<'a,  ()>{
         fn tokens_to_string(tokens: &[TokenType]) -> String {
@@ -1430,6 +1430,23 @@ fn parse_trait_item_(&mut self,
                     attrs.extend(inner_attrs.iter().cloned());
                     Some(body)
                 }
+                token::Interpolated(ref nt) => {
+                    match &nt.0 {
+                        token::NtBlock(..) => {
+                            *at_end = true;
+                            let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
+                            attrs.extend(inner_attrs.iter().cloned());
+                            Some(body)
+                        }
+                        _ => {
+                            let token_str = self.this_token_to_string();
+                            let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`",
+                                                              token_str));
+                            err.span_label(self.span, "expected `;` or `{`");
+                            return Err(err);
+                        }
+                    }
+                }
                 _ => {
                     let token_str = self.this_token_to_string();
                     let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`",
@@ -3866,6 +3883,9 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::Fiel
             // check that a comma comes after every field
             if !ate_comma {
                 let err = self.struct_span_err(self.prev_span, "expected `,`");
+                if let Some(mut delayed) = delayed_err {
+                    delayed.emit();
+                }
                 return Err(err);
             }
             ate_comma = false;
index f1ab1d4ddfa476d8fb0006583f4a3b7521eac4e6..2b1bf1c0290812c228099457d3b57df54c6f8cda 100644 (file)
@@ -178,6 +178,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
     return Attribute::SanitizeAddress;
   case SanitizeMemory:
     return Attribute::SanitizeMemory;
+  case NonLazyBind:
+    return Attribute::NonLazyBind;
   }
   report_fatal_error("bad AttributeKind");
 }
index 1070068b99845f86c72e6cc839a4e0d90f2da995..b6fa9a2fa950809b5b52dd42bea14f10e1e112fa 100644 (file)
@@ -97,6 +97,7 @@ enum LLVMRustAttribute {
   SanitizeThread = 20,
   SanitizeAddress = 21,
   SanitizeMemory = 22,
+  NonLazyBind = 23,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
index 14624176436000dbd682ee8d1b1aa564a70a92d9..c4a49fd4ec4d65f040767b0716e13b70f59268eb 100644 (file)
@@ -13,7 +13,6 @@
 
 // NB: We do not expect *any* monomorphization to be generated here.
 
-#![feature(min_const_fn)]
 #![deny(dead_code)]
 #![crate_type = "rlib"]
 
index 3ea20aa921e1bf6f6646bf9aa3a7dceae2432da3..4492ad5208354af11e8383dea52f399f5efdbafc 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags:-Clink-dead-code
 
-#![feature(min_const_fn)]
 #![crate_type = "rlib"]
 
 // This test makes sure that, when -Clink-dead-code is specified, we generate
index aab5f1bfb4f863825d67206ef1efd378688bbe0b..2cf8ce00bfb5d7d8366a67be1584d6f8f4c24c7a 100644 (file)
@@ -15,7 +15,7 @@
 #![crate_type = "lib"]
 #![feature(naked_functions)]
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define void @naked_empty()
 #[no_mangle]
 #[naked]
@@ -24,7 +24,7 @@ pub fn naked_empty() {
     // CHECK-NEXT: ret void
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 #[no_mangle]
 #[naked]
 // CHECK-NEXT: define void @naked_with_args(i{{[0-9]+}})
@@ -35,7 +35,7 @@ pub fn naked_with_args(a: isize) {
     // CHECK: ret void
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define i{{[0-9]+}} @naked_with_return()
 #[no_mangle]
 #[naked]
@@ -45,7 +45,7 @@ pub fn naked_with_return() -> isize {
     0
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
 #[no_mangle]
 #[naked]
@@ -57,7 +57,7 @@ pub fn naked_with_args_and_return(a: isize) -> isize {
     a
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define void @naked_recursive()
 #[no_mangle]
 #[naked]
diff --git a/src/test/codegen/no-plt.rs b/src/test/codegen/no-plt.rs
new file mode 100644 (file)
index 0000000..8f302e5
--- /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.
+
+// compile-flags: -C relocation-model=pic -Z plt=no
+
+#![crate_type = "lib"]
+
+// We need a function which is normally called through the PLT.
+extern "C" {
+    // CHECK: Function Attrs: nounwind nonlazybind
+    fn getenv(name: *const u8) -> *mut u8;
+}
+
+// Ensure the function gets referenced.
+pub unsafe fn call_through_plt() -> *mut u8 {
+    getenv(b"\0".as_ptr())
+}
+
+// Ensure intrinsics also skip the PLT
+// CHECK: !"RtLibUseGOT"
index fea81f0cc8fa4c6a48f2600646aa58d7caadd19b..86ae3e2113cefeb20f640dca4b658a0df39c1662 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(min_const_fn)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
 // On platforms *without* `#[thread_local]`, use
index ccd94022711cd7362408154793d7b80f6cff185b..229f9466b512257ea140ca9ec9d8b3226e30c3b7 100644 (file)
 // lldb-command:run
 
 // lldb-command:print arg
-// lldb-check:[...]$0 = Struct<i32> { b: -1, b1: 0 }
+// lldbg-check:[...]$0 = Struct<i32> { b: -1, b1: 0 }
+// lldbr-check:(associated_types::Struct<i32>) arg = Struct<i32> { b: -1, b1: 0 }
 // lldb-command:continue
 
 // lldb-command:print inferred
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i64) inferred = 1
 // lldb-command:print explicitly
-// lldb-check:[...]$2 = 1
+// lldbg-check:[...]$2 = 1
+// lldbr-check:(i64) explicitly = 1
 // lldb-command:continue
 
 // lldb-command:print arg
-// lldb-check:[...]$3 = 2
+// lldbg-check:[...]$3 = 2
+// lldbr-check:(i64) arg = 2
 // lldb-command:continue
 
 // lldb-command:print arg
-// lldb-check:[...]$4 = (4, 5)
+// lldbg-check:[...]$4 = (4, 5)
+// lldbr-check:((i32, i64)) arg = { = 4 = 5 }
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$5 = 6
+// lldbg-check:[...]$5 = 6
+// lldbr-check:(i32) a = 6
 // lldb-command:print b
-// lldb-check:[...]$6 = 7
+// lldbg-check:[...]$6 = 7
+// lldbr-check:(i64) b = 7
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$7 = 8
+// lldbg-check:[...]$7 = 8
+// lldbr-check:(i64) a = 8
 // lldb-command:print b
-// lldb-check:[...]$8 = 9
+// lldbg-check:[...]$8 = 9
+// lldbr-check:(i32) b = 9
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 01ce5bd31626e33ed0d3a5b047318144b30d7155..75737cd6f135e835cdc9337a8a77c1a2fd2eeaae 100644 (file)
 
 // lldb-command:run
 // lldb-command:print b
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) b = false
 // lldb-command:print i
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) i = -1
 
-// NOTE: LLDB does not support 32bit chars
-// d ebugger:print (usize)(c)
-// c heck:$3 = 97
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print c
+// lldbr-check:(char) c = 'a'
 
 // lldb-command:print i8
-// lldb-check:[...]$2 = 'D'
+// lldbg-check:[...]$2 = 'D'
+// lldbr-check:(i8) i8 = 68
 // lldb-command:print i16
-// lldb-check:[...]$3 = -16
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) i16 = -16
 // lldb-command:print i32
-// lldb-check:[...]$4 = -32
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) i32 = -32
 // lldb-command:print i64
-// lldb-check:[...]$5 = -64
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) i64 = -64
 // lldb-command:print u
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) u = 1
 // lldb-command:print u8
-// lldb-check:[...]$7 = 'd'
+// lldbg-check:[...]$7 = 'd'
+// lldbr-check:(u8) u8 = 100
 // lldb-command:print u16
-// lldb-check:[...]$8 = 16
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) u16 = 16
 // lldb-command:print u32
-// lldb-check:[...]$9 = 32
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) u32 = 32
 // lldb-command:print u64
-// lldb-check:[...]$10 = 64
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) u64 = 64
 // lldb-command:print f32
-// lldb-check:[...]$11 = 2.5
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) f32 = 2.5
 // lldb-command:print f64
-// lldb-check:[...]$12 = 3.5
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) f64 = 3.5
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index f6c0ff09efe93f7fa3ac509327d9ca71bb979424..6f618c3881f968e056b8a7e2c4193ac66833c1a8 100644 (file)
 
 // lldb-command:run
 // lldb-command:print *bool_ref
-// lldb-check:[...]$0 = true
+// lldbg-check:[...]$0 = true
+// lldbr-check:(bool) *bool_ref = true
 
 // lldb-command:print *int_ref
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) *int_ref = -1
 
-// NOTE: lldb doesn't support 32bit chars at the moment
-// d ebugger:print *char_ref
-// c heck:[...]$x = 97
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print *char_ref
+// lldbr-check:(char) *char_ref = 'a'
 
 // lldb-command:print *i8_ref
-// lldb-check:[...]$2 = 'D'
+// lldbg-check:[...]$2 = 'D'
+// lldbr-check:(i8) *i8_ref = 68
 
 // lldb-command:print *i16_ref
-// lldb-check:[...]$3 = -16
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) *i16_ref = -16
 
 // lldb-command:print *i32_ref
-// lldb-check:[...]$4 = -32
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) *i32_ref = -32
 
 // lldb-command:print *i64_ref
-// lldb-check:[...]$5 = -64
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) *i64_ref = -64
 
 // lldb-command:print *uint_ref
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) *uint_ref = 1
 
 // lldb-command:print *u8_ref
-// lldb-check:[...]$7 = 'd'
+// lldbg-check:[...]$7 = 'd'
+// lldbr-check:(u8) *u8_ref = 100
 
 // lldb-command:print *u16_ref
-// lldb-check:[...]$8 = 16
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) *u16_ref = 16
 
 // lldb-command:print *u32_ref
-// lldb-check:[...]$9 = 32
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) *u32_ref = 32
 
 // lldb-command:print *u64_ref
-// lldb-check:[...]$10 = 64
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) *u64_ref = 64
 
 // lldb-command:print *f32_ref
-// lldb-check:[...]$11 = 2.5
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) *f32_ref = 2.5
 
 // lldb-command:print *f64_ref
-// lldb-check:[...]$12 = 3.5
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) *f64_ref = 3.5
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index d6f379634be5bceddfa9b652316bb0871b6afea8..73b92b82ba0a6032c888e9301be75cbbad271185 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *the_a_ref
-// lldb-check:[...]$0 = TheA
+// lldbg-check:[...]$0 = TheA
+// lldbr-check:(borrowed_c_style_enum::ABC) *the_a_ref = borrowed_c_style_enum::ABC::TheA
 
 // lldb-command:print *the_b_ref
-// lldb-check:[...]$1 = TheB
+// lldbg-check:[...]$1 = TheB
+// lldbr-check:(borrowed_c_style_enum::ABC) *the_b_ref = borrowed_c_style_enum::ABC::TheB
 
 // lldb-command:print *the_c_ref
-// lldb-check:[...]$2 = TheC
+// lldbg-check:[...]$2 = TheC
+// lldbr-check:(borrowed_c_style_enum::ABC) *the_c_ref = borrowed_c_style_enum::ABC::TheC
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 9e63beff3cb2eeb0f7c3973a87224fe562f3cc9c..9143e83343fb89cddc0ee653302d92e8e4c585c1 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *the_a_ref
-// lldb-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbr-check:(borrowed_enum::ABC::TheA) *the_a_ref = TheA { borrowed_enum::ABC::TheA: 0, borrowed_enum::ABC::TheB: 8970181431921507452 }
 // lldb-command:print *the_b_ref
-// lldb-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbr-check:(borrowed_enum::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 }
 // lldb-command:print *univariant_ref
-// lldb-check:[...]$2 = TheOnlyCase(4820353753753434)
+// lldbg-check:[...]$2 = TheOnlyCase(4820353753753434)
+// lldbr-check:(borrowed_enum::Univariant) *univariant_ref = { borrowed_enum::TheOnlyCase = { = 4820353753753434 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 01428e515e27f25b15dfc333980167356c33015a..3efb4dd470e65800ce62a5b860ecb7dc1f96eace 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *stack_val_ref
-// lldb-check:[...]$0 = SomeStruct { x: 10, y: 23.5 }
+// lldbg-check:[...]$0 = SomeStruct { x: 10, y: 23.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *stack_val_ref = SomeStruct { x: 10, y: 23.5 }
 
 // lldb-command:print *stack_val_interior_ref_1
-// lldb-check:[...]$1 = 10
+// lldbg-check:[...]$1 = 10
+// lldbr-check:(isize) *stack_val_interior_ref_1 = 10
 
 // lldb-command:print *stack_val_interior_ref_2
-// lldb-check:[...]$2 = 23.5
+// lldbg-check:[...]$2 = 23.5
+// lldbr-check:(f64) *stack_val_interior_ref_2 = 23.5
 
 // lldb-command:print *ref_to_unnamed
-// lldb-check:[...]$3 = SomeStruct { x: 11, y: 24.5 }
+// lldbg-check:[...]$3 = SomeStruct { x: 11, y: 24.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *ref_to_unnamed = SomeStruct { x: 11, y: 24.5 }
 
 // lldb-command:print *unique_val_ref
-// lldb-check:[...]$4 = SomeStruct { x: 13, y: 26.5 }
+// lldbg-check:[...]$4 = SomeStruct { x: 13, y: 26.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *unique_val_ref = SomeStruct { x: 13, y: 26.5 }
 
 // lldb-command:print *unique_val_interior_ref_1
-// lldb-check:[...]$5 = 13
+// lldbg-check:[...]$5 = 13
+// lldbr-check:(isize) *unique_val_interior_ref_1 = 13
 
 // lldb-command:print *unique_val_interior_ref_2
-// lldb-check:[...]$6 = 26.5
+// lldbg-check:[...]$6 = 26.5
+// lldbr-check:(f64) *unique_val_interior_ref_2 = 26.5
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index 17db88ee37f53fcecbeaad6a81a415e8274e2caf..ec7c000350f53023ce9fa366227feab7b4a54c48 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *stack_val_ref
-// lldb-check:[...]$0 = (-14, -19)
+// lldbg-check:[...]$0 = (-14, -19)
+// lldbr-check:((i16, f32)) *stack_val_ref = { = -14 = -19 }
 
 // lldb-command:print *ref_to_unnamed
-// lldb-check:[...]$1 = (-15, -20)
+// lldbg-check:[...]$1 = (-15, -20)
+// lldbr-check:((i16, f32)) *ref_to_unnamed = { = -15 = -20 }
 
 // lldb-command:print *unique_val_ref
-// lldb-check:[...]$2 = (-17, -22)
+// lldbg-check:[...]$2 = (-17, -22)
+// lldbr-check:((i16, f32)) *unique_val_ref = { = -17 = -22 }
 
 
 #![allow(unused_variables)]
index 9e95498b0c30e7cbbd6903efb3a121e9e1bb9e27..78effa5f3dffe3af4575bfb9d6bac054e0f6d7f6 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *bool_ref
-// lldb-check:[...]$0 = true
+// lldbg-check:[...]$0 = true
+// lldbr-check:(bool) *bool_ref = true
 
 // lldb-command:print *int_ref
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) *int_ref = -1
 
-// d ebugger:print *char_ref
-// c heck:[...]$3 = 97
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print *char_ref
+// lldbr-check:(char) *char_ref = 97
 
 // lldb-command:print *i8_ref
-// lldb-check:[...]$2 = 68
+// lldbg-check:[...]$2 = 68
+// lldbr-check:(i8) *i8_ref = 68
 
 // lldb-command:print *i16_ref
-// lldb-check:[...]$3 = -16
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) *i16_ref = -16
 
 // lldb-command:print *i32_ref
-// lldb-check:[...]$4 = -32
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) *i32_ref = -32
 
 // lldb-command:print *i64_ref
-// lldb-check:[...]$5 = -64
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) *i64_ref = -64
 
 // lldb-command:print *uint_ref
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) *uint_ref = 1
 
 // lldb-command:print *u8_ref
-// lldb-check:[...]$7 = 100
+// lldbg-check:[...]$7 = 100
+// lldbr-check:(u8) *u8_ref = 100
 
 // lldb-command:print *u16_ref
-// lldb-check:[...]$8 = 16
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) *u16_ref = 16
 
 // lldb-command:print *u32_ref
-// lldb-check:[...]$9 = 32
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) *u32_ref = 32
 
 // lldb-command:print *u64_ref
-// lldb-check:[...]$10 = 64
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) *u64_ref = 64
 
 // lldb-command:print *f32_ref
-// lldb-check:[...]$11 = 2.5
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) *f32_ref = 2.5
 
 // lldb-command:print *f64_ref
-// lldb-check:[...]$12 = 3.5
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) *f64_ref = 3.5
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index 98c09fe09de8f3f2937ef30b644e15bbae403352..7e25a9bf76a86e947511c16f88386d000a923e13 100644 (file)
 
 // lldb-command:run
 // lldb-command:print *a
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(i32) *a = 1
 // lldb-command:print *b
-// lldb-check:[...]$1 = (2, 3.5)
+// lldbg-check:[...]$1 = (2, 3.5)
+// lldbr-check:((i32, f64)) *b = { = 2 = 3.5 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index ac091b4a533db49b8b3fabe694e74eba386ad5d0..130ea3822cb3ae9e91eee7886d7fd80e2ab610ea 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 // lldb-command:run
 
 // lldb-command:print *unique
-// lldb-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
+// lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
+// lldbr-check:(boxed_struct::StructWithSomePadding) *unique = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
 
 // lldb-command:print *unique_dtor
-// lldb-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
+// lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
+// lldbr-check:(boxed_struct::StructWithDestructor) *unique_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index c14f8c7b354fcaaf75dbfef7792ee6c78c238480..c0fb2dbdda2746776004599a6b7f288f253d3e50 100644 (file)
 // lldb-command:run
 
 // lldb-command:print self
-// lldb-check:[...]$0 = 1111
+// lldbg-check:[...]$0 = 1111
+// lldbr-check:(isize) self = 1111
 // lldb-command:continue
 
 // lldb-command:print self
-// lldb-check:[...]$1 = Struct { x: 2222, y: 3333 }
+// lldbg-check:[...]$1 = Struct { x: 2222, y: 3333 }
+// lldbr-check:(by_value_self_argument_in_trait_impl::Struct) self = Struct { x: 2222, y: 3333 }
 // lldb-command:continue
 
 // lldb-command:print self
-// lldb-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
+// lldbg-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
+// lldbr-check:((f64, isize, isize, f64)) self = { = 4444.5 = 5555 = 6666 = 7777.5 }
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 004e15d1cc6c15a0745afa92bc96d3d910f6a8dd..0a19a040a5f438bed847e4d88a6a48b15ca7844d 100644 (file)
 // lldb-command:run
 
 // lldb-command:print tuple_interior_padding
-// lldb-check:[...]$0 = (0, OneHundred)
+// lldbg-check:[...]$0 = (0, OneHundred)
+// lldbr-check:((i16, c_style_enum_in_composite::AnEnum)) tuple_interior_padding = { = 0 = c_style_enum_in_composite::AnEnum::OneHundred }
 
 // lldb-command:print tuple_padding_at_end
-// lldb-check:[...]$1 = ((1, OneThousand), 2)
+// lldbg-check:[...]$1 = ((1, OneThousand), 2)
+// lldbr-check:(((u64, c_style_enum_in_composite::AnEnum), u64)) tuple_padding_at_end = { = { = 1 = c_style_enum_in_composite::AnEnum::OneThousand } = 2 }
 // lldb-command:print tuple_different_enums
-// lldb-check:[...]$2 = (OneThousand, MountainView, OneMillion, Vienna)
+// lldbg-check:[...]$2 = (OneThousand, MountainView, OneMillion, Vienna)
+// lldbr-check:((c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum, c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum)) tuple_different_enums = { = c_style_enum_in_composite::AnEnum::OneThousand = c_style_enum_in_composite::AnotherEnum::MountainView = c_style_enum_in_composite::AnEnum::OneMillion = c_style_enum_in_composite::AnotherEnum::Vienna }
 
 // lldb-command:print padded_struct
-// lldb-check:[...]$3 = PaddedStruct { a: 3, b: OneMillion, c: 4, d: Toronto, e: 5 }
+// lldbg-check:[...]$3 = PaddedStruct { a: 3, b: OneMillion, c: 4, d: Toronto, e: 5 }
+// lldbr-check:(c_style_enum_in_composite::PaddedStruct) padded_struct = PaddedStruct { a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5 }
 
 // lldb-command:print packed_struct
-// lldb-check:[...]$4 = PackedStruct { a: 6, b: OneHundred, c: 7, d: Vienna, e: 8 }
+// lldbg-check:[...]$4 = PackedStruct { a: 6, b: OneHundred, c: 7, d: Vienna, e: 8 }
+// lldbr-check:(c_style_enum_in_composite::PackedStruct) packed_struct = PackedStruct { a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8 }
 
 // lldb-command:print non_padded_struct
-// lldb-check:[...]$5 = NonPaddedStruct { a: OneMillion, b: MountainView, c: OneThousand, d: Toronto }
+// lldbg-check:[...]$5 = NonPaddedStruct { a: OneMillion, b: MountainView, c: OneThousand, d: Toronto }
+// lldbr-check:(c_style_enum_in_composite::NonPaddedStruct) non_padded_struct = NonPaddedStruct { a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto }
 
 // lldb-command:print struct_with_drop
-// lldb-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
+// lldbg-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
+// lldbr-check:((c_style_enum_in_composite::StructWithDrop, i64)) struct_with_drop = { = StructWithDrop { a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna } = 9 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 2dbac8e3d9eac0cff654f54edffbc4ec311f5af8..a756d4fdf6ce799fb192cdf73ac10459af284e64 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // ignore-aarch64
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 // lldb-command:run
 
 // lldb-command:print auto_one
-// lldb-check:[...]$0 = One
+// lldbg-check:[...]$0 = One
+// lldbr-check:(c_style_enum::AutoDiscriminant) auto_one = c_style_enum::AutoDiscriminant::One
 
 // lldb-command:print auto_two
-// lldb-check:[...]$1 = Two
+// lldbg-check:[...]$1 = Two
+// lldbr-check:(c_style_enum::AutoDiscriminant) auto_two = c_style_enum::AutoDiscriminant::Two
 
 // lldb-command:print auto_three
-// lldb-check:[...]$2 = Three
+// lldbg-check:[...]$2 = Three
+// lldbr-check:(c_style_enum::AutoDiscriminant) auto_three = c_style_enum::AutoDiscriminant::Three
 
 // lldb-command:print manual_one_hundred
-// lldb-check:[...]$3 = OneHundred
+// lldbg-check:[...]$3 = OneHundred
+// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_hundred = c_style_enum::ManualDiscriminant::OneHundred
 
 // lldb-command:print manual_one_thousand
-// lldb-check:[...]$4 = OneThousand
+// lldbg-check:[...]$4 = OneThousand
+// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_thousand = c_style_enum::ManualDiscriminant::OneThousand
 
 // lldb-command:print manual_one_million
-// lldb-check:[...]$5 = OneMillion
+// lldbg-check:[...]$5 = OneMillion
+// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_million = c_style_enum::ManualDiscriminant::OneMillion
 
 // lldb-command:print single_variant
-// lldb-check:[...]$6 = TheOnlyVariant
+// lldbg-check:[...]$6 = TheOnlyVariant
+// lldbr-check:(c_style_enum::SingleVariant) single_variant = c_style_enum::SingleVariant::TheOnlyVariant
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index 5335e0bfa4a6984297f7449e3da158962850b19a..bb61b394a9c7be2831228671e66f38d8e0ca8488 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = 0.5
+// lldbg-check:[...]$0 = 0.5
+// lldbr-check:(f64) x = 0.5
 // lldb-command:print y
-// lldb-check:[...]$1 = 10
+// lldbg-check:[...]$1 = 10
+// lldbr-check:(i32) y = 10
 // lldb-command:continue
 
 // lldb-command:print *x
-// lldb-check:[...]$2 = 29
+// lldbg-check:[...]$2 = 29
+// lldbr-check:(i32) *x = 29
 // lldb-command:print *y
-// lldb-check:[...]$3 = 110
+// lldbg-check:[...]$3 = 110
+// lldbr-check:(i32) *y = 110
 // lldb-command:continue
 
 #![feature(box_syntax)]
index 28728df92805103c5c708df6c38f2f5fab1ff166..9002e19ce21baa77b38b903e732393794e475362 100644 (file)
 // lldb-command:run
 
 // lldb-command:print result
-// lldb-check:[...]$0 = (17, 17)
+// lldbg-check:[...]$0 = (17, 17)
+// lldbr-check:((u32, u32)) result = { = 17 = 17 }
 // lldb-command:print a_variable
-// lldb-check:[...]$1 = 123456789
+// lldbg-check:[...]$1 = 123456789
+// lldbr-check:(u32) a_variable = 123456789
 // lldb-command:print another_variable
-// lldb-check:[...]$2 = 123456789.5
+// lldbg-check:[...]$2 = 123456789.5
+// lldbr-check:(f64) another_variable = 123456789.5
 // lldb-command:continue
 
 // lldb-command:print result
-// lldb-check:[...]$3 = (1212, 1212)
+// lldbg-check:[...]$3 = (1212, 1212)
+// lldbr-check:((i16, i16)) result = { = 1212 = 1212 }
 // lldb-command:print a_variable
-// lldb-check:[...]$4 = 123456789
+// lldbg-check:[...]$4 = 123456789
+// lldbr-check:(u32) a_variable = 123456789
 // lldb-command:print another_variable
-// lldb-check:[...]$5 = 123456789.5
+// lldbg-check:[...]$5 = 123456789.5
+// lldbr-check:(f64) another_variable = 123456789.5
 // lldb-command:continue
 
 
index efa9ee59b22b2233588d078348b2c34f07b852e5..b152fa27906f1d146fee8142c683d9817ddb5f2b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) a = 1
 // lldb-command:print b
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) b = false
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(isize) a = 2
 // lldb-command:print b
-// lldb-check:[...]$3 = 3
+// lldbg-check:[...]$3 = 3
+// lldbr-check:(u16) b = 3
 // lldb-command:print c
-// lldb-check:[...]$4 = 4
+// lldbg-check:[...]$4 = 4
+// lldbr-check:(u16) c = 4
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$5 = 5
+// lldbg-check:[...]$5 = 5
+// lldbr-check:(isize) a = 5
 // lldb-command:print b
-// lldb-check:[...]$6 = (6, 7)
+// lldbg-check:[...]$6 = (6, 7)
+// lldbr-check:((u32, u32)) b = { = 6 = 7 }
 // lldb-command:continue
 
 // lldb-command:print h
-// lldb-check:[...]$7 = 8
+// lldbg-check:[...]$7 = 8
+// lldbr-check:(i16) h = 8
 // lldb-command:print i
-// lldb-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbg-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbr-check:(destructured_fn_argument::Struct) i = Struct { a: 9, b: 10 }
 // lldb-command:print j
-// lldb-check:[...]$9 = 11
+// lldbg-check:[...]$9 = 11
+// lldbr-check:(i16) j = 11
 // lldb-command:continue
 
 // lldb-command:print k
-// lldb-check:[...]$10 = 12
+// lldbg-check:[...]$10 = 12
+// lldbr-check:(i64) k = 12
 // lldb-command:print l
-// lldb-check:[...]$11 = 13
+// lldbg-check:[...]$11 = 13
+// lldbr-check:(i32) l = 13
 // lldb-command:continue
 
 // lldb-command:print m
-// lldb-check:[...]$12 = 14
+// lldbg-check:[...]$12 = 14
+// lldbr-check:(isize) m = 14
 // lldb-command:print n
-// lldb-check:[...]$13 = 16
+// lldbg-check:[...]$13 = 16
+// lldbr-check:(i32) n = 16
 // lldb-command:continue
 
 // lldb-command:print o
-// lldb-check:[...]$14 = 18
+// lldbg-check:[...]$14 = 18
+// lldbr-check:(i32) o = 18
 // lldb-command:continue
 
 // lldb-command:print p
-// lldb-check:[...]$15 = 19
+// lldbg-check:[...]$15 = 19
+// lldbr-check:(i64) p = 19
 // lldb-command:print q
-// lldb-check:[...]$16 = 20
+// lldbg-check:[...]$16 = 20
+// lldbr-check:(i32) q = 20
 // lldb-command:print r
-// lldb-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbg-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbr-check:(destructured_fn_argument::Struct) r = Struct { a: 21, b: 22 }
 // lldb-command:continue
 
 // lldb-command:print s
-// lldb-check:[...]$18 = 24
+// lldbg-check:[...]$18 = 24
+// lldbr-check:(i32) s = 24
 // lldb-command:print t
-// lldb-check:[...]$19 = 23
+// lldbg-check:[...]$19 = 23
+// lldbr-check:(i64) t = 23
 // lldb-command:continue
 
 // lldb-command:print u
-// lldb-check:[...]$20 = 25
+// lldbg-check:[...]$20 = 25
+// lldbr-check:(i16) u = 25
 // lldb-command:print v
-// lldb-check:[...]$21 = 26
+// lldbg-check:[...]$21 = 26
+// lldbr-check:(i32) v = 26
 // lldb-command:print w
-// lldb-check:[...]$22 = 27
+// lldbg-check:[...]$22 = 27
+// lldbr-check:(i64) w = 27
 // lldb-command:print x
-// lldb-check:[...]$23 = 28
+// lldbg-check:[...]$23 = 28
+// lldbr-check:(i32) x = 28
 // lldb-command:print y
-// lldb-check:[...]$24 = 29
+// lldbg-check:[...]$24 = 29
+// lldbr-check:(i64) y = 29
 // lldb-command:print z
-// lldb-check:[...]$25 = 30
+// lldbg-check:[...]$25 = 30
+// lldbr-check:(i32) z = 30
 // lldb-command:print ae
-// lldb-check:[...]$26 = 31
+// lldbg-check:[...]$26 = 31
+// lldbr-check:(i64) ae = 31
 // lldb-command:print oe
-// lldb-check:[...]$27 = 32
+// lldbg-check:[...]$27 = 32
+// lldbr-check:(i32) oe = 32
 // lldb-command:print ue
-// lldb-check:[...]$28 = 33
+// lldbg-check:[...]$28 = 33
+// lldbr-check:(u16) ue = 33
 // lldb-command:continue
 
 // lldb-command:print aa
-// lldb-check:[...]$29 = (34, 35)
+// lldbg-check:[...]$29 = (34, 35)
+// lldbr-check:((isize, isize)) aa = { = 34 = 35 }
 // lldb-command:continue
 
 // lldb-command:print bb
-// lldb-check:[...]$30 = (36, 37)
+// lldbg-check:[...]$30 = (36, 37)
+// lldbr-check:((isize, isize)) bb = { = 36 = 37 }
 // lldb-command:continue
 
 // lldb-command:print cc
-// lldb-check:[...]$31 = 38
+// lldbg-check:[...]$31 = 38
+// lldbr-check:(isize) cc = 38
 // lldb-command:continue
 
 // lldb-command:print dd
-// lldb-check:[...]$32 = (40, 41, 42)
+// lldbg-check:[...]$32 = (40, 41, 42)
+// lldbr-check:((isize, isize, isize)) dd = { = 40 = 41 = 42 }
 // lldb-command:continue
 
 // lldb-command:print *ee
-// lldb-check:[...]$33 = (43, 44, 45)
+// lldbg-check:[...]$33 = (43, 44, 45)
+// lldbr-check:((isize, isize, isize)) *ee = { = 43 = 44 = 45 }
 // lldb-command:continue
 
 // lldb-command:print *ff
-// lldb-check:[...]$34 = 46
+// lldbg-check:[...]$34 = 46
+// lldbr-check:(isize) *ff = 46
 // lldb-command:print gg
-// lldb-check:[...]$35 = (47, 48)
+// lldbg-check:[...]$35 = (47, 48)
+// lldbr-check:((isize, isize)) gg = { = 47 = 48 }
 // lldb-command:continue
 
 // lldb-command:print *hh
-// lldb-check:[...]$36 = 50
+// lldbg-check:[...]$36 = 50
+// lldbr-check:(i32) *hh = 50
 // lldb-command:continue
 
 // lldb-command:print ii
-// lldb-check:[...]$37 = 51
+// lldbg-check:[...]$37 = 51
+// lldbr-check:(i32) ii = 51
 // lldb-command:continue
 
 // lldb-command:print *jj
-// lldb-check:[...]$38 = 52
+// lldbg-check:[...]$38 = 52
+// lldbr-check:(i32) *jj = 52
 // lldb-command:continue
 
 // lldb-command:print kk
-// lldb-check:[...]$39 = 53
+// lldbg-check:[...]$39 = 53
+// lldbr-check:(f64) kk = 53
 // lldb-command:print ll
-// lldb-check:[...]$40 = 54
+// lldbg-check:[...]$40 = 54
+// lldbr-check:(isize) ll = 54
 // lldb-command:continue
 
 // lldb-command:print mm
-// lldb-check:[...]$41 = 55
+// lldbg-check:[...]$41 = 55
+// lldbr-check:(f64) mm = 55
 // lldb-command:print *nn
-// lldb-check:[...]$42 = 56
+// lldbg-check:[...]$42 = 56
+// lldbr-check:(isize) *nn = 56
 // lldb-command:continue
 
 // lldb-command:print oo
-// lldb-check:[...]$43 = 57
+// lldbg-check:[...]$43 = 57
+// lldbr-check:(isize) oo = 57
 // lldb-command:print pp
-// lldb-check:[...]$44 = 58
+// lldbg-check:[...]$44 = 58
+// lldbr-check:(isize) pp = 58
 // lldb-command:print qq
-// lldb-check:[...]$45 = 59
+// lldbg-check:[...]$45 = 59
+// lldbr-check:(isize) qq = 59
 // lldb-command:continue
 
 // lldb-command:print rr
-// lldb-check:[...]$46 = 60
+// lldbg-check:[...]$46 = 60
+// lldbr-check:(isize) rr = 60
 // lldb-command:print ss
-// lldb-check:[...]$47 = 61
+// lldbg-check:[...]$47 = 61
+// lldbr-check:(isize) ss = 61
 // lldb-command:print tt
-// lldb-check:[...]$48 = 62
+// lldbg-check:[...]$48 = 62
+// lldbr-check:(isize) tt = 62
 // lldb-command:continue
 
 #![allow(unused_variables)]
index e973c22fd4a8502b785310a15e6792422ed48f74..48231a906c902a7032a7187f33dc6c2dac277621 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 
 // DESTRUCTURED STRUCT
 // lldb-command:print x
-// lldb-check:[...]$0 = 400
+// lldbg-check:[...]$0 = 400
+// lldbr-check:(i16) x = 400
 // lldb-command:print y
-// lldb-check:[...]$1 = 401.5
+// lldbg-check:[...]$1 = 401.5
+// lldbr-check:(f32) y = 401.5
 // lldb-command:print z
-// lldb-check:[...]$2 = true
+// lldbg-check:[...]$2 = true
+// lldbr-check:(bool) z = true
 // lldb-command:continue
 
 // DESTRUCTURED TUPLE
 // lldb-command:print _i8
-// lldb-check:[...]$3 = 0x6f
+// lldbg-check:[...]$3 = 0x6f
+// lldbr-check:(i8) _i8 = 111
 // lldb-command:print _u8
-// lldb-check:[...]$4 = 0x70
+// lldbg-check:[...]$4 = 0x70
+// lldbr-check:(u8) _u8 = 112
 // lldb-command:print _i16
-// lldb-check:[...]$5 = -113
+// lldbg-check:[...]$5 = -113
+// lldbr-check:(i16) _i16 = -113
 // lldb-command:print _u16
-// lldb-check:[...]$6 = 114
+// lldbg-check:[...]$6 = 114
+// lldbr-check:(u16) _u16 = 114
 // lldb-command:print _i32
-// lldb-check:[...]$7 = -115
+// lldbg-check:[...]$7 = -115
+// lldbr-check:(i32) _i32 = -115
 // lldb-command:print _u32
-// lldb-check:[...]$8 = 116
+// lldbg-check:[...]$8 = 116
+// lldbr-check:(u32) _u32 = 116
 // lldb-command:print _i64
-// lldb-check:[...]$9 = -117
+// lldbg-check:[...]$9 = -117
+// lldbr-check:(i64) _i64 = -117
 // lldb-command:print _u64
-// lldb-check:[...]$10 = 118
+// lldbg-check:[...]$10 = 118
+// lldbr-check:(u64) _u64 = 118
 // lldb-command:print _f32
-// lldb-check:[...]$11 = 119.5
+// lldbg-check:[...]$11 = 119.5
+// lldbr-check:(f32) _f32 = 119.5
 // lldb-command:print _f64
-// lldb-check:[...]$12 = 120.5
+// lldbg-check:[...]$12 = 120.5
+// lldbr-check:(f64) _f64 = 120.5
 // lldb-command:continue
 
 // MORE COMPLEX CASE
 // lldb-command:print v1
-// lldb-check:[...]$13 = 80000
+// lldbg-check:[...]$13 = 80000
+// lldbr-check:(i32) v1 = 80000
 // lldb-command:print x1
-// lldb-check:[...]$14 = 8000
+// lldbg-check:[...]$14 = 8000
+// lldbr-check:(i16) x1 = 8000
 // lldb-command:print *y1
-// lldb-check:[...]$15 = 80001.5
+// lldbg-check:[...]$15 = 80001.5
+// lldbr-check:(f32) *y1 = 80001.5
 // lldb-command:print z1
-// lldb-check:[...]$16 = false
+// lldbg-check:[...]$16 = false
+// lldbr-check:(bool) z1 = false
 // lldb-command:print *x2
-// lldb-check:[...]$17 = -30000
+// lldbg-check:[...]$17 = -30000
+// lldbr-check:(i16) *x2 = -30000
 // lldb-command:print y2
-// lldb-check:[...]$18 = -300001.5
+// lldbg-check:[...]$18 = -300001.5
+// lldbr-check:(f32) y2 = -300001.5
 // lldb-command:print *z2
-// lldb-check:[...]$19 = true
+// lldbg-check:[...]$19 = true
+// lldbr-check:(bool) *z2 = true
 // lldb-command:print v2
-// lldb-check:[...]$20 = 854237.5
+// lldbg-check:[...]$20 = 854237.5
+// lldbr-check:(f64) v2 = 854237.5
 // lldb-command:continue
 
 // SIMPLE IDENTIFIER
 // lldb-command:print i
-// lldb-check:[...]$21 = 1234
+// lldbg-check:[...]$21 = 1234
+// lldbr-check:(i32) i = 1234
 // lldb-command:continue
 
 // lldb-command:print simple_struct_ident
-// lldb-check:[...]$22 = Struct { x: 3537, y: 35437.5, z: true }
+// lldbg-check:[...]$22 = Struct { x: 3537, y: 35437.5, z: true }
+// lldbr-check:(destructured_for_loop_variable::Struct) simple_struct_ident = Struct { x: 3537, y: 35437.5, z: true }
 // lldb-command:continue
 
 // lldb-command:print simple_tuple_ident
-// lldb-check:[...]$23 = (34903493, 232323)
+// lldbg-check:[...]$23 = (34903493, 232323)
+// lldbr-check:((u32, i64)) simple_tuple_ident = { = 34903493 = 232323 }
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 1f18b77ab8f6fbf6b797096506b4d89b4d9991f5..5a2edf81d29316012d8a31e0ba3e82c3cfc86099 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) a = 1
 // lldb-command:print b
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) b = false
 
 // lldb-command:print c
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(isize) c = 2
 // lldb-command:print d
-// lldb-check:[...]$3 = 3
+// lldbg-check:[...]$3 = 3
+// lldbr-check:(u16) d = 3
 // lldb-command:print e
-// lldb-check:[...]$4 = 4
+// lldbg-check:[...]$4 = 4
+// lldbr-check:(u16) e = 4
 
 // lldb-command:print f
-// lldb-check:[...]$5 = 5
+// lldbg-check:[...]$5 = 5
+// lldbr-check:(isize) f = 5
 // lldb-command:print g
-// lldb-check:[...]$6 = (6, 7)
+// lldbg-check:[...]$6 = (6, 7)
+// lldbr-check:((u32, u32)) g = { = 6 = 7 }
 
 // lldb-command:print h
-// lldb-check:[...]$7 = 8
+// lldbg-check:[...]$7 = 8
+// lldbr-check:(i16) h = 8
 // lldb-command:print i
-// lldb-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbg-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbr-check:(destructured_local::Struct) i = Struct { a: 9, b: 10 }
 // lldb-command:print j
-// lldb-check:[...]$9 = 11
+// lldbg-check:[...]$9 = 11
+// lldbr-check:(i16) j = 11
 
 // lldb-command:print k
-// lldb-check:[...]$10 = 12
+// lldbg-check:[...]$10 = 12
+// lldbr-check:(i64) k = 12
 // lldb-command:print l
-// lldb-check:[...]$11 = 13
+// lldbg-check:[...]$11 = 13
+// lldbr-check:(i32) l = 13
 
 // lldb-command:print m
-// lldb-check:[...]$12 = 14
+// lldbg-check:[...]$12 = 14
+// lldbr-check:(i32) m = 14
 // lldb-command:print n
-// lldb-check:[...]$13 = 16
+// lldbg-check:[...]$13 = 16
+// lldbr-check:(i32) n = 16
 
 // lldb-command:print o
-// lldb-check:[...]$14 = 18
+// lldbg-check:[...]$14 = 18
+// lldbr-check:(i32) o = 18
 
 // lldb-command:print p
-// lldb-check:[...]$15 = 19
+// lldbg-check:[...]$15 = 19
+// lldbr-check:(i64) p = 19
 // lldb-command:print q
-// lldb-check:[...]$16 = 20
+// lldbg-check:[...]$16 = 20
+// lldbr-check:(i32) q = 20
 // lldb-command:print r
-// lldb-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbg-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbr-check:(destructured_local::Struct) r = Struct { a: 21, b: 22 }
 
 // lldb-command:print s
-// lldb-check:[...]$18 = 24
+// lldbg-check:[...]$18 = 24
+// lldbr-check:(i32) s = 24
 // lldb-command:print t
-// lldb-check:[...]$19 = 23
+// lldbg-check:[...]$19 = 23
+// lldbr-check:(i64) t = 23
 
 // lldb-command:print u
-// lldb-check:[...]$20 = 25
+// lldbg-check:[...]$20 = 25
+// lldbr-check:(i32) u = 25
 // lldb-command:print v
-// lldb-check:[...]$21 = 26
+// lldbg-check:[...]$21 = 26
+// lldbr-check:(i32) v = 26
 // lldb-command:print w
-// lldb-check:[...]$22 = 27
+// lldbg-check:[...]$22 = 27
+// lldbr-check:(i32) w = 27
 // lldb-command:print x
-// lldb-check:[...]$23 = 28
+// lldbg-check:[...]$23 = 28
+// lldbr-check:(i32) x = 28
 // lldb-command:print y
-// lldb-check:[...]$24 = 29
+// lldbg-check:[...]$24 = 29
+// lldbr-check:(i64) y = 29
 // lldb-command:print z
-// lldb-check:[...]$25 = 30
+// lldbg-check:[...]$25 = 30
+// lldbr-check:(i32) z = 30
 // lldb-command:print ae
-// lldb-check:[...]$26 = 31
+// lldbg-check:[...]$26 = 31
+// lldbr-check:(i64) ae = 31
 // lldb-command:print oe
-// lldb-check:[...]$27 = 32
+// lldbg-check:[...]$27 = 32
+// lldbr-check:(i32) oe = 32
 // lldb-command:print ue
-// lldb-check:[...]$28 = 33
+// lldbg-check:[...]$28 = 33
+// lldbr-check:(i32) ue = 33
 
 // lldb-command:print aa
-// lldb-check:[...]$29 = (34, 35)
+// lldbg-check:[...]$29 = (34, 35)
+// lldbr-check:((i32, i32)) aa = { = 34 = 35 }
 
 // lldb-command:print bb
-// lldb-check:[...]$30 = (36, 37)
+// lldbg-check:[...]$30 = (36, 37)
+// lldbr-check:((i32, i32)) bb = { = 36 = 37 }
 
 // lldb-command:print cc
-// lldb-check:[...]$31 = 38
+// lldbg-check:[...]$31 = 38
+// lldbr-check:(i32) cc = 38
 
 // lldb-command:print dd
-// lldb-check:[...]$32 = (40, 41, 42)
+// lldbg-check:[...]$32 = (40, 41, 42)
+// lldbr-check:((i32, i32, i32)) dd = { = 40 = 41 = 42 }
 
 // lldb-command:print *ee
-// lldb-check:[...]$33 = (43, 44, 45)
+// lldbg-check:[...]$33 = (43, 44, 45)
+// lldbr-check:((i32, i32, i32)) *ee = { = 43 = 44 = 45 }
 
 // lldb-command:print *ff
-// lldb-check:[...]$34 = 46
+// lldbg-check:[...]$34 = 46
+// lldbr-check:(i32) *ff = 46
 
 // lldb-command:print gg
-// lldb-check:[...]$35 = (47, 48)
+// lldbg-check:[...]$35 = (47, 48)
+// lldbr-check:((i32, i32)) gg = { = 47 = 48 }
 
 // lldb-command:print *hh
-// lldb-check:[...]$36 = 50
+// lldbg-check:[...]$36 = 50
+// lldbr-check:(i32) *hh = 50
 
 // lldb-command:print ii
-// lldb-check:[...]$37 = 51
+// lldbg-check:[...]$37 = 51
+// lldbr-check:(i32) ii = 51
 
 // lldb-command:print *jj
-// lldb-check:[...]$38 = 52
+// lldbg-check:[...]$38 = 52
+// lldbr-check:(i32) *jj = 52
 
 // lldb-command:print kk
-// lldb-check:[...]$39 = 53
+// lldbg-check:[...]$39 = 53
+// lldbr-check:(f64) kk = 53
 
 // lldb-command:print ll
-// lldb-check:[...]$40 = 54
+// lldbg-check:[...]$40 = 54
+// lldbr-check:(isize) ll = 54
 
 // lldb-command:print mm
-// lldb-check:[...]$41 = 55
+// lldbg-check:[...]$41 = 55
+// lldbr-check:(f64) mm = 55
 
 // lldb-command:print *nn
-// lldb-check:[...]$42 = 56
+// lldbg-check:[...]$42 = 56
+// lldbr-check:(isize) *nn = 56
 
 
 #![allow(unused_variables)]
index 2e151577590b3647ded4c70aee82c8940b414c99..c5460c69944f1535128af557dec11aa821a44ce2 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 // lldb-command:run
 
 // lldb-command:print no_padding1
-// lldb-check:[...]$0 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
+// lldbg-check:[...]$0 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
+// lldbr-check:(evec_in_struct::NoPadding1) no_padding1 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
 // lldb-command:print no_padding2
-// lldb-check:[...]$1 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
+// lldbg-check:[...]$1 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
+// lldbr-check:(evec_in_struct::NoPadding2) no_padding2 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
 
 // lldb-command:print struct_internal_padding
-// lldb-check:[...]$2 = StructInternalPadding { x: [13, 14], y: [15, 16] }
+// lldbg-check:[...]$2 = StructInternalPadding { x: [13, 14], y: [15, 16] }
+// lldbr-check:(evec_in_struct::StructInternalPadding) struct_internal_padding = StructInternalPadding { x: [13, 14], y: [15, 16] }
 
 // lldb-command:print single_vec
-// lldb-check:[...]$3 = SingleVec { x: [17, 18, 19, 20, 21] }
+// lldbg-check:[...]$3 = SingleVec { x: [17, 18, 19, 20, 21] }
+// lldbr-check:(evec_in_struct::SingleVec) single_vec = SingleVec { x: [17, 18, 19, 20, 21] }
 
 // lldb-command:print struct_padded_at_end
-// lldb-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
+// lldbg-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
+// lldbr-check:(evec_in_struct::StructPaddedAtEnd) struct_padded_at_end = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 01901b2c42b8e74c693470b5fc1e526541897fad..2e6602c63ff707e2031b2e4142ba6535c658bf05 100644 (file)
 // lldb-command:run
 
 // lldb-command:print len
-// lldb-check:[...]$0 = 20
+// lldbg-check:[...]$0 = 20
+// lldbr-check:(i32) len = 20
 // lldb-command:print local0
-// lldb-check:[...]$1 = 19
+// lldbg-check:[...]$1 = 19
+// lldbr-check:(i32) local0 = 19
 // lldb-command:print local1
-// lldb-check:[...]$2 = true
+// lldbg-check:[...]$2 = true
+// lldbr-check:(bool) local1 = true
 // lldb-command:print local2
-// lldb-check:[...]$3 = 20.5
+// lldbg-check:[...]$3 = 20.5
+// lldbr-check:(f64) local2 = 20.5
 
 // lldb-command:continue
 
index c8f2e385a6e74fbac0dd2d4393743004d900678f..9fc03feec9b6dc5297ce3487561947fde752d592 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = 111102
+// lldbg-check:[...]$0 = 111102
+// lldbr-check:(isize) x = 111102
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$2 = 2000
+// lldbg-check:[...]$2 = 2000
+// lldbr-check:(i32) a = 2000
 // lldb-command:print b
-// lldb-check:[...]$3 = 3000
+// lldbg-check:[...]$3 = 3000
+// lldbr-check:(i64) b = 3000
 // lldb-command:continue
 
 
index f1bfc08915edd86258f6e1a0af53dcf2215fffed..89b0e4ca453bf5a573acab158e3a84210d1f4c5b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *t0
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(i32) *t0 = 1
 // lldb-command:print *t1
-// lldb-check:[...]$1 = 2.5
+// lldbg-check:[...]$1 = 2.5
+// lldbr-check:(f64) *t1 = 2.5
 // lldb-command:print ret
-// lldb-check:[...]$2 = ((1, 2.5), (2.5, 1))
+// lldbg-check:[...]$2 = ((1, 2.5), (2.5, 1))
+// lldbr-check:(((i32, f64), (f64, i32))) ret = { = { = 1 = 2.5 } = { = 2.5 = 1 } }
 // lldb-command:continue
 
 // lldb-command:print *t0
-// lldb-check:[...]$3 = 3.5
+// lldbg-check:[...]$3 = 3.5
+// lldbr-check:(f64) *t0 = 3.5
 // lldb-command:print *t1
-// lldb-check:[...]$4 = 4
+// lldbg-check:[...]$4 = 4
+// lldbr-check:(u16) *t1 = 4
 // lldb-command:print ret
-// lldb-check:[...]$5 = ((3.5, 4), (4, 3.5))
+// lldbg-check:[...]$5 = ((3.5, 4), (4, 3.5))
+// lldbr-check:(((f64, u16), (u16, f64))) ret = { = { = 3.5 = 4 } = { = 4 = 3.5 } }
 // lldb-command:continue
 
 // lldb-command:print *t0
-// lldb-check:[...]$6 = 5
+// lldbg-check:[...]$6 = 5
+// lldbr-check:(i32) *t0 = 5
 // lldb-command:print *t1
-// lldb-check:[...]$7 = Struct { a: 6, b: 7.5 }
+// lldbg-check:[...]$7 = Struct { a: 6, b: 7.5 }
+// lldbr-check:(generic_function::Struct) *t1 = Struct { a: 6, b: 7.5 }
 // lldb-command:print ret
-// lldb-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5))
+// lldbg-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5))
+// lldbr-check:(((i32, generic_function::Struct), (generic_function::Struct, i32))) ret = { = { = 5 = Struct { a: 6, b: 7.5 } } = { = Struct { a: 6, b: 7.5 } = 5 } }
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 79ae007a5006285820e37cc016dd47216911095c..ea6dc62eca9eb8278f2b689f64201b236aca5b73 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = -1
+// lldbg-check:[...]$0 = -1
+// lldbr-check:(i32) x = -1
 // lldb-command:print y
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i32) y = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = -1
+// lldbg-check:[...]$2 = -1
+// lldbr-check:(i32) x = -1
 // lldb-command:print y
-// lldb-check:[...]$3 = 2.5
+// lldbg-check:[...]$3 = 2.5
+// lldbr-check:(f64) y = 2.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = -2.5
+// lldbg-check:[...]$4 = -2.5
+// lldbr-check:(f64) x = -2.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 1
+// lldbg-check:[...]$5 = 1
+// lldbr-check:(i32) y = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = -2.5
+// lldbg-check:[...]$6 = -2.5
+// lldbr-check:(f64) x = -2.5
 // lldb-command:print y
-// lldb-check:[...]$7 = 2.5
+// lldbg-check:[...]$7 = 2.5
+// lldbr-check:(f64) y = 2.5
 // lldb-command:continue
 
 
index 4f3f6dfc821eef4d589405ed70559aaca94c3a3e..97bb9aa98e87b4dd95ef7c39887c95b8610b1cd4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
 
 // compile-flags:-g
 // min-lldb-version: 310
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(u16) arg2 = 2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(i16) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(i32) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(i64) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10.5
+// lldbg-check:[...]$14 = -10.5
+// lldbr-check:(f32) arg2 = -10.5
 // lldb-command:continue
 
 #![feature(box_syntax)]
index 35f00ce78717b59901fc5f8cd3cc26725e710c59..4e06a15e1cdf0000239a2f7ef8821ccdacbcab97 100644 (file)
 // lldb-command:run
 
 // lldb-command:print int_int
-// lldb-check:[...]$0 = AGenericStruct<i32, i32> { key: 0, value: 1 }
+// lldbg-check:[...]$0 = AGenericStruct<i32, i32> { key: 0, value: 1 }
+// lldbr-check:(generic_struct::AGenericStruct<i32, i32>) int_int = AGenericStruct<i32, i32> { key: 0, value: 1 }
 // lldb-command:print int_float
-// lldb-check:[...]$1 = AGenericStruct<i32, f64> { key: 2, value: 3.5 }
+// lldbg-check:[...]$1 = AGenericStruct<i32, f64> { key: 2, value: 3.5 }
+// lldbr-check:(generic_struct::AGenericStruct<i32, f64>) int_float = AGenericStruct<i32, f64> { key: 2, value: 3.5 }
 // lldb-command:print float_int
-// lldb-check:[...]$2 = AGenericStruct<f64, i32> { key: 4.5, value: 5 }
+// lldbg-check:[...]$2 = AGenericStruct<f64, i32> { key: 4.5, value: 5 }
+// lldbr-check:(generic_struct::AGenericStruct<f64, i32>) float_int = AGenericStruct<f64, i32> { key: 4.5, value: 5 }
 
 // lldb-command:print float_int_float
-// lldb-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
+// lldbg-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
+// lldbr-check:(generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>>) float_int_float = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 
 
 #![feature(omit_gdb_pretty_printer_section)]
index 012bd6140cdbe6470f3f54e92696cad08979c528..62bec28a022af0ab397827956926f5a7edd28fb9 100644 (file)
 // lldb-command:run
 
 // lldb-command:print case1
-// lldb-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbr-check:(generic_tuple_style_enum::Regular<u16, u32, u64>::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
 
 // lldb-command:print case2
-// lldb-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbr-check:(generic_tuple_style_enum::Regular<i16, i32, i64>::Case2) case2 = Regular<i16, i32, i64>::Case2 { generic_tuple_style_enum::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum::Regular<i16, i32, i64>::Case2: 286331153, generic_tuple_style_enum::Regular<i16, i32, i64>::Case3: 286331153 }
 
 // lldb-command:print case3
-// lldb-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbr-check:(generic_tuple_style_enum::Regular<i16, i32, i64>::Case3) case3 = Regular<i16, i32, i64>::Case3 { generic_tuple_style_enum::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum::Regular<i16, i32, i64>::Case2: 6438275382588823897 }
 
 // lldb-command:print univariant
-// lldb-check:[...]$3 = TheOnlyCase(-1)
+// lldbg-check:[...]$3 = TheOnlyCase(-1)
+// lldbr-check:(generic_tuple_style_enum::Univariant<i64>) univariant = { generic_tuple_style_enum::TheOnlyCase = { = -1 } }
 
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
index 2c75349e5c8c7b18c8252ca26bc6c0b38a5d97d2..e915bf137028b82589fe93d8769e7f9ee9b1cf0f 100644 (file)
 // lldb-command:run
 
 // lldb-command:print string1.length
-// lldb-check:[...]$0 = 48
+// lldbg-check:[...]$0 = 48
+// lldbr-check:(usize) length = 48
 // lldb-command:print string2.length
-// lldb-check:[...]$1 = 49
+// lldbg-check:[...]$1 = 49
+// lldbr-check:(usize) length = 49
 // lldb-command:print string3.length
-// lldb-check:[...]$2 = 50
+// lldbg-check:[...]$2 = 50
+// lldbr-check:(usize) length = 50
 
 // lldb-command:continue
 
index a971e06ed5ec211b4a94f3a461802ffd80027059..6c3988b127ec21ac05aff709c0835e4efed3e1a0 100644 (file)
 // lldb-command:run
 
 // lldb-command:print v
-// lldb-check:[...]$0 = vec![1, 2, 3]
+// lldbg-check:[...]$0 = vec![1, 2, 3]
+// lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
 // lldb-command:print zs
-// lldb-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
-// lldb-command:continue
+// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
+// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
+// lldbr-command:continue
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index e99e241411bfd3a56e83103bb71fc87bf07ea49f..7a3c30ed8e5d02598ecea2d244948e80390efc5b 100644 (file)
 
 // FIRST ITERATION
 // lldb-command:print x
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(i32) x = -1
 // lldb-command:continue
 
 // SECOND ITERATION
 // lldb-command:print x
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = -2
+// lldbg-check:[...]$3 = -2
+// lldbr-check:(i32) x = -2
 // lldb-command:continue
 
 // THIRD ITERATION
 // lldb-command:print x
-// lldb-check:[...]$4 = 3
+// lldbg-check:[...]$4 = 3
+// lldbr-check:(i32) x = 3
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = -3
+// lldbg-check:[...]$5 = -3
+// lldbr-check:(i32) x = -3
 // lldb-command:continue
 
 // AFTER LOOP
 // lldb-command:print x
-// lldb-check:[...]$6 = 1000000
+// lldbg-check:[...]$6 = 1000000
+// lldbr-check:(i32) x = 1000000
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 42e288321e1977366dc266b3701831558a1d4d73..1a21fe6c1a98c35fc73b36f7b1f4aa1bcfb90660 100644 (file)
 
 // BEFORE if
 // lldb-command:print x
-// lldb-check:[...]$0 = 999
+// lldbg-check:[...]$0 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // AT BEGINNING of 'then' block
 // lldb-command:print x
-// lldb-check:[...]$2 = 999
+// lldbg-check:[...]$2 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$3 = -1
+// lldbg-check:[...]$3 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // AFTER 1st redeclaration of 'x'
 // lldb-command:print x
-// lldb-check:[...]$4 = 1001
+// lldbg-check:[...]$4 = 1001
+// lldbr-check:(i32) x = 1001
 // lldb-command:print y
-// lldb-check:[...]$5 = -1
+// lldbg-check:[...]$5 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // AFTER 2st redeclaration of 'x'
 // lldb-command:print x
-// lldb-check:[...]$6 = 1002
+// lldbg-check:[...]$6 = 1002
+// lldbr-check:(i32) x = 1002
 // lldb-command:print y
-// lldb-check:[...]$7 = 1003
+// lldbg-check:[...]$7 = 1003
+// lldbr-check:(i32) y = 1003
 // lldb-command:continue
 
 // AFTER 1st if expression
 // lldb-command:print x
-// lldb-check:[...]$8 = 999
+// lldbg-check:[...]$8 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$9 = -1
+// lldbg-check:[...]$9 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // BEGINNING of else branch
 // lldb-command:print x
-// lldb-check:[...]$10 = 999
+// lldbg-check:[...]$10 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$11 = -1
+// lldbg-check:[...]$11 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // BEGINNING of else branch
 // lldb-command:print x
-// lldb-check:[...]$12 = 1004
+// lldbg-check:[...]$12 = 1004
+// lldbr-check:(i32) x = 1004
 // lldb-command:print y
-// lldb-check:[...]$13 = 1005
+// lldbg-check:[...]$13 = 1005
+// lldbr-check:(i32) y = 1005
 // lldb-command:continue
 
 // BEGINNING of else branch
 // lldb-command:print x
-// lldb-check:[...]$14 = 999
+// lldbg-check:[...]$14 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$15 = -1
+// lldbg-check:[...]$15 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 597d9837aadcffb3e5571fac494ad60e4596497a..3c10039e76abfb93b25b9dfe1a3122dbff8aa549 100644 (file)
 // lldb-command:run
 
 // lldb-command:print shadowed
-// lldb-check:[...]$0 = 231
+// lldbg-check:[...]$0 = 231
+// lldbr-check:(i32) shadowed = 231
 // lldb-command:print not_shadowed
-// lldb-check:[...]$1 = 232
+// lldbg-check:[...]$1 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$2 = 233
+// lldbg-check:[...]$2 = 233
+// lldbr-check:(i32) shadowed = 233
 // lldb-command:print not_shadowed
-// lldb-check:[...]$3 = 232
+// lldbg-check:[...]$3 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:print local_to_arm
-// lldb-check:[...]$4 = 234
+// lldbg-check:[...]$4 = 234
+// lldbr-check:(i32) local_to_arm = 234
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$5 = 236
+// lldbg-check:[...]$5 = 236
+// lldbr-check:(i32) shadowed = 236
 // lldb-command:print not_shadowed
-// lldb-check:[...]$6 = 232
+// lldbg-check:[...]$6 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$7 = 237
+// lldbg-check:[...]$7 = 237
+// lldbr-check:(isize) shadowed = 237
 // lldb-command:print not_shadowed
-// lldb-check:[...]$8 = 232
+// lldbg-check:[...]$8 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:print local_to_arm
-// lldb-check:[...]$9 = 238
+// lldbg-check:[...]$9 = 238
+// lldbr-check:(isize) local_to_arm = 238
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$10 = 239
+// lldbg-check:[...]$10 = 239
+// lldbr-check:(isize) shadowed = 239
 // lldb-command:print not_shadowed
-// lldb-check:[...]$11 = 232
+// lldbg-check:[...]$11 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$12 = 241
+// lldbg-check:[...]$12 = 241
+// lldbr-check:(isize) shadowed = 241
 // lldb-command:print not_shadowed
-// lldb-check:[...]$13 = 232
+// lldbg-check:[...]$13 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$14 = 243
+// lldbg-check:[...]$14 = 243
+// lldbr-check:(i32) shadowed = 243
 // lldb-command:print *local_to_arm
-// lldb-check:[...]$15 = 244
+// lldbg-check:[...]$15 = 244
+// lldbr-check:(i32) *local_to_arm = 244
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$16 = 231
+// lldbg-check:[...]$16 = 231
+// lldbr-check:(i32) shadowed = 231
 // lldb-command:print not_shadowed
-// lldb-check:[...]$17 = 232
+// lldbg-check:[...]$17 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 0a8d3b61a8d8db681aad922b0e89a6f475d705ce..fec9d9af1bacab03286c78a2066d7f7157fae9cf 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 1000
+// lldbg-check:[...]$2 = 1000
+// lldbr-check:(isize) x = 1000
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 2.5
+// lldbg-check:[...]$3 = 2.5
+// lldbr-check:(f64) x = 2.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = true
+// lldbg-check:[...]$4 = true
+// lldbr-check:(bool) x = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = false
+// lldbg-check:[...]$5 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index e55088afd7d9fc739e2c21fcd06482d0159591c5..d160b0250cf32da9ddaf4e76c74406c28489b1ee 100644 (file)
 
 // FIRST ITERATION
 // lldb-command:print x
-// lldb-check:[...]$0 = 0
+// lldbg-check:[...]$0 = 0
+// lldbr-check:(i32) x = 0
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 101
+// lldbg-check:[...]$2 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 101
+// lldbg-check:[...]$3 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = -987
+// lldbg-check:[...]$4 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = 101
+// lldbg-check:[...]$5 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 
 // SECOND ITERATION
 // lldb-command:print x
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$7 = 2
+// lldbg-check:[...]$7 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 102
+// lldbg-check:[...]$8 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$9 = 102
+// lldbg-check:[...]$9 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$10 = -987
+// lldbg-check:[...]$10 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$11 = 102
+// lldbg-check:[...]$11 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$12 = 2
+// lldbg-check:[...]$12 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 70dece865ece02fd36a64a5cede9d9e8fc157172..574752d728f6f7704be6d6241dfaf0bf0a801f80 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 1000
+// lldbg-check:[...]$2 = 1000
+// lldbr-check:(isize) x = 1000
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 2.5
+// lldbg-check:[...]$3 = 2.5
+// lldbr-check:(f64) x = 2.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = true
+// lldbg-check:[...]$4 = true
+// lldbr-check:(bool) x = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = false
+// lldbg-check:[...]$5 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 
index 38d8b75a644fd2d825d8e681d5e3e5baa0ae60aa..7bc0409f2bb02e71098458e7dc833a7b913b532c 100644 (file)
 
 // FIRST ITERATION
 // lldb-command:print x
-// lldb-check:[...]$0 = 0
+// lldbg-check:[...]$0 = 0
+// lldbr-check:(i32) x = 0
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 101
+// lldbg-check:[...]$2 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 101
+// lldbg-check:[...]$3 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = -987
+// lldbg-check:[...]$4 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = 101
+// lldbg-check:[...]$5 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 
 // SECOND ITERATION
 // lldb-command:print x
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$7 = 2
+// lldbg-check:[...]$7 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 102
+// lldbg-check:[...]$8 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$9 = 102
+// lldbg-check:[...]$9 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$10 = -987
+// lldbg-check:[...]$10 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$11 = 102
+// lldbg-check:[...]$11 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$12 = 2
+// lldbg-check:[...]$12 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 32d775168692b8982e23f92533ee35b751fed896..4e88f65ad1d00b1065ddf4d4ee82f9361d5fb452 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 10
+// lldbg-check:[...]$0 = 10
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$1 = 34
+// lldbg-check:[...]$1 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$2 = 890242
+// lldbg-check:[...]$2 = 890242
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$3 = 34
+// lldbg-check:[...]$3 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$4 = 10
+// lldbg-check:[...]$4 = 10
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$5 = 34
+// lldbg-check:[...]$5 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$6 = 102
+// lldbg-check:[...]$6 = 102
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$7 = 34
+// lldbg-check:[...]$7 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
-// lldb-command:print a
-// lldb-check:[...]$8 = 110
-// lldb-command:print b
-// lldb-check:[...]$9 = 34
-// lldb-command:continue
-
-// lldb-command:print a
-// lldb-check:[...]$10 = 10
-// lldb-command:print b
-// lldb-check:[...]$11 = 34
-// lldb-command:continue
-
-// lldb-command:print a
-// lldb-check:[...]$12 = 10
-// lldb-command:print b
-// lldb-check:[...]$13 = 34
-// lldb-command:print c
-// lldb-check:[...]$14 = 400
-// lldb-command:continue
+// Don't test this with rust-enabled lldb for now; see issue #48807
+// lldbg-command:print a
+// lldbg-check:[...]$8 = 110
+// lldbg-command:print b
+// lldbg-check:[...]$9 = 34
+// lldbg-command:continue
+
+// lldbg-command:print a
+// lldbg-check:[...]$10 = 10
+// lldbg-command:print b
+// lldbg-check:[...]$11 = 34
+// lldbg-command:continue
+
+// lldbg-command:print a
+// lldbg-check:[...]$12 = 10
+// lldbg-command:print b
+// lldbg-check:[...]$13 = 34
+// lldbg-command:print c
+// lldbg-check:[...]$14 = 400
+// lldbg-command:continue
 
 
 #![feature(omit_gdb_pretty_printer_section)]
index e76f9da1c2505350950064d7ee17ba3e22b2ba43..9cb2a4c546efaab724cfb7c10b5fa24760cab263 100644 (file)
 
 // STRUCT EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$0 = -1
+// lldbg-check:[...]$0 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$1 = 10
+// lldbg-check:[...]$1 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$2 = 11
+// lldbg-check:[...]$2 = 11
+// lldbr-check:(isize) val = 11
 // lldb-command:print ten
-// lldb-check:[...]$3 = 10
+// lldbg-check:[...]$3 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$4 = -1
+// lldbg-check:[...]$4 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$5 = 10
+// lldbg-check:[...]$5 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // FUNCTION CALL
 // lldb-command:print val
-// lldb-check:[...]$6 = -1
+// lldbg-check:[...]$6 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$7 = 10
+// lldbg-check:[...]$7 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$8 = 12
+// lldbg-check:[...]$8 = 12
+// lldbr-check:(isize) val = 12
 // lldb-command:print ten
-// lldb-check:[...]$9 = 10
+// lldbg-check:[...]$9 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$10 = -1
+// lldbg-check:[...]$10 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$11 = 10
+// lldbg-check:[...]$11 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // TUPLE EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$12 = -1
+// lldbg-check:[...]$12 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$13 = 10
+// lldbg-check:[...]$13 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$14 = 13
+// lldbg-check:[...]$14 = 13
+// lldbr-check:(isize) val = 13
 // lldb-command:print ten
-// lldb-check:[...]$15 = 10
+// lldbg-check:[...]$15 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$16 = -1
+// lldbg-check:[...]$16 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$17 = 10
+// lldbg-check:[...]$17 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // VEC EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$18 = -1
+// lldbg-check:[...]$18 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$19 = 10
+// lldbg-check:[...]$19 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$20 = 14
+// lldbg-check:[...]$20 = 14
+// lldbr-check:(isize) val = 14
 // lldb-command:print ten
-// lldb-check:[...]$21 = 10
+// lldbg-check:[...]$21 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$22 = -1
+// lldbg-check:[...]$22 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$23 = 10
+// lldbg-check:[...]$23 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // REPEAT VEC EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$24 = -1
+// lldbg-check:[...]$24 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$25 = 10
+// lldbg-check:[...]$25 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$26 = 15
+// lldbg-check:[...]$26 = 15
+// lldbr-check:(isize) val = 15
 // lldb-command:print ten
-// lldb-check:[...]$27 = 10
+// lldbg-check:[...]$27 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$28 = -1
+// lldbg-check:[...]$28 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$29 = 10
+// lldbg-check:[...]$29 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // ASSIGNMENT EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$30 = -1
+// lldbg-check:[...]$30 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$31 = 10
+// lldbg-check:[...]$31 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$32 = 16
+// lldbg-check:[...]$32 = 16
+// lldbr-check:(isize) val = 16
 // lldb-command:print ten
-// lldb-check:[...]$33 = 10
+// lldbg-check:[...]$33 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$34 = -1
+// lldbg-check:[...]$34 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$35 = 10
+// lldbg-check:[...]$35 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 
 // ARITHMETIC EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$36 = -1
+// lldbg-check:[...]$36 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$37 = 10
+// lldbg-check:[...]$37 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$38 = 17
+// lldbg-check:[...]$38 = 17
+// lldbr-check:(isize) val = 17
 // lldb-command:print ten
-// lldb-check:[...]$39 = 10
+// lldbg-check:[...]$39 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$40 = -1
+// lldbg-check:[...]$40 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$41 = 10
+// lldbg-check:[...]$41 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // INDEX EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$42 = -1
+// lldbg-check:[...]$42 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$43 = 10
+// lldbg-check:[...]$43 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$44 = 18
+// lldbg-check:[...]$44 = 18
+// lldbr-check:(isize) val = 18
 // lldb-command:print ten
-// lldb-check:[...]$45 = 10
+// lldbg-check:[...]$45 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$46 = -1
+// lldbg-check:[...]$46 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$47 = 10
+// lldbg-check:[...]$47 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 20d419b4ac088357c00520dc58cbc8fe0079cd17..57238961e3fa3dae052fddf17acd3ba4559422dd 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(method_on_generic_struct::Struct<(u32, i32)>) self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(method_on_generic_struct::Struct<f64>) self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index c7546fe2221ff60365d8e6e1b7ca460f791bb73e..e64962593dfcd066406f91baf1ceb302c48fa5d5 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbr-check:(method_on_struct::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbr-check:(method_on_struct::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index 1dc37bb06ac40eadc8b9668febd69ec21ced572e..4c1e111d3b81dcbcec2a269c128842159560e661 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbr-check:(method_on_trait::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbr-check:(method_on_trait::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index dac762ae0c35bde7d36881afac4369a9bf2452dd..cef7a1cbf1b569c5baedf2c2acc3085f426adeaf 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = TupleStruct(100, -100.5)
+// lldbg-check:[...]$0 = TupleStruct(100, -100.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { = 100 = -100.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = TupleStruct(100, -100.5)
+// lldbg-check:[...]$3 = TupleStruct(100, -100.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { = 100 = -100.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = TupleStruct(200, -200.5)
+// lldbg-check:[...]$6 = TupleStruct(200, -200.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { = 200 = -200.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = TupleStruct(200, -200.5)
+// lldbg-check:[...]$9 = TupleStruct(200, -200.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { = 200 = -200.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = TupleStruct(200, -200.5)
+// lldbg-check:[...]$12 = TupleStruct(200, -200.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { = 200 = -200.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index f4f9f92396f2c20d3fb822eba05b41b247cc116a..7f370954b9053e00b564565ea28c80219d911405 100644 (file)
 // lldb-command:run
 
 // lldb-command:print xxx
-// lldb-check:[...]$0 = 12345
+// lldbg-check:[...]$0 = 12345
+// lldbr-check:(u32) xxx = 12345
 // lldb-command:continue
 
 // lldb-command:print yyy
-// lldb-check:[...]$1 = 67890
+// lldbg-check:[...]$1 = 67890
+// lldbr-check:(u64) yyy = 67890
 // lldb-command:continue
 
 
index 71ba1bcea306a1fac71d64832bd03342e851cf37..b2327e494e7d1359899113199117f409f22a48a5 100644 (file)
 // lldb-command:run
 
 // lldb-command:print abc
-// lldb-check:[...]$0 = 10101
+// lldbg-check:[...]$0 = 10101
+// lldbr-check:(i32) abc = 10101
 // lldb-command:continue
 
 // lldb-command:print abc
-// lldb-check:[...]$1 = 20202
+// lldbg-check:[...]$1 = 20202
+// lldbr-check:(i32) abc = 20202
 // lldb-command:continue
 
 // lldb-command:print abc
-// lldb-check:[...]$2 = 30303
+// lldbg-check:[...]$2 = 30303
+// lldbr-check:(i32) abc = 30303
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 7a1b7b19d9f5d1cc5db9d95f3306a268226754eb..d78ef0292c16042279952c016ad60ecbac244c44 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 10101
+// lldbg-check:[...]$0 = 10101
+// lldbr-check:(i32) a = 10101
 // lldb-command:continue
 
 // lldb-command:print b
-// lldb-check:[...]$1 = 20202
+// lldbg-check:[...]$1 = 20202
+// lldbr-check:(i32) b = 20202
 // lldb-command:continue
 
 // lldb-command:print c
-// lldb-check:[...]$2 = 30303
+// lldbg-check:[...]$2 = 30303
+// lldbr-check:(i32) c = 30303
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 462e1c59aea227929d1ea40698dc911925fa4db5..91f0e14157ee30c2f5ab65df06a48acb667058c5 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:print y
-// lldb-check:[...]$3 = true
+// lldbg-check:[...]$3 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldbg-check:[...]$5 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = true
+// lldbg-check:[...]$6 = true
+// lldbr-check:(bool) x = true
 // lldb-command:print y
-// lldb-check:[...]$7 = 2220
+// lldbg-check:[...]$7 = 2220
+// lldbr-check:(i32) y = 2220
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 203203.5
+// lldbg-check:[...]$8 = 203203.5
+// lldbr-check:(f64) x = 203203.5
 // lldb-command:print y
-// lldb-check:[...]$9 = 2220
+// lldbg-check:[...]$9 = 2220
+// lldbr-check:(i32) y = 2220
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$10 = 10.5
+// lldbg-check:[...]$10 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$11 = 20
+// lldbg-check:[...]$11 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 50bd857d460763c766cc7f87eda744e7ab153a9a..d5273d53dc59a17b5002a291a8b332d0ad14041b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print packed
-// lldb-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbg-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbr-check:(packed_struct_with_destructor::Packed) packed = Packed { x: 123, y: 234, z: 345 }
 
 // lldb-command:print packedInPacked
-// lldb-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbg-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInPacked) packedInPacked = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
 
 // lldb-command:print packedInUnpacked
-// lldb-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbg-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInUnpacked) packedInUnpacked = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
 
 // lldb-command:print unpackedInPacked
-// lldb-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
+// lldbg-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
+// lldbr-check:(packed_struct_with_destructor::UnpackedInPacked) unpackedInPacked = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
 
 // lldb-command:print packedInPackedWithDrop
-// lldb-check:[...]$4 = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
+// lldbg-check:[...]$4 = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInPackedWithDrop) packedInPackedWithDrop = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
 
 // lldb-command:print packedInUnpackedWithDrop
-// lldb-check:[...]$5 = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
+// lldbg-check:[...]$5 = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInUnpackedWithDrop) packedInUnpackedWithDrop = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
 
 // lldb-command:print unpackedInPackedWithDrop
-// lldb-check:[...]$6 = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
+// lldbg-check:[...]$6 = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
+// lldbr-check:(packed_struct_with_destructor::UnpackedInPackedWithDrop) unpackedInPackedWithDrop = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
 
 // lldb-command:print deeplyNested
-// lldb-check:[...]$7 = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
+// lldbg-check:[...]$7 = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
+// lldbr-check:(packed_struct_with_destructor::DeeplyNested) deeplyNested = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
 
 
 #![allow(unused_variables)]
index 16e6371a9c0a9944db7f6989d8061dd26492f5ff..2ed3711fbde80a6bcf7998b7a7333e1b58eacec3 100644 (file)
 // lldb-command:run
 
 // lldb-command:print packed
-// lldb-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbg-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbr-check:(packed_struct::Packed) packed = Packed { x: 123, y: 234, z: 345 }
 
 // lldb-command:print packedInPacked
-// lldb-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbg-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbr-check:(packed_struct::PackedInPacked) packedInPacked = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
 
 // lldb-command:print packedInUnpacked
-// lldb-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbg-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbr-check:(packed_struct::PackedInUnpacked) packedInUnpacked = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
 
 // lldb-command:print unpackedInPacked
-// lldb-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
+// lldbg-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
+// lldbr-check:(packed_struct::UnpackedInPacked) unpackedInPacked = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
 
 // lldb-command:print sizeof(packed)
-// lldb-check:[...]$4 = 14
+// lldbg-check:[...]$4 = 14
+// lldbr-check:(usize) = 14
 
 // lldb-command:print sizeof(packedInPacked)
-// lldb-check:[...]$5 = 40
+// lldbg-check:[...]$5 = 40
+// lldbr-check:(usize) = 40
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 796d122cd66baed906c47425376a11cc60e29514..a9acaab7dfc06c330580e7eecbd87c634b90070b 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbr-check:(self_in_default_method::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbr-check:(self_in_default_method::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 #![feature(box_syntax)]
index b07d7ca5fb7b7c34de917910bda563c3fbf849eb..2613300b8d996000ea1fda80b0ac9f3d5135b0e2 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 987 }
+// lldbg-check:[...]$0 = Struct { x: 987 }
+// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 987 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(u16) arg2 = 2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 987 }
+// lldbg-check:[...]$3 = Struct { x: 987 }
+// lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 987 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(i16) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 879 }
+// lldbg-check:[...]$6 = Struct { x: 879 }
+// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(i32) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 879 }
+// lldbg-check:[...]$9 = Struct { x: 879 }
+// lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 879 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(i64) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 879 }
+// lldbg-check:[...]$12 = Struct { x: 879 }
+// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10.5
+// lldbg-check:[...]$14 = -10.5
+// lldbr-check:(f32) arg2 = -10.5
 // lldb-command:continue
 
 #![feature(box_syntax)]
index baf782b7e678a182f67613cd1daff1b6f1fc91d3..49d876d4530b91245892bae31e1bd06fcb80a695 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:print y
-// lldb-check:[...]$3 = true
+// lldbg-check:[...]$3 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldbg-check:[...]$5 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 
index 6e4d94d26cdeb0a66889e6df60ea48f15de5cb8d..3a8f6d3b70d16b5d692e905f268d1b6e899e037b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:print y
-// lldb-check:[...]$3 = true
+// lldbg-check:[...]$3 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldbg-check:[...]$5 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = 10.5
+// lldbg-check:[...]$6 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$7 = 20
+// lldbg-check:[...]$7 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 11.5
+// lldbg-check:[...]$8 = 11.5
+// lldbr-check:(f64) x = 11.5
 // lldb-command:print y
-// lldb-check:[...]$9 = 20
+// lldbg-check:[...]$9 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 5f9a4fd08053404d685e708d876db3bb490a064c..935a0bb2ae443bba450a1e08917add6c7b52e839 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 10
+// lldbg-check:[...]$3 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = 10
+// lldbg-check:[...]$5 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = false
+// lldbg-check:[...]$6 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 
index 8fdf204d30ab57761e5a6b3890c2cbe855dd793e..e27324fe330663229473b30cdd3863135f5f6528 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // lldb-command:run
 
 // lldb-command:print no_padding16
-// lldb-check:[...]$0 = NoPadding16 { x: 10000, y: -10001 }
+// lldbg-check:[...]$0 = NoPadding16 { x: 10000, y: -10001 }
+// lldbr-check:(simple_struct::NoPadding16) no_padding16 = NoPadding16 { x: 10000, y: -10001 }
 
 // lldb-command:print no_padding32
-// lldb-check:[...]$1 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
+// lldbg-check:[...]$1 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
+// lldbr-check:(simple_struct::NoPadding32) no_padding32 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
 
 // lldb-command:print no_padding64
-// lldb-check:[...]$2 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
+// lldbg-check:[...]$2 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
+// lldbr-check:(simple_struct::NoPadding64) no_padding64 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
 
 // lldb-command:print no_padding163264
-// lldb-check:[...]$3 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
+// lldbg-check:[...]$3 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
+// lldbr-check:(simple_struct::NoPadding163264) no_padding163264 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
 
 // lldb-command:print internal_padding
-// lldb-check:[...]$4 = InternalPadding { x: 10012, y: -10013 }
+// lldbg-check:[...]$4 = InternalPadding { x: 10012, y: -10013 }
+// lldbr-check:(simple_struct::InternalPadding) internal_padding = InternalPadding { x: 10012, y: -10013 }
 
 // lldb-command:print padding_at_end
-// lldb-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 }
+// lldbg-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 }
+// lldbr-check:(simple_struct::PaddingAtEnd) padding_at_end = PaddingAtEnd { x: -10014, y: 10015 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index 8f69672c888440e30986dfd28e2d2f1ea7b65b47..ea0fd4e37fd422299c4effb24a2a96ff488b81b7 100644 (file)
 // lldb-command:run
 
 // lldb-command:print/d noPadding8
-// lldb-check:[...]$0 = (-100, 100)
+// lldbg-check:[...]$0 = (-100, 100)
+// lldbr-check:((i8, u8)) noPadding8 = { = -100 -100 = 100 100 }
 // lldb-command:print noPadding16
-// lldb-check:[...]$1 = (0, 1, 2)
+// lldbg-check:[...]$1 = (0, 1, 2)
+// lldbr-check:((i16, i16, u16)) noPadding16 = { = 0 = 1 = 2 }
 // lldb-command:print noPadding32
-// lldb-check:[...]$2 = (3, 4.5, 5)
+// lldbg-check:[...]$2 = (3, 4.5, 5)
+// lldbr-check:((i32, f32, u32)) noPadding32 = { = 3 = 4.5 = 5 }
 // lldb-command:print noPadding64
-// lldb-check:[...]$3 = (6, 7.5, 8)
+// lldbg-check:[...]$3 = (6, 7.5, 8)
+// lldbr-check:((i64, f64, u64)) noPadding64 = { = 6 = 7.5 = 8 }
 
 // lldb-command:print internalPadding1
-// lldb-check:[...]$4 = (9, 10)
+// lldbg-check:[...]$4 = (9, 10)
+// lldbr-check:((i16, i32)) internalPadding1 = { = 9 = 10 }
 // lldb-command:print internalPadding2
-// lldb-check:[...]$5 = (11, 12, 13, 14)
+// lldbg-check:[...]$5 = (11, 12, 13, 14)
+// lldbr-check:((i16, i32, u32, u64)) internalPadding2 = { = 11 = 12 = 13 = 14 }
 
 // lldb-command:print paddingAtEnd
-// lldb-check:[...]$6 = (15, 16)
+// lldbg-check:[...]$6 = (15, 16)
+// lldbr-check:((i32, i16)) paddingAtEnd = { = 15 = 16 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index dab4ab515d9954e4c931f5462b69b1fac776825d..75a67c6b84bce623019fcd440808c1f12fc560ab 100644 (file)
 
 // STRUCT
 // lldb-command:print arg1
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) arg1 = 1
 // lldb-command:print arg2
-// lldb-check:[...]$1 = 2
+// lldbg-check:[...]$1 = 2
+// lldbr-check:(isize) arg2 = 2
 // lldb-command:continue
 
 // ENUM
 // lldb-command:print arg1
-// lldb-check:[...]$2 = -3
+// lldbg-check:[...]$2 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$3 = 4.5
+// lldbg-check:[...]$3 = 4.5
+// lldbr-check:(f64) arg2 = 4.5
 // lldb-command:print arg3
-// lldb-check:[...]$4 = 5
+// lldbg-check:[...]$4 = 5
+// lldbr-check:(usize) arg3 = 5
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 46524cf1d029a98b1180f6831ec6be2dc904382c..129500860c82f47888100915a5846e675c70a12c 100644 (file)
 // lldb-command:run
 
 // lldb-command:print three_simple_structs
-// lldb-check:[...]$0 = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
+// lldbg-check:[...]$0 = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
+// lldbr-check:(struct_in_struct::ThreeSimpleStructs) three_simple_structs = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
 
 // lldb-command:print internal_padding_parent
-// lldb-check:[...]$1 = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
+// lldbg-check:[...]$1 = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
+// lldbr-check:(struct_in_struct::InternalPaddingParent) internal_padding_parent = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
 
 // lldb-command:print padding_at_end_parent
-// lldb-check:[...]$2 = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
+// lldbg-check:[...]$2 = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
+// lldbr-check:(struct_in_struct::PaddingAtEndParent) padding_at_end_parent = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
 
 // lldb-command:print mixed
-// lldb-check:[...]$3 = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
+// lldbg-check:[...]$3 = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
+// lldbr-check:(struct_in_struct::Mixed) mixed = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
 
 // lldb-command:print bag
-// lldb-check:[...]$4 = Bag { x: Simple { x: 22 } }
+// lldbg-check:[...]$4 = Bag { x: Simple { x: 22 } }
+// lldbr-check:(struct_in_struct::Bag) bag = Bag { x: Simple { x: 22 } }
 
 // lldb-command:print bag_in_bag
-// lldb-check:[...]$5 = BagInBag { x: Bag { x: Simple { x: 23 } } }
+// lldbg-check:[...]$5 = BagInBag { x: Bag { x: Simple { x: 23 } } }
+// lldbr-check:(struct_in_struct::BagInBag) bag_in_bag = BagInBag { x: Bag { x: Simple { x: 23 } } }
 
 // lldb-command:print tjo
-// lldb-check:[...]$6 = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
+// lldbg-check:[...]$6 = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
+// lldbr-check:(struct_in_struct::ThatsJustOverkill) tjo = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
 
 // lldb-command:print tree
-// lldb-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
+// lldbg-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
+// lldbr-check:(struct_in_struct::Tree) tree = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 3fd4cf57b2a802c63847a444a0991f3af3f77e28..efa415c7100b8e144582325b1ae74ba2734b2cdc 100644 (file)
 
 // lldb-command:run
 // lldb-command:p struct1
-// lldb-check:(struct_namespace::Struct1) $0 = [...]
+// lldbg-check:(struct_namespace::Struct1) $0 = [...]
+// lldbr-check:(struct_namespace::Struct1) struct1 = Struct1 { a: 0, b: 1 }
 // lldb-command:p struct2
-// lldb-check:(struct_namespace::Struct2) $1 = [...]
+// lldbg-check:(struct_namespace::Struct2) $1 = [...]
+// lldbr-check:(struct_namespace::Struct2) struct2 = { = 2 }
 
 // lldb-command:p mod1_struct1
-// lldb-check:(struct_namespace::mod1::Struct1) $2 = [...]
+// lldbg-check:(struct_namespace::mod1::Struct1) $2 = [...]
+// lldbr-check:(struct_namespace::mod1::Struct1) mod1_struct1 = Struct1 { a: 3, b: 4 }
 // lldb-command:p mod1_struct2
-// lldb-check:(struct_namespace::mod1::Struct2) $3 = [...]
+// lldbg-check:(struct_namespace::mod1::Struct2) $3 = [...]
+// lldbr-check:(struct_namespace::mod1::Struct2) mod1_struct2 = { = 5 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index b156a3be699e3359490962ebe9c755824aaee5e3..36cd85fb4dc6503945c48f94bd5ad0026ad917fd 100644 (file)
 // lldb-command:run
 
 // lldb-command:print case1
-// lldb-check:[...]$0 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }
+// lldbg-check:[...]$0 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }
+// lldbr-check:(struct_style_enum::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 }
 
 // lldb-command:print case2
-// lldb-check:[...]$1 = Case2 { a: 0, b: 286331153, c: 286331153 }
+// lldbg-check:[...]$1 = Case2 { a: 0, b: 286331153, c: 286331153 }
+// lldbr-check:(struct_style_enum::Regular::Case2) case2 = Case2 { struct_style_enum::Regular::Case1: 0, struct_style_enum::Regular::Case2: 286331153, struct_style_enum::Regular::Case3: 286331153 }
 
 // lldb-command:print case3
-// lldb-check:[...]$2 = Case3 { a: 0, b: 6438275382588823897 }
+// lldbg-check:[...]$2 = Case3 { a: 0, b: 6438275382588823897 }
+// lldbr-check:(struct_style_enum::Regular::Case3) case3 = Case3 { struct_style_enum::Regular::Case1: 0, struct_style_enum::Regular::Case2: 6438275382588823897 }
 
 // lldb-command:print univariant
-// lldb-check:[...]$3 = TheOnlyCase { a: -1 }
+// lldbg-check:[...]$3 = TheOnlyCase { a: -1 }
+// lldbr-check:(struct_style_enum::Univariant) univariant = Univariant { struct_style_enum::TheOnlyCase: TheOnlyCase { a: -1 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index ab935a07d650fc3164fa47edd1673b35d8b4e3ea..f7722bb377531721a369ebbe0259b137d3c205b5 100644 (file)
 
 // lldb-command:run
 // lldb-command:print simple
-// lldb-check:[...]$0 = WithDestructor { x: 10, y: 20 }
+// lldbg-check:[...]$0 = WithDestructor { x: 10, y: 20 }
+// lldbr-check:(struct_with_destructor::WithDestructor) simple = WithDestructor { x: 10, y: 20 }
 
 // lldb-command:print noDestructor
-// lldb-check:[...]$1 = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbg-check:[...]$1 = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbr-check:(struct_with_destructor::NoDestructorGuarded) noDestructor = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
 
 // lldb-command:print withDestructor
-// lldb-check:[...]$2 = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbg-check:[...]$2 = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbr-check:(struct_with_destructor::WithDestructorGuarded) withDestructor = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
 
 // lldb-command:print nested
-// lldb-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
+// lldbg-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
+// lldbr-check:(struct_with_destructor::NestedOuter) nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 4ebc740b9c0f7a55c625666275a8cd4fae3a3cbb..79335a3d0e139e6fd393921fcf450105dbecafa4 100644 (file)
 // lldb-command:run
 
 // lldb-command:print no_padding1
-// lldb-check:[...]$0 = ((0, 1), 2, 3)
+// lldbg-check:[...]$0 = ((0, 1), 2, 3)
+// lldbr-check:(((u32, u32), u32, u32)) no_padding1 = { = { = 0 = 1 } = 2 = 3 }
 // lldb-command:print no_padding2
-// lldb-check:[...]$1 = (4, (5, 6), 7)
+// lldbg-check:[...]$1 = (4, (5, 6), 7)
+// lldbr-check:((u32, (u32, u32), u32)) no_padding2 = { = 4 = { = 5 = 6 } = 7 }
 // lldb-command:print no_padding3
-// lldb-check:[...]$2 = (8, 9, (10, 11))
+// lldbg-check:[...]$2 = (8, 9, (10, 11))
+// lldbr-check:((u32, u32, (u32, u32))) no_padding3 = { = 8 = 9 = { = 10 = 11 } }
 
 // lldb-command:print internal_padding1
-// lldb-check:[...]$3 = (12, (13, 14))
+// lldbg-check:[...]$3 = (12, (13, 14))
+// lldbr-check:((i16, (i32, i32))) internal_padding1 = { = 12 = { = 13 = 14 } }
 // lldb-command:print internal_padding2
-// lldb-check:[...]$4 = (15, (16, 17))
+// lldbg-check:[...]$4 = (15, (16, 17))
+// lldbr-check:((i16, (i16, i32))) internal_padding2 = { = 15 = { = 16 = 17 } }
 
 // lldb-command:print padding_at_end1
-// lldb-check:[...]$5 = (18, (19, 20))
+// lldbg-check:[...]$5 = (18, (19, 20))
+// lldbr-check:((i32, (i32, i16))) padding_at_end1 = { = 18 = { = 19 = 20 } }
 // lldb-command:print padding_at_end2
-// lldb-check:[...]$6 = ((21, 22), 23)
+// lldbg-check:[...]$6 = ((21, 22), 23)
+// lldbr-check:(((i32, i16), i32)) padding_at_end2 = { = { = 21 = 22 } = 23 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index aa644d8419b54f72a3aac5334cb1ac83eb639ffd..def48c84488dc333b7b3f05909536576d8cfc596 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 // lldb-command:run
 
 // lldb-command:print no_padding16
-// lldb-check:[...]$0 = NoPadding16(10000, -10001)
+// lldbg-check:[...]$0 = NoPadding16(10000, -10001)
+// lldbr-check:(tuple_struct::NoPadding16) no_padding16 = { = 10000 = -10001 }
 
 // lldb-command:print no_padding32
-// lldb-check:[...]$1 = NoPadding32(-10002, -10003.5, 10004)
+// lldbg-check:[...]$1 = NoPadding32(-10002, -10003.5, 10004)
+// lldbr-check:(tuple_struct::NoPadding32) no_padding32 = { = -10002 = -10003.5 = 10004 }
 
 // lldb-command:print no_padding64
-// lldb-check:[...]$2 = NoPadding64(-10005.5, 10006, 10007)
+// lldbg-check:[...]$2 = NoPadding64(-10005.5, 10006, 10007)
+// lldbr-check:(tuple_struct::NoPadding64) no_padding64 = { = -10005.5 = 10006 = 10007 }
 
 // lldb-command:print no_padding163264
-// lldb-check:[...]$3 = NoPadding163264(-10008, 10009, 10010, 10011)
+// lldbg-check:[...]$3 = NoPadding163264(-10008, 10009, 10010, 10011)
+// lldbr-check:(tuple_struct::NoPadding163264) no_padding163264 = { = -10008 = 10009 = 10010 = 10011 }
 
 // lldb-command:print internal_padding
-// lldb-check:[...]$4 = InternalPadding(10012, -10013)
+// lldbg-check:[...]$4 = InternalPadding(10012, -10013)
+// lldbr-check:(tuple_struct::InternalPadding) internal_padding = { = 10012 = -10013 }
 
 // lldb-command:print padding_at_end
-// lldb-check:[...]$5 = PaddingAtEnd(-10014, 10015)
+// lldbg-check:[...]$5 = PaddingAtEnd(-10014, 10015)
+// lldbr-check:(tuple_struct::PaddingAtEnd) padding_at_end = { = -10014 = 10015 }
 
 // This test case mainly makes sure that no field names are generated for tuple structs (as opposed
 // to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
index f36153d1f5c5a8eca5d52aa027edf3d4f559ce27..682e74601b0a11b7f15f2a3357ec22e175dd8c66 100644 (file)
 // lldb-command:run
 
 // lldb-command:print case1
-// lldb-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbr-check:(tuple_style_enum::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
 
 // lldb-command:print case2
-// lldb-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbr-check:(tuple_style_enum::Regular::Case2) case2 = Case2 { tuple_style_enum::Regular::Case1: 0, tuple_style_enum::Regular::Case2: 286331153, tuple_style_enum::Regular::Case3: 286331153 }
 
 // lldb-command:print case3
-// lldb-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbr-check:(tuple_style_enum::Regular::Case3) case3 = Case3 { tuple_style_enum::Regular::Case1: 0, tuple_style_enum::Regular::Case2: 6438275382588823897 }
 
 // lldb-command:print univariant
-// lldb-check:[...]$3 = TheOnlyCase(-1)
+// lldbg-check:[...]$3 = TheOnlyCase(-1)
+// lldbr-check:(tuple_style_enum::Univariant) univariant = { tuple_style_enum::TheOnlyCase = { = -1 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 622c7cf0d333423dd8784d42d18aac38c1f97ec2..7772127bad295ee012d121721d58050a5ab9435d 100644 (file)
 
 // lldb-command:run
 // lldb-command:print u
-// lldb-check:[...]$0 = U { a: ('\x02', '\x02'), b: 514 }
-// lldb-command:print union_smoke::SU
-// lldb-check:[...]$1 = U { a: ('\x01', '\x01'), b: 257 }
+// lldbg-check:[...]$0 = U { a: ('\x02', '\x02'), b: 514 }
+// lldbr-check:(union_smoke::U) u = { a = { = 2 = 2 } b = 514 }
+
+// Don't test this with rust-enabled lldb for now; see
+// https://github.com/rust-lang-nursery/lldb/issues/18
+// lldbg-command:print union_smoke::SU
+// lldbg-check:[...]$1 = U { a: ('\x01', '\x01'), b: 257 }
 
 #![allow(unused)]
 #![feature(omit_gdb_pretty_printer_section)]
index 5a99de7779cffd3972190b807d7981b2db6b3e68..6b62c304513944ea0ea0f7abd220493c0258d084 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *the_a
-// lldb-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbr-check:(unique_enum::ABC::TheA) *the_a = TheA { unique_enum::ABC::TheA: 0, unique_enum::ABC::TheB: 8970181431921507452 }
 
 // lldb-command:print *the_b
-// lldb-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbr-check:(unique_enum::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 }
 
 // lldb-command:print *univariant
-// lldb-check:[...]$2 = TheOnlyCase(123234)
+// lldbg-check:[...]$2 = TheOnlyCase(123234)
+// lldbr-check:(unique_enum::Univariant) *univariant = { unique_enum::TheOnlyCase = { = 123234 } }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index b9a1d73b6d8696de85d1c44237e1678be2e89562..02c836bb6ac47503590c65f59c1d46f64dbcf0b5 100644 (file)
 // lldb-command:run
 
 // lldb-command:print variable
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) variable = 1
 // lldb-command:print constant
-// lldb-check:[...]$1 = 2
+// lldbg-check:[...]$1 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$4 = 6
+// lldbg-check:[...]$4 = 6
+// lldbr-check:(isize) *owned = 6
 // lldb-command:print closure_local
-// lldb-check:[...]$5 = 8
+// lldbg-check:[...]$5 = 8
+// lldbr-check:(isize) closure_local = 8
 // lldb-command:continue
 
 // lldb-command:print variable
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(isize) variable = 1
 // lldb-command:print constant
-// lldb-check:[...]$7 = 2
+// lldbg-check:[...]$7 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$9 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$9 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$10 = 6
+// lldbg-check:[...]$10 = 6
+// lldbr-check:(isize) *owned = 6
 // lldb-command:print closure_local
-// lldb-check:[...]$11 = 8
+// lldbg-check:[...]$11 = 8
+// lldbr-check:(isize) closure_local = 8
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 9aeb3bc91336a67b17f9b6f4eb8a790c254fa034..a562584dfd028c18cfa07766d41929063348e78a 100644 (file)
 // lldb-command:run
 
 // lldb-command:print constant
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) constant = 1
 // lldb-command:print a_struct
-// lldb-check:[...]$1 = Struct { a: -2, b: 3.5, c: 4 }
+// lldbg-check:[...]$1 = Struct { a: -2, b: 3.5, c: 4 }
+// lldbr-check:(var_captured_in_sendable_closure::Struct) a_struct = Struct { a: -2, b: 3.5, c: 4 }
 // lldb-command:print *owned
-// lldb-check:[...]$2 = 5
+// lldbg-check:[...]$2 = 5
+// lldbr-check:(isize) *owned = 5
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index c795a095b9769a095d1ffb7a95a7cc185e24cbda..cf4eaf393e9562f8c9702bda3996a40430b1dee4 100644 (file)
 // lldb-command:run
 
 // lldb-command:print variable
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) variable = 1
 // lldb-command:print constant
-// lldb-check:[...]$1 = 2
+// lldbg-check:[...]$1 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$4 = 6
+// lldbg-check:[...]$4 = 6
+// lldbr-check:(isize) *owned = 6
 
 // lldb-command:continue
 
 // lldb-command:print variable
-// lldb-check:[...]$5 = 2
+// lldbg-check:[...]$5 = 2
+// lldbr-check:(isize) variable = 2
 // lldb-command:print constant
-// lldb-check:[...]$6 = 2
+// lldbg-check:[...]$6 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$7 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$7 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$9 = 6
+// lldbg-check:[...]$9 = 6
+// lldbr-check:(isize) *owned = 6
 
 #![feature(box_syntax)]
 #![allow(unused_variables)]
index 888d9b28506b3608b585018e0fd0a9824e8cce9a..39bf0c175ebcb7ea41eb7401ee965b3d42888f5a 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // ignore-windows
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 // lldb-command:run
 
 // lldb-command:print empty
-// lldb-check:[...]$0 = &[]
+// lldbg-check:[...]$0 = &[]
+// lldbr-check:(&[i64]) empty = &[]
 
 // lldb-command:print singleton
-// lldb-check:[...]$1 = &[1]
+// lldbg-check:[...]$1 = &[1]
+// lldbr-check:(&[i64]) singleton = &[1]
 
 // lldb-command:print multiple
-// lldb-check:[...]$2 = &[2, 3, 4, 5]
+// lldbg-check:[...]$2 = &[2, 3, 4, 5]
+// lldbr-check:(&[i64]) multiple = &[2, 3, 4, 5]
 
 // lldb-command:print slice_of_slice
-// lldb-check:[...]$3 = &[3, 4]
+// lldbg-check:[...]$3 = &[3, 4]
+// lldbr-check:(&[i64]) slice_of_slice = &[3, 4]
 
 // lldb-command:print padded_tuple
-// lldb-check:[...]$4 = &[(6, 7), (8, 9)]
+// lldbg-check:[...]$4 = &[(6, 7), (8, 9)]
+// lldbr-check:(&[(i32, i16)]) padded_tuple = { data_ptr = *0x555555554ff0 length = 2 }
 
 // lldb-command:print padded_struct
-// lldb-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
+// lldbg-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
+// lldbr-check:(&[vec_slices::AStruct]) padded_struct = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
 
 #![allow(dead_code, unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index dba947530fea8fdeac0451a9641f867d32c8bc81..752f3f1cba1ecec6e48b74cf815ff6fc59e72434 100644 (file)
@@ -28,7 +28,8 @@
 
 // lldb-command:run
 // lldb-command:print a
-// lldb-check:[...]$0 = [1, 2, 3]
+// lldbg-check:[...]$0 = [1, 2, 3]
+// lldbr-check:([i32; 3]) a = [1, 2, 3]
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 1bf740fdec6192beaf4cc5e25ed26d849193f876..a51498797e48fd87414ec77c0908fd546ecb1b95 100644 (file)
@@ -15,8 +15,6 @@
 
 // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes
 
-#![feature(min_const_fn)]
-
 static TEST_SIGNED: i128 = const_signed(-222);
 static TEST_UNSIGNED: u128 = const_unsigned(200);
 
index 235df8a6785d4d4d100d1d2d3afccaf165e8a845..f64981525b8102863185ab8e266ab9ca3ec630b9 100644 (file)
@@ -12,8 +12,6 @@
 
 // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O
 
-#![feature(min_const_fn)]
-
 static TEST_SIGNED: i128 = const_signed(-222);
 static TEST_UNSIGNED: u128 = const_unsigned(200);
 
index 30efe3b9ab2c48cd0fceaf3007e3a83b072f5b31..16b71f676e1fbaa2c524536e7f271440cfd0f606 100644 (file)
@@ -10,7 +10,6 @@
 
 // error-pattern:index out of bounds: the len is 5 but the index is 5
 
-#![feature(min_const_fn)]
 const fn test(x: usize) -> i32 {
     [42;5][x]
 }
index 08e2c35e0722c77cc4915822db6b50424a997ccb..3cd622a33b173afdbed2fb60bd59e4c7eb9aa46c 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(min_const_fn, rustc_attrs, rustc_private, step_trait)]
+#![feature(rustc_attrs, rustc_private, step_trait)]
 
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_serialize;
index 0cd9bad03af9ffd64dcca66599953b3ea17e0248..59da7580354669c369cfc7072f250dc61a18fa57 100644 (file)
@@ -170,6 +170,7 @@ macro_rules! test_with_borrow {
         async_closure,
         async_fn,
         async_fn_with_internal_borrow,
+        Foo::async_method,
         |x| {
             async move {
                 unsafe { await!(unsafe_async_fn(x)) }
index 6985a6527c874eb51562d2a2da695af198692421..c6ac35bfb10bc62cae20b3f28f10d2850ee8813e 100644 (file)
@@ -11,6 +11,5 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
 #![crate_type="rlib"]
-#![feature(min_const_fn)]
 
 pub const fn foo() -> usize { 22 }
index 78276f17e57da6120e48d309afd8a475a51e5cdb..5e05865aa1be137c5f4619f1d2b6a33397643ab4 100644 (file)
@@ -10,7 +10,6 @@
 
 // run-pass
 #![allow(dead_code)]
-#![feature(min_const_fn)]
 
 const fn add(x: usize, y: usize) -> usize {
     x + y
index 3ecb4fffba14ae025834351c90652f1b6f458fe1..cd136774a02c390819d1a31110471858a66a36c9 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // run-pass
-#![feature(min_const_fn)]
 
 struct Foo { value: u32 }
 
index 41198a901c29b3377c8a1ce73222f63760862ada..8944642d2d6383e506181e5323905e15cb5c6658 100644 (file)
@@ -11,8 +11,6 @@
 // run-pass
 // Test a call whose argument is the result of another call.
 
-#![feature(min_const_fn)]
-
 const fn sub(x: u32, y: u32) -> u32 {
     x - y
 }
index 1762c17e943c30072d41c9dad538d327e8fac61e..21e011cb17616cb8ce566cb59d97db2f3bed2265 100644 (file)
@@ -10,8 +10,6 @@
 
 // run-pass
 
-#![feature(min_const_fn)]
-
 struct A;
 
 impl A {
index b0e91e616a08ca2a9d5c3efccf2f8ccfacff52e7..095cdc09e060bed4ea187c6b48533a543fdcd11d 100644 (file)
@@ -10,7 +10,6 @@
 
 // run-pass
 #![allow(unreachable_patterns)]
-#![feature(min_const_fn)]
 
 #[derive(PartialEq, Eq)]
 enum Cake {
index 6732e4f14c8801cea25fe61e8173a3884fc5c3ae..d69e5ed930b91e4b19aa53e21b0f6fbd54381f09 100644 (file)
@@ -10,7 +10,6 @@
 
 // run-pass
 #![allow(dead_code)]
-#![feature(min_const_fn)]
 
 use std::mem;
 
index cb60b2fdf07697b4d454408d063fe4667ef6f7ff..8a2f862b5a001db5a32792b0e0a753a7e6be4457 100644 (file)
@@ -12,8 +12,6 @@
 #![allow(dead_code)]
 // A quick test of 'unsafe const fn' functionality
 
-#![feature(min_const_fn)]
-
 const unsafe fn dummy(v: u32) -> u32 {
     !v
 }
index b96ad2f40a57edcd02a2a5f63bbb237bd14eef6f..e2f7faa5955dcd2abe6f674d80e69f8700d9ab0a 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // run-pass
-#![feature(min_const_fn)]
 
 const FOO: isize = 10;
 const BAR: isize = 3;
index 40fdcda355fad1309580fdf2d301488dd23840b2..74a8ba64965fff37a7c3f390231b9de1f163edfe 100644 (file)
@@ -14,8 +14,6 @@
 
 // https://github.com/rust-lang/rust/issues/48279
 
-#![feature(min_const_fn)]
-
 #[derive(PartialEq, Eq)]
 pub struct NonZeroU32 {
     value: u32
index 1c6d72d530f07be47006568531d7995cd25810f0..e41ff906fd217651366132aeb11d6f34f9b8e230 100644 (file)
@@ -13,8 +13,6 @@
 
 // https://github.com/rust-lang/rust/issues/46114
 
-#![feature(min_const_fn)]
-
 #[derive(Eq, PartialEq)]
 struct A { value: u32 }
 
index e0020019523796a7a46971f883a1fc7158f2198f..933ec588614864ad3625c2a78b13af66f5faa7a3 100644 (file)
@@ -12,7 +12,6 @@
 
 // https://github.com/rust-lang/rust/issues/43754
 
-#![feature(min_const_fn)]
 const fn foo(x: usize) -> usize {
     return x;
 }
diff --git a/src/test/run-pass/impl-trait/existential-minimal.rs b/src/test/run-pass/impl-trait/existential-minimal.rs
deleted file mode 100644 (file)
index bae4c68..0000000
+++ /dev/null
@@ -1,15 +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.
-
-// run-pass
-
-fn main() {}
-
-fn foo() -> impl std::fmt::Debug { "cake" }
diff --git a/src/test/run-pass/impl-trait/issue-42479.rs b/src/test/run-pass/impl-trait/issue-42479.rs
deleted file mode 100644 (file)
index 1da5cd3..0000000
+++ /dev/null
@@ -1,27 +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.
-
-// run-pass
-
-use std::iter::once;
-
-struct Foo {
-    x: i32,
-}
-
-impl Foo {
-    fn inside(&self) -> impl Iterator<Item = &i32> {
-        once(&self.x)
-    }
-}
-
-fn main() {
-    println!("hi");
-}
diff --git a/src/test/run-pass/impl-trait/issue-49376.rs b/src/test/run-pass/impl-trait/issue-49376.rs
deleted file mode 100644 (file)
index 10379da..0000000
+++ /dev/null
@@ -1,31 +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.
-
-// run-pass
-
-// Tests for nested self-reference which caused a stack overflow.
-
-use std::fmt::Debug;
-use std::ops::*;
-
-fn gen() -> impl PartialOrd + PartialEq + Debug { }
-
-struct Bar {}
-trait Foo<T = Self> {}
-impl Foo for Bar {}
-
-fn foo() -> impl Foo {
-    Bar {}
-}
-
-fn test_impl_ops() -> impl Add + Sub + Mul + Div { 1 }
-fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign { 1 }
-
-fn main() {}
index 5351a40916b7d44df25f6e7c8bec63a0460fd13a..e5eafa5a5d154d2c69e7a9d5e5cf3578fdd2ef89 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(min_const_fn)]
 #![crate_type = "lib"]
 
 const fn foo(i: i32) -> i32 {
index 863d9e74abb284d1c895e6990d3ef4c2f083d0d1..ce28ebc53cd9e47e43e787efbd78d9c2d1d9b8b9 100644 (file)
@@ -10,7 +10,6 @@
 
 // run-pass
 #![allow(dead_code)]
-#![feature(min_const_fn)]
 struct A {
     field: usize,
 }
index 3ef1595b95887e3d5be23daf9f4ace72a812ea69..023b0e800f59f07ef7a415d2f674fd0746d45dc2 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // run-pass
-#![feature(min_const_fn)]
 
 const fn foo() -> *const i8 {
     b"foo" as *const _ as *const i8
index 578c22fe232216d18778c15d68d83e16adacf1a0..e63ba3acce3343d14302355e7f3ca53dabf1967e 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // run-pass
-#![feature(min_const_fn)]
 
 const fn foo() -> i64 {
     3
diff --git a/src/test/run-pass/issues/issue-49556.rs b/src/test/run-pass/issues/issue-49556.rs
deleted file mode 100644 (file)
index aeeb55d..0000000
+++ /dev/null
@@ -1,23 +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.
-
-// run-pass
-fn iter<'a>(data: &'a [usize]) -> impl Iterator<Item = usize> + 'a {
-    data.iter()
-        .map(
-            |x| x // fn(&'a usize) -> &'(ReScope) usize
-        )
-        .map(
-            |x| *x // fn(&'(ReScope) usize) -> usize
-        )
-}
-
-fn main() {
-}
index e33329092067e25edc3494a238af1099c26c94e6..2104f5ef08a7fc30178a8a85f2fcd811a7b4e0ee 100644 (file)
@@ -10,7 +10,6 @@
 
 // run-pass
 #![allow(dead_code)]
-#![feature(min_const_fn)]
 const fn f() -> usize {
     5
 }
diff --git a/src/test/run-pass/macros/macro-as-fn-body.rs b/src/test/run-pass/macros/macro-as-fn-body.rs
new file mode 100644 (file)
index 0000000..8c3c9fd
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// run-pass
+//
+// Description - ensure Interpolated blocks can act as valid function bodies
+// Covered cases: free functions, struct methods, and default trait functions
+
+macro_rules! def_fn {
+    ($body:block) => {
+        fn bar() $body
+    }
+}
+
+trait Foo {
+    def_fn!({ println!("foo"); });
+}
+
+struct Baz {}
+
+impl Foo for Baz {}
+
+struct Qux {}
+
+impl Qux {
+    def_fn!({ println!("qux"); });
+}
+
+def_fn!({ println!("quux"); });
+
+pub fn main() {
+    Baz::bar();
+    Qux::bar();
+    bar();
+}
index 24ec43b12f60e259f169bead63dab5c6214b219b..2705c03598a0d2c2bb84560dadc96478e7740b2e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_lints)]
+
 #![deny(unknown_lints)]
 
 #[allow(clippy::almost_swapped)]
index 6cd57eaa195958d599ae1b32fa8df965eaaf212e..57df3e072a8dc988c56737177fd5e532223e10cd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_lints)]
+
 #![feature(rust_2018_preview)]
 #![deny(unknown_lints)]
 
diff --git a/src/test/run-pass/traits/conservative_impl_trait.rs b/src/test/run-pass/traits/conservative_impl_trait.rs
deleted file mode 100644 (file)
index b6abeb9..0000000
+++ /dev/null
@@ -1,18 +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.
-
-// run-pass
-// #39665
-
-fn batches(n: &u32) -> impl Iterator<Item=&u32> {
-    std::iter::once(n)
-}
-
-fn main() {}
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
new file mode 100644 (file)
index 0000000..8c790d7
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// compile-flags: --error-format=human
+
+/// ```
+/// \__________pkt->size___________/          \_result->size_/ \__pkt->size__/
+/// ```
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
new file mode 100644 (file)
index 0000000..b566133
--- /dev/null
@@ -0,0 +1,10 @@
+Output from rustc:
+error: unknown start of token: /
+ --> <stdin>:1:1
+  |
+1 | /__________pkt->size___________/          /_result->size_/ /__pkt->size__/
+  | ^
+
+warning: Invalid doc comment starting with: `/__________pkt->size___________/          /_result->size_/ /__pkt->size__/`
+(Ignoring this codeblock)
+
index 0c1eedc86ccfd83cdcd60d6155fc670566cfa77a..454f8cb4a510fd9f19a721c01bf820e98ed1d27d 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags: -Cmetadata=aux
 
-#![feature(min_const_fn)]
-
 pub const fn foo() {}
 pub const unsafe fn bar() {}
 
index dc7a2799b46a911a0c3e92583613ff021e9c0371..cb4a5909120c4aa428b1709fd9c94640a691e24c 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(min_const_fn)]
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
index 49694e3ae08d1830599ce2d7946d8a8da2e15081..074a211cd08998cfe18d3460194bc35dc55b7ff4 100644 (file)
@@ -10,8 +10,6 @@
 
 #![crate_type="lib"]
 
-#![feature(min_const_fn)]
-
 pub struct Foo;
 
 impl Foo {
index ebe10b3714f20fecf91988379b59d6d24e8f6710..11b70d1d7809cb20176513fe0e1c89982a46a228 100644 (file)
@@ -11,8 +11,8 @@
 // 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))]
diff --git a/src/test/ui/auxiliary/namespaced_enums.rs b/src/test/ui/auxiliary/namespaced_enums.rs
deleted file mode 100644 (file)
index 3bf39b7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub enum Foo {
-    A,
-    B(isize),
-    C { a: isize },
-}
-
-impl Foo {
-    pub fn foo() {}
-    pub fn bar(&self) {}
-}
index ac6cfac2a165f61a4822904969b3c39263d74227..5721c52ba217287063d75333f8032ff8ae8567e0 100644 (file)
@@ -20,24 +20,22 @@ LL |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than o
 LL |                    *y = 1;
    |                    ------ first borrow later used here
 
-error: unsatisfied lifetime constraints
+error: captured variable cannot escape `FnMut` closure body
   --> $DIR/borrowck-describe-lvalue.rs:305:16
    |
 LL |              || {
-   |              --
-   |              ||
-   |              |return type of closure is [closure@$DIR/borrowck-describe-lvalue.rs:305:16: 311:18 x:&'2 mut i32]
-   |              lifetime `'1` represents this closure's body
-LL | /                || { //[mir]~ ERROR unsatisfied lifetime constraints
+   |               - inferred to be a `FnMut` closure
+LL | /                || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body
 LL | |                    let y = &mut x;
 LL | |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
 LL | |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
 LL | |                    *y = 1;
 LL | |                    drop(y);
 LL | |                 }
-   | |_________________^ returning this value requires that `'1` must outlive `'2`
+   | |_________________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |
-   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
   --> $DIR/borrowck-describe-lvalue.rs:53:9
index ac6cfac2a165f61a4822904969b3c39263d74227..5721c52ba217287063d75333f8032ff8ae8567e0 100644 (file)
@@ -20,24 +20,22 @@ LL |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than o
 LL |                    *y = 1;
    |                    ------ first borrow later used here
 
-error: unsatisfied lifetime constraints
+error: captured variable cannot escape `FnMut` closure body
   --> $DIR/borrowck-describe-lvalue.rs:305:16
    |
 LL |              || {
-   |              --
-   |              ||
-   |              |return type of closure is [closure@$DIR/borrowck-describe-lvalue.rs:305:16: 311:18 x:&'2 mut i32]
-   |              lifetime `'1` represents this closure's body
-LL | /                || { //[mir]~ ERROR unsatisfied lifetime constraints
+   |               - inferred to be a `FnMut` closure
+LL | /                || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body
 LL | |                    let y = &mut x;
 LL | |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
 LL | |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
 LL | |                    *y = 1;
 LL | |                    drop(y);
 LL | |                 }
-   | |_________________^ returning this value requires that `'1` must outlive `'2`
+   | |_________________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |
-   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
   --> $DIR/borrowck-describe-lvalue.rs:53:9
index 2ef08e75cfda3898baf185f7daad39f9ef7d5a9b..649de888ab0a249aa9b073076a105594eeed7b36 100644 (file)
@@ -302,7 +302,7 @@ unsafe fn bump2(mut block: *mut Block2) {
         // FIXME(#49824) -- the free region error below should probably not be there
         let mut x = 0;
            || {
-               || { //[mir]~ ERROR unsatisfied lifetime constraints
+               || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body
                    let y = &mut x;
                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
index f823a6f08d789485e47546b7e9fa34f4ec5f1f34..c3a2180b9f082e062f9afab0ede465a7511ac8f3 100644 (file)
@@ -1,10 +1,10 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of dereference of raw pointer
   --> $DIR/borrowck-move-from-unsafe-ptr.rs:13:13
    |
 LL |     let y = *x; //~ ERROR cannot move out of dereference of raw pointer
    |             ^^
    |             |
-   |             cannot move out of borrowed content
+   |             cannot move out of dereference of raw pointer
    |             help: consider removing the `*`: `x`
 
 error: aborting due to previous error
index 4c399ab6014df7fa591af816f79d0b1b2b9f6e34..0c0f539df6a3b5aafb21a808182824e34e25d1af 100644 (file)
@@ -1,11 +1,11 @@
 error[E0507]: cannot move out of borrowed content
-  --> $DIR/move-in-static-initializer-issue-38520.rs:27:23
+  --> $DIR/move-in-static-initializer-issue-38520.rs:25:23
    |
 LL | static Y: usize = get(*&X); //[ast]~ ERROR E0507
    |                       ^^^ cannot move out of borrowed content
 
 error[E0507]: cannot move out of borrowed content
-  --> $DIR/move-in-static-initializer-issue-38520.rs:29:22
+  --> $DIR/move-in-static-initializer-issue-38520.rs:27:22
    |
 LL | const Z: usize = get(*&X); //[ast]~ ERROR E0507
    |                      ^^^ cannot move out of borrowed content
index 4c399ab6014df7fa591af816f79d0b1b2b9f6e34..0c0f539df6a3b5aafb21a808182824e34e25d1af 100644 (file)
@@ -1,11 +1,11 @@
 error[E0507]: cannot move out of borrowed content
-  --> $DIR/move-in-static-initializer-issue-38520.rs:27:23
+  --> $DIR/move-in-static-initializer-issue-38520.rs:25:23
    |
 LL | static Y: usize = get(*&X); //[ast]~ ERROR E0507
    |                       ^^^ cannot move out of borrowed content
 
 error[E0507]: cannot move out of borrowed content
-  --> $DIR/move-in-static-initializer-issue-38520.rs:29:22
+  --> $DIR/move-in-static-initializer-issue-38520.rs:27:22
    |
 LL | const Z: usize = get(*&X); //[ast]~ ERROR E0507
    |                      ^^^ cannot move out of borrowed content
index d71c8462587d06e8e1411930b0791d66255ea65d..34e76c92a658df2c7f7e578cb6c3025e97450e90 100644 (file)
@@ -15,8 +15,6 @@
 // permitted as `Foo` is not copy (even in a static/const
 // initializer).
 
-#![feature(min_const_fn)]
-
 struct Foo(usize);
 
 const fn get(x: Foo) -> usize {
diff --git a/src/test/ui/cfg-arg-invalid-1.rs b/src/test/ui/cfg-arg-invalid-1.rs
deleted file mode 100644 (file)
index 36dd78d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: --cfg a(b=c)
-// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`)
-fn main() {}
diff --git a/src/test/ui/cfg-arg-invalid-2.rs b/src/test/ui/cfg-arg-invalid-2.rs
deleted file mode 100644 (file)
index 48d656a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: --cfg a{b}
-// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`)
-fn main() {}
diff --git a/src/test/ui/cfg-arg-invalid-3.rs b/src/test/ui/cfg-arg-invalid-3.rs
deleted file mode 100644 (file)
index 96ac782..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: --cfg a::b
-// error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier)
-fn main() {}
diff --git a/src/test/ui/cfg-arg-invalid-4.rs b/src/test/ui/cfg-arg-invalid-4.rs
deleted file mode 100644 (file)
index e7dfa17..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: --cfg a(b)
-// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`)
-fn main() {}
diff --git a/src/test/ui/cfg-arg-invalid-5.rs b/src/test/ui/cfg-arg-invalid-5.rs
deleted file mode 100644 (file)
index a939f45..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: --cfg a=10
-// error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string)
-fn main() {}
diff --git a/src/test/ui/cfg-attr-cfg-2.rs b/src/test/ui/cfg-attr-cfg-2.rs
deleted file mode 100644 (file)
index 58a62d4..0000000
+++ /dev/null
@@ -1,18 +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.
-//
-// error-pattern: `main` function not found
-// compile-flags: --cfg foo
-
-// main is conditionally compiled, but the conditional compilation
-// is conditional too!
-
-#[cfg_attr(foo, cfg(bar))]
-fn main() { }
diff --git a/src/test/ui/cfg-attr-cfg-2.stderr b/src/test/ui/cfg-attr-cfg-2.stderr
deleted file mode 100644 (file)
index db3c7ac..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
-   |
-   = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/cfg-attr-crate-2.rs b/src/test/ui/cfg-attr-crate-2.rs
deleted file mode 100644 (file)
index a79c766..0000000
+++ /dev/null
@@ -1,17 +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.
-//
-// compile-flags: --cfg broken
-
-// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
-
-#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental
-
-fn main() { }
diff --git a/src/test/ui/cfg-attr-crate-2.stderr b/src/test/ui/cfg-attr-crate-2.stderr
deleted file mode 100644 (file)
index 7b66c8f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: no_core is experimental (see issue #29639)
-  --> $DIR/cfg-attr-crate-2.rs:15:21
-   |
-LL | #![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental
-   |                     ^^^^^^^^
-   |
-   = help: add #![feature(no_core)] 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/cfg-attr-invalid-predicate.rs b/src/test/ui/cfg-attr-invalid-predicate.rs
deleted file mode 100644 (file)
index 09fe6ce..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
-fn main() {}
diff --git a/src/test/ui/cfg-attr-invalid-predicate.stderr b/src/test/ui/cfg-attr-invalid-predicate.stderr
deleted file mode 100644 (file)
index 5a89f97..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0537]: invalid predicate `foo`
-  --> $DIR/cfg-attr-invalid-predicate.rs:11:7
-   |
-LL | #[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
-   |       ^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0537`.
diff --git a/src/test/ui/cfg-attr-syntax-validation.rs b/src/test/ui/cfg-attr-syntax-validation.rs
deleted file mode 100644 (file)
index 06a22ef..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#[cfg] //~ ERROR `cfg` is not followed by parentheses
-struct S1;
-
-#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
-struct S2;
-
-#[cfg()] //~ ERROR `cfg` predicate is not specified
-struct S3;
-
-#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
-struct S4;
-
-#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
-struct S5;
-
-#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
-struct S6;
-
-#[cfg(a())] //~ ERROR invalid predicate `a`
-struct S7;
-
-#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
-struct S8;
-
-macro_rules! generate_s9 {
-    ($expr: expr) => {
-        #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item
-        struct S9;
-    }
-}
-
-generate_s9!(concat!("nonexistent"));
diff --git a/src/test/ui/cfg-attr-syntax-validation.stderr b/src/test/ui/cfg-attr-syntax-validation.stderr
deleted file mode 100644 (file)
index 7773fdb..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-error: `cfg` is not followed by parentheses
-  --> $DIR/cfg-attr-syntax-validation.rs:1:1
-   |
-LL | #[cfg] //~ ERROR `cfg` is not followed by parentheses
-   | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
-
-error: `cfg` is not followed by parentheses
-  --> $DIR/cfg-attr-syntax-validation.rs:4:1
-   |
-LL | #[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
-   | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
-
-error: `cfg` predicate is not specified
-  --> $DIR/cfg-attr-syntax-validation.rs:7:1
-   |
-LL | #[cfg()] //~ ERROR `cfg` predicate is not specified
-   | ^^^^^^^^
-
-error: multiple `cfg` predicates are specified
-  --> $DIR/cfg-attr-syntax-validation.rs:10:10
-   |
-LL | #[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
-   |          ^
-
-error: `cfg` predicate key cannot be a literal
-  --> $DIR/cfg-attr-syntax-validation.rs:13:7
-   |
-LL | #[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
-   |       ^^^^^
-
-error: `cfg` predicate key must be an identifier
-  --> $DIR/cfg-attr-syntax-validation.rs:16:7
-   |
-LL | #[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
-   |       ^^^^
-
-error[E0537]: invalid predicate `a`
-  --> $DIR/cfg-attr-syntax-validation.rs:19:7
-   |
-LL | #[cfg(a())] //~ ERROR invalid predicate `a`
-   |       ^^^
-
-error: literal in `cfg` predicate value must be a string
-  --> $DIR/cfg-attr-syntax-validation.rs:22:11
-   |
-LL | #[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
-   |           ^^
-
-error: `cfg` is not a well-formed meta-item
-  --> $DIR/cfg-attr-syntax-validation.rs:27:9
-   |
-LL |         #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: expected syntax is: `#[cfg(/* predicate */)]`
-...
-LL | generate_s9!(concat!("nonexistent"));
-   | ------------------------------------- in this macro invocation
-
-error: aborting due to 9 previous errors
-
-For more information about this error, try `rustc --explain E0537`.
diff --git a/src/test/ui/cfg-attr-trailing-comma.rs b/src/test/ui/cfg-attr-trailing-comma.rs
deleted file mode 100644 (file)
index 21e0054..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: --cfg TRUE
-
-#[cfg_attr(TRUE, inline,)] // OK
-fn f() {}
-
-#[cfg_attr(FALSE, inline,)] // OK
-fn g() {}
-
-#[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,`
-fn h() {}
-
-#[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,`
-fn i() {}
diff --git a/src/test/ui/cfg-attr-trailing-comma.stderr b/src/test/ui/cfg-attr-trailing-comma.stderr
deleted file mode 100644 (file)
index 76a4704..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: expected `)`, found `,`
-  --> $DIR/cfg-attr-trailing-comma.rs:9:25
-   |
-LL | #[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,`
-   |                         ^ expected `)`
-
-error: expected `)`, found `,`
-  --> $DIR/cfg-attr-trailing-comma.rs:12:26
-   |
-LL | #[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,`
-   |                          ^ expected `)`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.rs
deleted file mode 100644 (file)
index afcb896..0000000
+++ /dev/null
@@ -1,20 +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.
-
-macro_rules! foo {
-    () => {
-        #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
-        fn foo() {}
-    }
-}
-
-foo!();
-
-fn main() {}
diff --git a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr
deleted file mode 100644 (file)
index 0f51c7d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:13:27
-   |
-LL |         #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
-   |                           ^^^^^^^
-...
-LL | foo!();
-   | ------- in this macro invocation
-   |
-   = help: add #![feature(custom_attribute)] 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/cfg-empty-codemap.rs b/src/test/ui/cfg-empty-codemap.rs
deleted file mode 100644 (file)
index 5cf8135..0000000
+++ /dev/null
@@ -1,18 +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.
-
-// Tests that empty source_maps don't ICE (#23301)
-
-// compile-flags: --cfg ""
-
-// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`)
-
-pub fn main() {
-}
diff --git a/src/test/ui/cfg-in-crate-1.rs b/src/test/ui/cfg-in-crate-1.rs
deleted file mode 100644 (file)
index bbccf2b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: `main` function not found
-
-#![cfg(bar)]
diff --git a/src/test/ui/cfg-in-crate-1.stderr b/src/test/ui/cfg-in-crate-1.stderr
deleted file mode 100644 (file)
index c6d42c7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-error[E0601]: `main` function not found in crate `cfg_in_crate_1`
-   |
-   = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/cfg-non-opt-expr.rs b/src/test/ui/cfg-non-opt-expr.rs
deleted file mode 100644 (file)
index 55eca7f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(stmt_expr_attributes)]
-#![feature(custom_test_frameworks)]
-
-fn main() {
-    let _ = #[cfg(unset)] ();
-    //~^ ERROR removing an expression is not supported in this position
-    let _ = 1 + 2 + #[cfg(unset)] 3;
-    //~^ 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
-}
diff --git a/src/test/ui/cfg-non-opt-expr.stderr b/src/test/ui/cfg-non-opt-expr.stderr
deleted file mode 100644 (file)
index 1892cee..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: removing an expression is not supported in this position
-  --> $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: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:19:23
-   |
-LL |     let _ = [1, 2, 3][#[cfg(unset)] 1];
-   |                       ^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/cfg_attr_path.rs b/src/test/ui/cfg_attr_path.rs
deleted file mode 100644 (file)
index 7d79985..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-#![deny(unused_attributes)] // c.f #35584
-
-mod auxiliary {
-    #[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums;
-    #[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file;
-}
-
-#[rustc_error]
-fn main() { //~ ERROR compilation successful
-    let _ = auxiliary::namespaced_enums::Foo::A;
-    let _ = auxiliary::nonexistent_file::Foo::A;
-}
diff --git a/src/test/ui/cfg_attr_path.stderr b/src/test/ui/cfg_attr_path.stderr
deleted file mode 100644 (file)
index 67e59d0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: compilation successful
-  --> $DIR/cfg_attr_path.rs:21:1
-   |
-LL | / fn main() { //~ ERROR compilation successful
-LL | |     let _ = auxiliary::namespaced_enums::Foo::A;
-LL | |     let _ = auxiliary::nonexistent_file::Foo::A;
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
index c5ba5beeca7a57de53875488fcec1ad0f0e9fc7d..ba7d4ff0d9bf55ac0adc4573e195552b28810d93 100644 (file)
 
 #![feature(rustc_attrs)]
 
+trait Bar { }
+
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<S, T, U> {
-    fn s(_: S) -> S;
-    fn t(_: T) -> T;
-    fn u(_: U) -> U;
+trait Foo<S, T: ?Sized> {
+    #[rustc_dump_program_clauses] //~ ERROR program clause dump
+    type Assoc: Bar + ?Sized;
 }
 
 fn main() {
index c4e768415d60b5501ff5156f6c8a26b8bbab1b0d..dc2375277e7342d713049d371ae759707c5fdd1f 100644 (file)
@@ -1,14 +1,23 @@
 error: program clause dump
-  --> $DIR/lower_trait.rs:13:1
+  --> $DIR/lower_trait.rs:15:1
    |
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
-   = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
-   = note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
-   = note: WellFormed(Self: Foo<S, T, U>) :- Implemented(Self: Foo<S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(U: std::marker::Sized).
+   = note: FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>).
+   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>).
+   = note: Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>).
+   = note: WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar).
 
-error: aborting due to previous error
+error: program clause dump
+  --> $DIR/lower_trait.rs:17:5
+   |
+LL |     #[rustc_dump_program_clauses] //~ ERROR program clause dump
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)).
+   = note: ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)).
+   = note: WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>).
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs b/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs
new file mode 100644 (file)
index 0000000..3bf39b7
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+pub enum Foo {
+    A,
+    B(isize),
+    C { a: isize },
+}
+
+impl Foo {
+    pub fn foo() {}
+    pub fn bar(&self) {}
+}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs
new file mode 100644 (file)
index 0000000..36dd78d
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a(b=c)
+// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs
new file mode 100644 (file)
index 0000000..48d656a
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a{b}
+// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs
new file mode 100644 (file)
index 0000000..96ac782
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a::b
+// error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs
new file mode 100644 (file)
index 0000000..e7dfa17
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a(b)
+// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs
new file mode 100644 (file)
index 0000000..a939f45
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a=10
+// error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs
new file mode 100644 (file)
index 0000000..58a62d4
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+//
+// error-pattern: `main` function not found
+// compile-flags: --cfg foo
+
+// main is conditionally compiled, but the conditional compilation
+// is conditional too!
+
+#[cfg_attr(foo, cfg(bar))]
+fn main() { }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
new file mode 100644 (file)
index 0000000..db3c7ac
--- /dev/null
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
+   |
+   = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs
new file mode 100644 (file)
index 0000000..a79c766
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-flags: --cfg broken
+
+// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
+
+#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental
+
+fn main() { }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr
new file mode 100644 (file)
index 0000000..a730473
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/cfg-attr-crate-2.rs:15:21
+   |
+LL | #![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental
+   |                     ^^^^^^^
+   |
+   = help: add #![feature(no_core)] 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/conditional-compilation/cfg-attr-invalid-predicate.rs b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs
new file mode 100644 (file)
index 0000000..09fe6ce
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr
new file mode 100644 (file)
index 0000000..5a89f97
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0537]: invalid predicate `foo`
+  --> $DIR/cfg-attr-invalid-predicate.rs:11:7
+   |
+LL | #[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
+   |       ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0537`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
new file mode 100644 (file)
index 0000000..84bd33f
--- /dev/null
@@ -0,0 +1,20 @@
+// Test that cfg_attr doesn't emit any attributes when the
+// configuation variable is false. This mirrors `cfg-attr-multi-true.rs`
+
+// compile-pass
+
+#![warn(unused_must_use)]
+#![feature(cfg_attr_multi)]
+
+#[cfg_attr(any(), deprecated, must_use)]
+struct Struct {}
+
+impl Struct {
+    fn new() -> Struct {
+        Struct {}
+    }
+}
+
+fn main() {
+    Struct::new();
+}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs
new file mode 100644 (file)
index 0000000..d4c3186
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-flags: --cfg broken
+
+#![feature(cfg_attr_multi)]
+#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
+
+fn main() { }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr
new file mode 100644 (file)
index 0000000..bf68d92
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/cfg-attr-multi-invalid-1.rs:14:21
+   |
+LL | #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
+   |                     ^^^^^^^
+   |
+   = help: add #![feature(no_core)] 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/conditional-compilation/cfg-attr-multi-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs
new file mode 100644 (file)
index 0000000..bee6b7d
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-flags: --cfg broken
+
+#![feature(cfg_attr_multi)]
+#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
+
+fn main() { }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr
new file mode 100644 (file)
index 0000000..5c72a40
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/cfg-attr-multi-invalid-2.rs:14:29
+   |
+LL | #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
+   |                             ^^^^^^^
+   |
+   = help: add #![feature(no_core)] 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/conditional-compilation/cfg-attr-multi-true.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
new file mode 100644 (file)
index 0000000..a31dde0
--- /dev/null
@@ -0,0 +1,22 @@
+// Test that cfg_attr with multiple attributes actually emits both attributes.
+// This is done by emitting two attributes that cause new warnings, and then
+// triggering those warnings.
+
+// compile-pass
+
+#![warn(unused_must_use)]
+#![feature(cfg_attr_multi)]
+
+#[cfg_attr(all(), deprecated, must_use)]
+struct MustUseDeprecated {}
+
+impl MustUseDeprecated { //~ warning: use of deprecated item
+    fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
+        MustUseDeprecated {} //~ warning: use of deprecated item
+    }
+}
+
+fn main() {
+    MustUseDeprecated::new(); //~ warning: use of deprecated item
+    //| warning: unused `MustUseDeprecated` which must be used
+}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
new file mode 100644 (file)
index 0000000..37cb3de
--- /dev/null
@@ -0,0 +1,38 @@
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:13:6
+   |
+LL | impl MustUseDeprecated { //~ warning: use of deprecated item
+   |      ^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(deprecated)] on by default
+
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:20:5
+   |
+LL |     MustUseDeprecated::new(); //~ warning: use of deprecated item
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:14:17
+   |
+LL |     fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
+   |                 ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:15:9
+   |
+LL |         MustUseDeprecated {} //~ warning: use of deprecated item
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: unused `MustUseDeprecated` which must be used
+  --> $DIR/cfg-attr-multi-true.rs:20:5
+   |
+LL |     MustUseDeprecated::new(); //~ warning: use of deprecated item
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/cfg-attr-multi-true.rs:7:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
new file mode 100644 (file)
index 0000000..eec0e8f
--- /dev/null
@@ -0,0 +1,45 @@
+// Parse `cfg_attr` with varying numbers of attributes and trailing commas
+
+#![feature(cfg_attr_multi)]
+
+// Completely empty `cfg_attr` input
+#[cfg_attr()] //~ error: expected identifier, found `)`
+struct NoConfigurationPredicate;
+
+// Zero attributes, zero trailing comma (comma manatory here)
+#[cfg_attr(all())] //~ error: expected `,`, found `)`
+struct A0C0;
+
+// Zero attributes, one trailing comma
+#[cfg_attr(all(),)] // Ok
+struct A0C1;
+
+// Zero attributes, two trailing commas
+#[cfg_attr(all(),,)] //~ ERROR expected identifier
+struct A0C2;
+
+// One attribute, no trailing comma
+#[cfg_attr(all(), must_use)] // Ok
+struct A1C0;
+
+// One attribute, one trailing comma
+#[cfg_attr(all(), must_use,)] // Ok
+struct A1C1;
+
+// One attribute, two trailing commas
+#[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier
+struct A1C2;
+
+// Two attributes, no trailing comma
+#[cfg_attr(all(), must_use, deprecated)] // Ok
+struct A2C0;
+
+// Two attributes, one trailing comma
+#[cfg_attr(all(), must_use, deprecated,)] // Ok
+struct A2C1;
+
+// Two attributes, two trailing commas
+#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
+struct A2C2;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
new file mode 100644 (file)
index 0000000..553406b
--- /dev/null
@@ -0,0 +1,32 @@
+error: expected identifier, found `)`
+  --> $DIR/cfg-attr-parse.rs:6:12
+   |
+LL | #[cfg_attr()] //~ error: expected identifier, found `)`
+   |            ^ expected identifier
+
+error: expected `,`, found `)`
+  --> $DIR/cfg-attr-parse.rs:10:17
+   |
+LL | #[cfg_attr(all())] //~ error: expected `,`, found `)`
+   |                 ^ expected `,`
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:18:18
+   |
+LL | #[cfg_attr(all(),,)] //~ ERROR expected identifier
+   |                  ^ expected identifier
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:30:28
+   |
+LL | #[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier
+   |                            ^ expected identifier
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:42:40
+   |
+LL | #[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
+   |                                        ^ expected identifier
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs
new file mode 100644 (file)
index 0000000..06a22ef
--- /dev/null
@@ -0,0 +1,32 @@
+#[cfg] //~ ERROR `cfg` is not followed by parentheses
+struct S1;
+
+#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
+struct S2;
+
+#[cfg()] //~ ERROR `cfg` predicate is not specified
+struct S3;
+
+#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
+struct S4;
+
+#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
+struct S5;
+
+#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
+struct S6;
+
+#[cfg(a())] //~ ERROR invalid predicate `a`
+struct S7;
+
+#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
+struct S8;
+
+macro_rules! generate_s9 {
+    ($expr: expr) => {
+        #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item
+        struct S9;
+    }
+}
+
+generate_s9!(concat!("nonexistent"));
diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
new file mode 100644 (file)
index 0000000..7773fdb
--- /dev/null
@@ -0,0 +1,60 @@
+error: `cfg` is not followed by parentheses
+  --> $DIR/cfg-attr-syntax-validation.rs:1:1
+   |
+LL | #[cfg] //~ ERROR `cfg` is not followed by parentheses
+   | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: `cfg` is not followed by parentheses
+  --> $DIR/cfg-attr-syntax-validation.rs:4:1
+   |
+LL | #[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
+   | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: `cfg` predicate is not specified
+  --> $DIR/cfg-attr-syntax-validation.rs:7:1
+   |
+LL | #[cfg()] //~ ERROR `cfg` predicate is not specified
+   | ^^^^^^^^
+
+error: multiple `cfg` predicates are specified
+  --> $DIR/cfg-attr-syntax-validation.rs:10:10
+   |
+LL | #[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
+   |          ^
+
+error: `cfg` predicate key cannot be a literal
+  --> $DIR/cfg-attr-syntax-validation.rs:13:7
+   |
+LL | #[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
+   |       ^^^^^
+
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-attr-syntax-validation.rs:16:7
+   |
+LL | #[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
+   |       ^^^^
+
+error[E0537]: invalid predicate `a`
+  --> $DIR/cfg-attr-syntax-validation.rs:19:7
+   |
+LL | #[cfg(a())] //~ ERROR invalid predicate `a`
+   |       ^^^
+
+error: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg-attr-syntax-validation.rs:22:11
+   |
+LL | #[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
+   |           ^^
+
+error: `cfg` is not a well-formed meta-item
+  --> $DIR/cfg-attr-syntax-validation.rs:27:9
+   |
+LL |         #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: expected syntax is: `#[cfg(/* predicate */)]`
+...
+LL | generate_s9!(concat!("nonexistent"));
+   | ------------------------------------- in this macro invocation
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0537`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
new file mode 100644 (file)
index 0000000..afcb896
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+macro_rules! foo {
+    () => {
+        #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
+        fn foo() {}
+    }
+}
+
+foo!();
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
new file mode 100644 (file)
index 0000000..0f51c7d
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:13:27
+   |
+LL |         #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
+   |                           ^^^^^^^
+...
+LL | foo!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(custom_attribute)] 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/conditional-compilation/cfg-empty-codemap.rs b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs
new file mode 100644 (file)
index 0000000..5cf8135
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// Tests that empty source_maps don't ICE (#23301)
+
+// compile-flags: --cfg ""
+
+// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`)
+
+pub fn main() {
+}
diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.rs b/src/test/ui/conditional-compilation/cfg-in-crate-1.rs
new file mode 100644 (file)
index 0000000..bbccf2b
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+// error-pattern: `main` function not found
+
+#![cfg(bar)]
diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
new file mode 100644 (file)
index 0000000..c6d42c7
--- /dev/null
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `cfg_in_crate_1`
+   |
+   = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs b/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs
new file mode 100644 (file)
index 0000000..55eca7f
--- /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.
+
+#![feature(stmt_expr_attributes)]
+#![feature(custom_test_frameworks)]
+
+fn main() {
+    let _ = #[cfg(unset)] ();
+    //~^ ERROR removing an expression is not supported in this position
+    let _ = 1 + 2 + #[cfg(unset)] 3;
+    //~^ 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
+}
diff --git a/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr b/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr
new file mode 100644 (file)
index 0000000..1892cee
--- /dev/null
@@ -0,0 +1,20 @@
+error: removing an expression is not supported in this position
+  --> $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: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:19:23
+   |
+LL |     let _ = [1, 2, 3][#[cfg(unset)] 1];
+   |                       ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_attr_path.rs b/src/test/ui/conditional-compilation/cfg_attr_path.rs
new file mode 100644 (file)
index 0000000..7d79985
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![deny(unused_attributes)] // c.f #35584
+
+mod auxiliary {
+    #[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums;
+    #[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file;
+}
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+    let _ = auxiliary::namespaced_enums::Foo::A;
+    let _ = auxiliary::nonexistent_file::Foo::A;
+}
diff --git a/src/test/ui/conditional-compilation/cfg_attr_path.stderr b/src/test/ui/conditional-compilation/cfg_attr_path.stderr
new file mode 100644 (file)
index 0000000..67e59d0
--- /dev/null
@@ -0,0 +1,11 @@
+error: compilation successful
+  --> $DIR/cfg_attr_path.rs:21:1
+   |
+LL | / fn main() { //~ ERROR compilation successful
+LL | |     let _ = auxiliary::namespaced_enums::Foo::A;
+LL | |     let _ = auxiliary::nonexistent_file::Foo::A;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index 499227e71a74cc42bf5314b1de9a1ddd2a85b241..5063c8d1d1f54a1b9b4cea166cc2a651f07a43cc 100644 (file)
@@ -11,6 +11,5 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
 #![crate_type="rlib"]
-#![feature(min_const_fn)]
 
 pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable
index 751f4113fbf60a9f1fe49f00bc381aeb5deb70e9..7be9345b6b423c8a87f12d9c6be030488f0ca5cc 100644 (file)
@@ -2,7 +2,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
@@ -36,7 +36,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
@@ -74,7 +74,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
@@ -96,7 +96,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
@@ -144,7 +144,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
@@ -184,7 +184,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
@@ -208,7 +208,7 @@ 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
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = 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
 
index 200f423f6e39b5de9d5718650fcd299fc3577cbd..6e60fd834d4c3fa0b557e571a23be6cdd68e4244 100644 (file)
@@ -10,8 +10,6 @@
 
 #![warn(const_err)]
 
-#![feature(min_const_fn)]
-
 const fn foo(x: u32) -> u32 {
     x
 }
index 66921dcd7c50835ab02411acc6263f838fcc5b46..6229790f8adc2519baec7797faf9a2bef8dd28ab 100644 (file)
@@ -1,5 +1,5 @@
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:20:5
+  --> $DIR/issue-43197.rs:18:5
    |
 LL |     const X: u32 = 0-1;
    |     ^^^^^^^^^^^^^^^---^
@@ -13,7 +13,7 @@ LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:22:5
+  --> $DIR/issue-43197.rs:20:5
    |
 LL |     const Y: u32 = foo(0-1);
    |     ^^^^^^^^^^^^^^^^^^^---^^
@@ -21,7 +21,7 @@ LL |     const Y: u32 = foo(0-1);
    |                        attempt to subtract with overflow
 
 error[E0080]: referenced constant has errors
-  --> $DIR/issue-43197.rs:24:26
+  --> $DIR/issue-43197.rs:22:26
    |
 LL |     const Y: u32 = foo(0-1);
    |                        --- attempt to subtract with overflow
@@ -30,13 +30,13 @@ LL |     println!("{} {}", X, Y);
    |                          ^
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:24:26
+  --> $DIR/issue-43197.rs:22:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
 error[E0080]: referenced constant has errors
-  --> $DIR/issue-43197.rs:24:23
+  --> $DIR/issue-43197.rs:22:23
    |
 LL |     const X: u32 = 0-1;
    |                    --- attempt to subtract with overflow
@@ -45,7 +45,7 @@ LL |     println!("{} {}", X, Y);
    |                       ^
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:24:23
+  --> $DIR/issue-43197.rs:22:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
index 2bc860e3ef94fb2890dc870a709674a050893032..dc449c663c3d1b12f00481c715f2af6dc6564892 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-pass
 
-#![feature(min_const_fn)]
-
 struct S(pub &'static u32, pub u32);
 
 const fn g(ss: &S) -> &u32 { &ss.1 }
index a585a4404adf6487a65d98f095a99ae39a449d5c..477e7119ba93735f0cf4203fc4f3a945408f2596 100644 (file)
@@ -14,6 +14,5 @@
 
 static FOO: bool = unsafe { mem::transmute(3u8) };
 //~^ ERROR this static likely exhibits undefined behavior
-//~^^ type validation failed: encountered 3, but expected something in the range 0..=1
 
 fn main() {}
index 572d08ddfeebd0958d9db040dc249c98ac783ed2..243343c94b065b0131dc4b30f4f9ff24916d2cca 100644 (file)
@@ -18,7 +18,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/ub-enum.rs:45:1
    |
 LL | const BAD_ENUM_CHAR : Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered character at .Some.0.1, but expected a valid unicode codepoint
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .Some.0.1, but expected something in the range 0..=1114111
    |
    = 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
 
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
new file mode 100644 (file)
index 0000000..2b07eee
--- /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_transmute)]
+
+use std::mem;
+use std::ptr::NonNull;
+use std::num::{NonZeroU8, NonZeroUsize};
+
+const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
+//~^ ERROR this constant likely exhibits undefined behavior
+const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
new file mode 100644 (file)
index 0000000..8d1ca88
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-nonnull.rs:17:1
+   |
+LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-nonnull.rs:20:1
+   |
+LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-nonnull.rs:22:1
+   |
+LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = 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: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs
new file mode 100644 (file)
index 0000000..7ee13f2
--- /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(const_transmute)]
+
+use std::mem;
+
+const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const NULL: &u16 = unsafe { mem::transmute(0usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr
new file mode 100644 (file)
index 0000000..9907c78
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:15:1
+   |
+LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:18:1
+   |
+LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:21:1
+   |
+LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:24:1
+   |
+LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered integer pointer in non-ZST reference
+   |
+   = 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: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index a5e341524bc7312b0911d0624f12112adb56cf1c..99305beee52814c58bd999e3d005d93fa5cab671 100644 (file)
@@ -8,15 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-union Foo {
-    a: u8,
-    b: Bar,
-}
+#![feature(const_transmute)]
+
+use std::mem;
 
 #[derive(Copy, Clone)]
 enum Bar {}
 
-const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b};
+const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
 //~^ ERROR this constant likely exhibits undefined behavior
 
 fn main() {
index 623b98dc4531b797054f177d80704d035a9b4f4b..136d5f29199467a284a8ae9b000a68399691ad03 100644 (file)
@@ -1,11 +1,27 @@
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/ub-uninhabit.rs:19:1
+  --> $DIR/ub-uninhabit.rs:18:1
    |
-LL | const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
    |
    = 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: aborting due to previous error
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-uninhabit.rs:21:1
+   |
+LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-uninhabit.rs:24:1
+   |
+LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at [0]
+   |
+   = 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: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-usize-in-ref.rs b/src/test/ui/consts/const-eval/ub-usize-in-ref.rs
deleted file mode 100644 (file)
index aaff2f2..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,
-}
-
-// This might point to an invalid address, but that's the user's problem
-const USIZE_AS_STATIC_REF: &'static u8 = unsafe { Foo { b: 1337 }.a};
-
-fn main() {
-}
index ec51802681e0df40295b55d80407b9800539969f..4484dd6a14740f12cf06feb11faa1b2361e96e3d 100644 (file)
@@ -13,7 +13,7 @@ LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibi
 LL | |     a: 42,
 LL | |     b: unsafe { UNION.field3 },
 LL | | };
-   | |__^ type validation failed: encountered undefined bytes at .b
+   | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain bits
    |
    = 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
 
diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs b/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs
new file mode 100644 (file)
index 0000000..0c42d28
--- /dev/null
@@ -0,0 +1,139 @@
+// 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.
+
+#![allow(unused)]
+
+// normalize-stderr-test "alignment \d+" -> "alignment N"
+// normalize-stderr-test "offset \d+" -> "offset N"
+// normalize-stderr-test "allocation \d+" -> "allocation N"
+// normalize-stderr-test "size \d+" -> "size N"
+
+union BoolTransmute {
+  val: u8,
+  bl: bool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct SliceRepr {
+    ptr: *const u8,
+    len: usize,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct BadSliceRepr {
+    ptr: *const u8,
+    len: &'static u8,
+}
+
+union SliceTransmute {
+    repr: SliceRepr,
+    bad: BadSliceRepr,
+    slice: &'static [u8],
+    str: &'static str,
+    my_str: &'static MyStr,
+    my_slice: &'static MySliceBool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct DynRepr {
+    ptr: *const u8,
+    vtable: *const u8,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct DynRepr2 {
+    ptr: *const u8,
+    vtable: *const u64,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct BadDynRepr {
+    ptr: *const u8,
+    vtable: usize,
+}
+
+union DynTransmute {
+    repr: DynRepr,
+    repr2: DynRepr2,
+    bad: BadDynRepr,
+    rust: &'static Trait,
+}
+
+trait Trait {}
+impl Trait for bool {}
+
+// custom unsized type
+struct MyStr(str);
+
+// custom unsized type with sized fields
+struct MySlice<T: ?Sized>(bool, T);
+type MySliceBool = MySlice<[bool]>;
+
+// OK
+const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
+// bad str
+const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad str
+const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad str in user-defined unsized type
+const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// OK
+const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
+// bad slice
+const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad slice
+const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// bad trait object
+const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad trait object
+const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad trait object
+const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// bad data *inside* the trait object
+const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad data *inside* the slice
+const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// good MySliceBool
+const I1: &MySliceBool = &MySlice(true, [false]);
+// bad: sized field is not okay
+const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad: unsized part is not okay
+const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// invalid UTF-8
+const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+//~^ ERROR this constant likely exhibits undefined behavior
+// invalid UTF-8 in user-defined str-like
+const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr
new file mode 100644 (file)
index 0000000..c4632ff
--- /dev/null
@@ -0,0 +1,115 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:87:1
+   |
+LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling (not entirely in bounds) reference
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:90:1
+   |
+LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:93:1
+   |
+LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:99:1
+   |
+LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling (not entirely in bounds) reference
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:102:1
+   |
+LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:106:1
+   |
+LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:109:1
+   |
+LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:112:1
+   |
+LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:116:1
+   |
+LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>, but expected something in the range 0..=1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:119:1
+   |
+LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something in the range 0..=1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:125:1
+   |
+LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something in the range 0..=1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:128:1
+   |
+LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something in the range 0..=1
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:132:1
+   |
+LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
+   |
+   = 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[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:135:1
+   |
+LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
+   |
+   = 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: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index db36764c4a30693f280666512ff10a16a3fd991a..86b3bdaa6b79ec82d41cb0e9a8b9208501dd6b5b 100644 (file)
@@ -41,5 +41,4 @@ union Bar {
 const BAD_UNION: Foo = unsafe { Bar { u8: 42 }.foo };
 
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs
new file mode 100644 (file)
index 0000000..a195e12
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-pass
+
+// Some constants that *are* valid
+#![feature(const_transmute)]
+
+use std::mem;
+use std::ptr::NonNull;
+use std::num::{NonZeroU8, NonZeroUsize};
+
+const NON_NULL_PTR1: NonNull<u8> = unsafe { mem::transmute(1usize) };
+const NON_NULL_PTR2: NonNull<u8> = unsafe { mem::transmute(&0) };
+
+const NON_NULL_U8: NonZeroU8 = unsafe { mem::transmute(1u8) };
+const NON_NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(1usize) };
+
+const UNIT: () = ();
+
+fn main() {}
index 4f02b1eef3a0fef1a81922bc43a6c3aca273615c..07880b03001299a8a801afc9a0809faa92dd696f 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-pass
 
-#![feature(min_const_fn)]
-
 #[derive(PartialEq, Eq)]
 enum Cake {
     BlackForest,
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
new file mode 100644 (file)
index 0000000..d8abd97
--- /dev/null
@@ -0,0 +1,5 @@
+const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable
+    x == y
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
new file mode 100644 (file)
index 0000000..a050c10
--- /dev/null
@@ -0,0 +1,8 @@
+error: function pointers in const fn are unstable
+  --> $DIR/cmp_fn_pointers.rs:1:14
+   |
+LL | const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable
+   |              ^
+
+error: aborting due to previous error
+
index 715884d5175124582d54dd962af92cc1eeed71a0..a03c5168367db8874d283267fe0d16e4164bbca6 100644 (file)
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/min_const_fn.rs:49:25
+  --> $DIR/min_const_fn.rs:47: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:36
+  --> $DIR/min_const_fn.rs:49:36
    |
 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
+  --> $DIR/min_const_fn.rs:54: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:42
+  --> $DIR/min_const_fn.rs:56:42
    |
 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
+  --> $DIR/min_const_fn.rs:61: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:38
+  --> $DIR/min_const_fn.rs:63:38
    |
 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:39
+  --> $DIR/min_const_fn.rs:68:39
    |
 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
+  --> $DIR/min_const_fn.rs:86: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
+  --> $DIR/min_const_fn.rs:88: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
+  --> $DIR/min_const_fn.rs:90: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
+  --> $DIR/min_const_fn.rs:92: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
+  --> $DIR/min_const_fn.rs:94: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
+  --> $DIR/min_const_fn.rs:96: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
+  --> $DIR/min_const_fn.rs:100: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
+  --> $DIR/min_const_fn.rs:101: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
+  --> $DIR/min_const_fn.rs:102: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
+  --> $DIR/min_const_fn.rs:104: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
+  --> $DIR/min_const_fn.rs:106: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
+  --> $DIR/min_const_fn.rs:108: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
+  --> $DIR/min_const_fn.rs:109: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
+  --> $DIR/min_const_fn.rs:110: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
+  --> $DIR/min_const_fn.rs:112: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
+  --> $DIR/min_const_fn.rs:114: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
+  --> $DIR/min_const_fn.rs:119: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
+  --> $DIR/min_const_fn.rs:124: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
+  --> $DIR/min_const_fn.rs:129:6
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:137:24
+  --> $DIR/min_const_fn.rs:135:24
    |
 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
+  --> $DIR/min_const_fn.rs:137: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
+  --> $DIR/min_const_fn.rs:139: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:23
+  --> $DIR/min_const_fn.rs:140:23
    |
 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
+  --> $DIR/min_const_fn.rs:141: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:32
+  --> $DIR/min_const_fn.rs:142:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/min_const_fn.rs:144:64
+  --> $DIR/min_const_fn.rs:142:64
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                                                ^^ - temporary value is freed at the end of this statement
@@ -201,19 +201,19 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    = 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
+  --> $DIR/min_const_fn.rs:147: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
+  --> $DIR/min_const_fn.rs:150:21
    |
 LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:154:27
+  --> $DIR/min_const_fn.rs:152:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
index b861e312d4245e4664ea6d12c1956927e3ee0269..0dba3a7de53781e83b2f10abff826e5fdcaa26b0 100644 (file)
@@ -8,8 +8,6 @@
 // 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 }
index 6779b8a761461dcdacb7476628290a88e082e587..bcb9be6e5485eff485765fc077d4b9a2e78e1110 100644 (file)
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/min_const_fn.rs:49:25
+  --> $DIR/min_const_fn.rs:47: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:36
+  --> $DIR/min_const_fn.rs:49:36
    |
 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
+  --> $DIR/min_const_fn.rs:54: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:42
+  --> $DIR/min_const_fn.rs:56:42
    |
 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
+  --> $DIR/min_const_fn.rs:61: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:38
+  --> $DIR/min_const_fn.rs:63:38
    |
 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:39
+  --> $DIR/min_const_fn.rs:68:39
    |
 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
+  --> $DIR/min_const_fn.rs:86: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
+  --> $DIR/min_const_fn.rs:88: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
+  --> $DIR/min_const_fn.rs:90: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
+  --> $DIR/min_const_fn.rs:92: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
+  --> $DIR/min_const_fn.rs:94: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
+  --> $DIR/min_const_fn.rs:96: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
+  --> $DIR/min_const_fn.rs:100: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
+  --> $DIR/min_const_fn.rs:101: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
+  --> $DIR/min_const_fn.rs:102: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
+  --> $DIR/min_const_fn.rs:104: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
+  --> $DIR/min_const_fn.rs:106: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
+  --> $DIR/min_const_fn.rs:108: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
+  --> $DIR/min_const_fn.rs:109: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
+  --> $DIR/min_const_fn.rs:110: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
+  --> $DIR/min_const_fn.rs:112: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
+  --> $DIR/min_const_fn.rs:114: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
+  --> $DIR/min_const_fn.rs:119: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
+  --> $DIR/min_const_fn.rs:124: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
+  --> $DIR/min_const_fn.rs:129:6
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:137:24
+  --> $DIR/min_const_fn.rs:135:24
    |
 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
+  --> $DIR/min_const_fn.rs:137: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
+  --> $DIR/min_const_fn.rs:139: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:23
+  --> $DIR/min_const_fn.rs:140:23
    |
 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
+  --> $DIR/min_const_fn.rs:141: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:32
+  --> $DIR/min_const_fn.rs:142:32
    |
 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
+  --> $DIR/min_const_fn.rs:147: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
+  --> $DIR/min_const_fn.rs:150:21
    |
 LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:154:27
+  --> $DIR/min_const_fn.rs:152:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
index 9fc38e9e1f36e2701dcf5aa2d6e583e00dc7e961..5d071a0fe24057f7330b7def8adf09483211df88 100644 (file)
@@ -1,17 +1,17 @@
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn_dyn.rs:21:5
+  --> $DIR/min_const_fn_dyn.rs:19: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
+  --> $DIR/min_const_fn_dyn.rs:22:66
    |
 LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |                                                                  ^^
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/min_const_fn_dyn.rs:24:67
+  --> $DIR/min_const_fn_dyn.rs:22:67
    |
 LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |                                                                   ^    - temporary value is freed at the end of this statement
index 38e2825643009aba926884ab2e0333624b6b53da..e02474734d9ae2ed03a5a9c785431edfbfee4902 100644 (file)
@@ -8,8 +8,6 @@
 // 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,
 }
index 3a1055f2ede1504ccd802e7ebfa2e91c461322c8..7bf9bdb6fa90a78c57f4918da11d422bcc2598e9 100644 (file)
@@ -1,11 +1,11 @@
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn_dyn.rs:21:5
+  --> $DIR/min_const_fn_dyn.rs:19: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
+  --> $DIR/min_const_fn_dyn.rs:22:66
    |
 LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |                                                                  ^^
index 100d275f97e732970f8c884338bf8cad8faa54d8..64f212bc23792d221705b8ebd71a231372114327 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(min_const_fn)]
-
 struct HasPtr {
     field: fn(),
 }
index c10af3d2c8e71d4aa3755f500456e1ae56a2f749..54ffe66581de1b3eb86dd7f409d585f580ebb3c5 100644 (file)
@@ -1,11 +1,11 @@
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn_fn_ptr.rs:23:5
+  --> $DIR/min_const_fn_fn_ptr.rs:21:5
    |
 LL |     x.0.field;
    |     ^^^^^^^^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn_fn_ptr.rs:26:59
+  --> $DIR/min_const_fn_fn_ptr.rs:24:59
    |
 LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
    |                                                           ^^^^^
index fcc9545d97f1548957266b9e8b0a1efe72d6f038..1a3e6d01912a21d5ee3a7fcdc4d5cbce11f44847 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(integer_atomics, min_const_fn)]
+#![feature(integer_atomics)]
 
 // compile-pass
 
index e7caa4c6cb4263d801f6fd0868f9434e55cb8302..67332c6d2cfb23607f5ec49c515a30503ef76c1e 100644 (file)
@@ -8,8 +8,6 @@
 // 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 }
index 17cba8569c148f8d7cd9bfeedd288c951924fa42..8cff0d491d8a4d563ae6e2f9a76a391fd51a3db4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe.rs:29:51
+  --> $DIR/min_const_fn_unsafe.rs:27:51
    |
 LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
    |                                                   ^^
@@ -7,7 +7,7 @@ LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowe
    = 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
+  --> $DIR/min_const_fn_unsafe.rs:34:5
    |
 LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
    |     ^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ 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
+  --> $DIR/min_const_fn_unsafe.rs:19:14
    |
 LL |     unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
    |              ^^^^^^ call to unsafe function
@@ -23,7 +23,7 @@ LL |     unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const
    = 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
+  --> $DIR/min_const_fn_unsafe.rs:22:14
    |
 LL |     unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
    |              ^^^^^^^^^^^^^^^^ call to unsafe function
@@ -31,7 +31,7 @@ LL |     unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed
    = 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
+  --> $DIR/min_const_fn_unsafe.rs:25:14
    |
 LL |     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
@@ -39,7 +39,7 @@ LL |     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in
    = 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
+  --> $DIR/min_const_fn_unsafe.rs:27:51
    |
 LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
    |                                                   ^^ dereference of raw pointer
@@ -47,7 +47,7 @@ LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowe
    = 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
+  --> $DIR/min_const_fn_unsafe.rs:34:5
    |
 LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
    |     ^^^^^^^^^^^^^^^ access to union field
index 999c26b535e9ca32b2f8ecbd7a3f1007b3c2ee42..396b58dd219d8d57532fd34173b625a773cb4781 100644 (file)
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:13:27
+  --> $DIR/promotion.rs:11:27
    |
 LL |     let x: &'static () = &foo1(); //~ ERROR does not live long enough
    |                           ^^^^^^ creates a temporary which is freed while still in use
@@ -10,7 +10,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:14:28
+  --> $DIR/promotion.rs:12:28
    |
 LL |     let y: &'static i32 = &foo2(42); //~ ERROR does not live long enough
    |                            ^^^^^^^^ creates a temporary which is freed while still in use
@@ -21,7 +21,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:15:28
+  --> $DIR/promotion.rs:13:28
    |
 LL |     let z: &'static i32 = &foo3(); //~ ERROR does not live long enough
    |                            ^^^^^^ creates a temporary which is freed while still in use
@@ -32,7 +32,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:16:34
+  --> $DIR/promotion.rs:14:34
    |
 LL |     let a: &'static Cell<i32> = &foo4();  //~ ERROR does not live long enough
    |                                  ^^^^^^ creates a temporary which is freed while still in use
@@ -43,7 +43,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:17:42
+  --> $DIR/promotion.rs:15:42
    |
 LL |     let a: &'static Option<Cell<i32>> = &foo5(); //~ ERROR does not live long enough
    |                                          ^^^^^^ creates a temporary which is freed while still in use
@@ -54,7 +54,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:18:42
+  --> $DIR/promotion.rs:16:42
    |
 LL |     let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
    |                                          ^^^^^^ creates a temporary which is freed while still in use
index cb3bfd74711cae8f418d7be988752dca25d86044..969bf40a93ba7cefee02173777f839783385f8c6 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(min_const_fn)]
-
 use std::cell::Cell;
 
 const fn foo1() {}
index 68d584658223f9d607a1c3325dd2602f26e8373a..7052f68c3ec61d85fa6728c41f7fd4f6d0fc9431 100644 (file)
@@ -1,5 +1,5 @@
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/promotion.rs:13:27
+  --> $DIR/promotion.rs:11:27
    |
 LL |     let x: &'static () = &foo1(); //~ ERROR does not live long enough
    |                           ^^^^^^ temporary value does not live long enough
@@ -10,7 +10,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/promotion.rs:14:28
+  --> $DIR/promotion.rs:12:28
    |
 LL |     let y: &'static i32 = &foo2(42); //~ ERROR does not live long enough
    |                            ^^^^^^^^ temporary value does not live long enough
@@ -21,7 +21,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/promotion.rs:15:28
+  --> $DIR/promotion.rs:13:28
    |
 LL |     let z: &'static i32 = &foo3(); //~ ERROR does not live long enough
    |                            ^^^^^^ temporary value does not live long enough
@@ -32,7 +32,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/promotion.rs:16:34
+  --> $DIR/promotion.rs:14:34
    |
 LL |     let a: &'static Cell<i32> = &foo4();  //~ ERROR does not live long enough
    |                                  ^^^^^^ temporary value does not live long enough
@@ -43,7 +43,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/promotion.rs:17:42
+  --> $DIR/promotion.rs:15:42
    |
 LL |     let a: &'static Option<Cell<i32>> = &foo5(); //~ ERROR does not live long enough
    |                                          ^^^^^^ temporary value does not live long enough
@@ -54,7 +54,7 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/promotion.rs:18:42
+  --> $DIR/promotion.rs:16:42
    |
 LL |     let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
    |                                          ^^^^^^ temporary value does not live long enough
index 21fc4079d5b59d29626e162a04f1d6c2aba956a9..ebd44d46eb2ce544eb8e082a9e58dfc194d64ac0 100644 (file)
@@ -1,6 +1,9 @@
 error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-2.rs:17:9
    |
+LL |     s: &'a String
+   |        ---------- help: consider changing this to be mutable: `&'a mut String`
+...
 LL |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
index d426c1f37fc1c667a3a44f339ed19d44b0fdbae1..d644a84c7bbcec2da5723cf079f523f68c0746ae 100644 (file)
@@ -1,6 +1,9 @@
 error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-3.rs:17:9
    |
+LL |     s: &'a String
+   |        ---------- help: consider changing this to be mutable: `&'a mut String`
+...
 LL |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
index 2cd17804e06caa100d73e62f85dcbb22434df408..5c6f6e49b3d77f9bcec8d825ca8206ea434e8bff 100644 (file)
@@ -1,15 +1,4 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// normalize-stderr-test: "The system cannot find the file specified\." -> "No such file or directory"
-// ignore-tidy-linelength
+// normalize-stderr-test: "not-a-file.md:.*\(" -> "not-a-file.md: $$FILE_NOT_FOUND_MSG ("
 
 #![feature(external_doc)]
 
index 98ade5de7f3a753fbec23ec74f34a51a471d4645..5cc7551ee03aa253732711a91bae481c4f956c99 100644 (file)
@@ -1,5 +1,5 @@
-error: couldn't read $DIR/not-a-file.md: No such file or directory (os error 2)
-  --> $DIR/external-doc-error.rs:16:1
+error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/external-doc-error.rs:5:1
    |
 LL | #[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs
new file mode 100644 (file)
index 0000000..9515380
--- /dev/null
@@ -0,0 +1,5 @@
+// gate-test-cfg_attr_multi
+
+#![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
+//~^ ERROR cfg_attr with zero or more than one attributes is experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr
new file mode 100644 (file)
index 0000000..088e6df
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881)
+  --> $DIR/feature-gate-cfg-attr-multi-1.rs:3:1
+   |
+LL | #![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_attr_multi)] 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-gates/feature-gate-cfg-attr-multi-2.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs
new file mode 100644 (file)
index 0000000..cf02432
--- /dev/null
@@ -0,0 +1,3 @@
+#![cfg_attr(all(),)]
+//~^ ERROR cfg_attr with zero or more than one attributes is experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr
new file mode 100644 (file)
index 0000000..a018761
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881)
+  --> $DIR/feature-gate-cfg-attr-multi-2.rs:1:1
+   |
+LL | #![cfg_attr(all(),)]
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_attr_multi)] 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-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs
new file mode 100644 (file)
index 0000000..e473792
--- /dev/null
@@ -0,0 +1,7 @@
+// Test that settingt the featute gate while using its functionality doesn't error.
+
+// compile-pass
+
+#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs
new file mode 100644 (file)
index 0000000..df74054
--- /dev/null
@@ -0,0 +1,9 @@
+// Test that settingt the featute gate while using its functionality doesn't error.
+// Specifically, if there's a cfg-attr *before* the feature gate.
+
+// compile-pass
+
+#![cfg_attr(all(),)]
+#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
+
+fn main() {}
index f774658975b79d983021d8ee80f4c430704a83a2..e52331fa92ac8f4ceb0f950e44325a7ae313053f 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test use of const fn without the `const_fn` feature gate.
-// `min_const_fn` is checked in its own file
-#![feature(min_const_fn)]
+// Test use of advanced const fn without the `const_fn` feature gate.
 
 const fn foo() -> usize { 0 } // ok
 
index 26c0c7877b4ecc6f51b03b1531e65a720dced564..150a702d105fa6cf42d959383ec11c0ff7408293 100644 (file)
@@ -1,23 +1,23 @@
 error[E0379]: trait fns cannot be declared const
-  --> $DIR/feature-gate-const_fn.rs:18:5
+  --> $DIR/feature-gate-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-const_fn.rs:20:5
+  --> $DIR/feature-gate-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-const_fn.rs:29:5
+  --> $DIR/feature-gate-const_fn.rs:27:5
    |
 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:18:5
+  --> $DIR/feature-gate-const_fn.rs:16:5
    |
 LL |     const fn foo() -> u32; //~ ERROR const fn is unstable
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ 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:20:5
+  --> $DIR/feature-gate-const_fn.rs:18:5
    |
 LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
index e052ba9c8b43a6846c13d8d172b17ed358dfc3ed..40cb75316efa130ac65cb284c8d12d91b17b02ee 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test use of min_const_fn without feature gate.
 
-const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+const fn foo() -> usize { 0 } // stabilized
 
 trait Foo {
     const fn foo() -> u32; //~ ERROR const fn is unstable
@@ -20,12 +20,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 } // stabilized
 }
 
 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 aa7750362b2fd363d89c113eff5575d66a7a5058..34526746db84413ecf099284c178a87f5750bbac 100644 (file)
@@ -13,17 +13,9 @@ LL |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
 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
+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 #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
    |
@@ -40,23 +32,7 @@ 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
+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-tool_lints-fail.rs b/src/test/ui/feature-gates/feature-gate-tool_lints-fail.rs
deleted file mode 100644 (file)
index c311eb7..0000000
+++ /dev/null
@@ -1,12 +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.
-
-#[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr b/src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr
deleted file mode 100644 (file)
index 33ee79c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: scoped lint `clippy::assign_ops` is experimental (see issue #44690)
-  --> $DIR/feature-gate-tool_lints-fail.rs:11:8
-   |
-LL | #[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental
-   |        ^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(tool_lints)] 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-gates/feature-gate-tool_lints.rs b/src/test/ui/feature-gates/feature-gate-tool_lints.rs
deleted file mode 100644 (file)
index 3ef6798..0000000
+++ /dev/null
@@ -1,15 +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.
-
-#[warn(clippy::decimal_literal_representation)]
-//~^ ERROR scoped lint `clippy::decimal_literal_representation` is experimental
-fn main() {
-    let a = 65_535;
-}
diff --git a/src/test/ui/feature-gates/feature-gate-tool_lints.stderr b/src/test/ui/feature-gates/feature-gate-tool_lints.stderr
deleted file mode 100644 (file)
index 8019b1e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: scoped lint `clippy::decimal_literal_representation` is experimental (see issue #44690)
-  --> $DIR/feature-gate-tool_lints.rs:11:8
-   |
-LL | #[warn(clippy::decimal_literal_representation)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(tool_lints)] 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/impl-trait/existential-minimal.rs b/src/test/ui/impl-trait/existential-minimal.rs
new file mode 100644 (file)
index 0000000..ff92092
--- /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.
+
+// compile-pass
+
+fn main() {}
+
+fn foo() -> impl std::fmt::Debug { "cake" }
diff --git a/src/test/ui/impl-trait/issue-42479.rs b/src/test/ui/impl-trait/issue-42479.rs
new file mode 100644 (file)
index 0000000..fbf2c3f
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+use std::iter::once;
+
+struct Foo {
+    x: i32,
+}
+
+impl Foo {
+    fn inside(&self) -> impl Iterator<Item = &i32> {
+        once(&self.x)
+    }
+}
+
+fn main() {
+    println!("hi");
+}
diff --git a/src/test/ui/impl-trait/issue-49376.rs b/src/test/ui/impl-trait/issue-49376.rs
new file mode 100644 (file)
index 0000000..1dfea0b
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+// Tests for nested self-reference which caused a stack overflow.
+
+use std::fmt::Debug;
+use std::ops::*;
+
+fn gen() -> impl PartialOrd + PartialEq + Debug { }
+
+struct Bar {}
+trait Foo<T = Self> {}
+impl Foo for Bar {}
+
+fn foo() -> impl Foo {
+    Bar {}
+}
+
+fn test_impl_ops() -> impl Add + Sub + Mul + Div { 1 }
+fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign { 1 }
+
+fn main() {}
index 63ae18cf9c2fa1d3c0cf735e778afb8aae26c965..f99a080a9f07d6079de3c180852bd253da0ea885 100644 (file)
@@ -10,7 +10,6 @@
 
 //https://github.com/rust-lang/rust/issues/31364
 
-#![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 fb7c1be75413e189bdb2ee94d474e0e7c4574768..579cc6bd548f9f585e64bd098f0055ae97c47564 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: could not evaluate constant expression
-  --> $DIR/infinite-recursion-const-fn.rs:16:1
+  --> $DIR/infinite-recursion-const-fn.rs:15:1
    |
 LL | const fn a() -> usize { b() }
    |                         ---
diff --git a/src/test/ui/inline-asm-bad-operand.rs b/src/test/ui/inline-asm-bad-operand.rs
new file mode 100644 (file)
index 0000000..37021f3
--- /dev/null
@@ -0,0 +1,57 @@
+// 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 that the compiler will catch passing invalid values to inline assembly
+// operands.
+
+#![feature(asm)]
+
+#[repr(C)]
+struct MyPtr(usize);
+
+fn main() {
+    issue_37433();
+    issue_37437();
+    issue_40187();
+    issue_54067();
+}
+
+fn issue_37433() {
+    unsafe {
+        asm!("" :: "r"("")); //~ ERROR E0669
+    }
+
+    unsafe {
+        let target = MyPtr(0);
+        asm!("ret" : : "{rdi}"(target)); //~ ERROR E0669
+    }
+}
+
+fn issue_37437() {
+    let hello: &str = "hello";
+    // this should fail...
+    unsafe { asm!("" :: "i"(hello)) }; //~ ERROR E0669
+    // but this should succeed.
+    unsafe { asm!("" :: "r"(hello.as_ptr())) };
+}
+
+fn issue_40187() {
+    let arr: [u8; 1] = [0; 1];
+    unsafe {
+        asm!("movups $1, %xmm0"::"m"(arr)); //~ ERROR E0669
+    }
+}
+
+fn issue_54067() {
+    let addr: Option<u32> = Some(123);
+    unsafe {
+        asm!("mov sp, $0"::"r"(addr)); //~ ERROR E0669
+    }
+}
diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr
new file mode 100644 (file)
index 0000000..6971215
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:28:9
+   |
+LL |         asm!("" :: "r"("")); //~ ERROR E0669
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:33:9
+   |
+LL |         asm!("ret" : : "{rdi}"(target)); //~ ERROR E0669
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:40:14
+   |
+LL |     unsafe { asm!("" :: "i"(hello)) }; //~ ERROR E0669
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:48:9
+   |
+LL |         asm!("movups $1, %xmm0"::"m"(arr)); //~ ERROR E0669
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:55:9
+   |
+LL |         asm!("mov sp, $0"::"r"(addr)); //~ ERROR E0669
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/issue-49556.rs b/src/test/ui/issue-49556.rs
new file mode 100644 (file)
index 0000000..7f7b349
--- /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
+fn iter<'a>(data: &'a [usize]) -> impl Iterator<Item = usize> + 'a {
+    data.iter()
+        .map(
+            |x| x // fn(&'a usize) -> &'(ReScope) usize
+        )
+        .map(
+            |x| *x // fn(&'(ReScope) usize) -> usize
+        )
+}
+
+fn main() {
+}
index 201a3b3d54a3fcb79b6d347a7086304af1a49e88..a21336654f379cdd2fee2c2c7786e9a4dbcd7b48 100644 (file)
@@ -1,13 +1,11 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/issue-10291.rs:12:65
+  --> $DIR/issue-10291.rs:13:9
    |
-LL |   fn test<'x>(x: &'x isize) {
-   |           -- lifetime `'x` defined here
-LL |       drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
-   |  _________________________________________________________________^
-LL | |         x //~ ERROR E0312
-LL | |     }));
-   | |_____^ closure body requires that `'x` must outlive `'static`
+LL | fn test<'x>(x: &'x isize) {
+   |         -- lifetime `'x` defined here
+LL |     drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+LL |         x //~ ERROR E0312
+   |         ^ returning this value requires that `'x` must outlive `'static`
 
 error: aborting due to previous error
 
index 250e78ce2464005d9837f07fe7d7e4178cb4d369..857db50edbbc166f3971cb611b3674291251f33c 100644 (file)
@@ -11,9 +11,9 @@
 #![allow(safe_extern_statics, warnings)]
 
 extern {
-    pub static symbol: ();
+    pub static symbol: u32;
 }
-static CRASH: () = symbol;
+static CRASH: u32 = symbol;
 //~^ ERROR could not evaluate static initializer
 //~| tried to read from foreign (extern) static
 
index f5f39465b187b6bf95755e014607b25657197b5d..dc6c72d8a725620a92b6d0935565f5908683ca0d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0080]: could not evaluate static initializer
-  --> $DIR/issue-14227.rs:16:20
+  --> $DIR/issue-14227.rs:16:21
    |
-LL | static CRASH: () = symbol;
-   |                    ^^^^^^ tried to read from foreign (extern) static
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ tried to read from foreign (extern) static
 
 error: aborting due to previous error
 
index 3a6784eed67dd35d3adaaadb90b1bcd59d38ebc7..362778b26c861911d2624046c87cd15c65d575ea 100644 (file)
@@ -16,22 +16,22 @@ LL |     let b = unsafe { *imm_ref() };
    |                      cannot move out of borrowed content
    |                      help: consider removing the `*`: `imm_ref()`
 
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of dereference of raw pointer
   --> $DIR/issue-20801.rs:42:22
    |
 LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^
    |                      |
-   |                      cannot move out of borrowed content
+   |                      cannot move out of dereference of raw pointer
    |                      help: consider removing the `*`: `mut_ptr()`
 
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of dereference of raw pointer
   --> $DIR/issue-20801.rs:45:22
    |
 LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^
    |                      |
-   |                      cannot move out of borrowed content
+   |                      cannot move out of dereference of raw pointer
    |                      help: consider removing the `*`: `const_ptr()`
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/issues/issue-24338.rs b/src/test/ui/issues/issue-24338.rs
new file mode 100644 (file)
index 0000000..0c5db8f
--- /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.
+//
+// compile-pass
+
+trait DictLike<'a> {
+    type ItemsIterator: Iterator<Item=u8>;
+    fn get(c: Self::ItemsIterator) {
+        c.into_iter();
+    }
+}
+
+trait DictLike2<'a> {
+    type ItemsIterator: Iterator<Item=u8>;
+
+    fn items(&self) -> Self::ItemsIterator;
+
+    fn get(&self)  {
+        for _ in self.items() {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs
new file mode 100644 (file)
index 0000000..333b073
--- /dev/null
@@ -0,0 +1,13 @@
+// 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-flags: --test
+
+#![test] //~ ERROR only functions may be used as tests
diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr
new file mode 100644 (file)
index 0000000..cecbe5b
--- /dev/null
@@ -0,0 +1,8 @@
+error: only functions may be used as tests
+  --> $DIR/issue-28134.rs:13:1
+   |
+LL | #![test] //~ ERROR only functions may be used as tests
+   | ^^^^^^^^
+
+error: aborting due to previous error
+
index af8531feff23a3b927282bdd1eeb1e164f4e4a04..03b91a13224543a7e1b8e1a62f8ff4b459ce1ca3 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-pass
 #![allow(dead_code)]
-#![feature(min_const_fn)]
 
 fn main() {}
 
diff --git a/src/test/ui/issues/issue-29743.rs b/src/test/ui/issues/issue-29743.rs
new file mode 100644 (file)
index 0000000..e563bf0
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-pass
+
+fn main() {
+    let mut i = [1, 2, 3];
+    i[i[0]] = 0;
+    i[i[0] - 1] = 0;
+}
index 3a579c04de176c3d47d406e82855a067f8b09260..1aeb1a89ead94f3789bf472efd709b136d98bc3f 100644 (file)
@@ -1,15 +1,13 @@
-error: unsatisfied lifetime constraints
+error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-40510-1.rs:18:9
    |
 LL |     || {
-   |     --
-   |     ||
-   |     |return type of closure is &'2 mut std::boxed::Box<()>
-   |     lifetime `'1` represents this closure's body
+   |      - inferred to be a `FnMut` closure
 LL |         &mut x
-   |         ^^^^^^ returning this value requires that `'1` must outlive `'2`
+   |         ^^^^^^ returns a reference to a captured variable which escapes the closure body
    |
-   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
 
 error: aborting due to previous error
 
index 84ab2a8216deb48aac547bd11c20e01983b92eef..c334e592fbc2bb0be5c0fb5ea0d77f364bbf1128 100644 (file)
@@ -1,17 +1,15 @@
-error: unsatisfied lifetime constraints
+error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-40510-3.rs:18:9
    |
 LL |       || {
-   |       --
-   |       ||
-   |       |return type of closure is [closure@$DIR/issue-40510-3.rs:18:9: 20:10 x:&'2 mut std::vec::Vec<()>]
-   |       lifetime `'1` represents this closure's body
+   |        - inferred to be a `FnMut` closure
 LL | /         || {
 LL | |             x.push(())
 LL | |         }
-   | |_________^ returning this value requires that `'1` must outlive `'2`
+   | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |
-   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
 
 error: aborting due to previous error
 
index df43158ec9c7cdd47cfa1f28f1370622d0d8a46f..2e0463fdd1d860b7e2cf72952e6a681a4c43d357 100644 (file)
@@ -1,17 +1,15 @@
-error: unsatisfied lifetime constraints
+error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-49824.rs:22:9
    |
 LL |       || {
-   |       --
-   |       ||
-   |       |return type of closure is [closure@$DIR/issue-49824.rs:22:9: 24:10 x:&'2 mut i32]
-   |       lifetime `'1` represents this closure's body
+   |        - inferred to be a `FnMut` closure
 LL | /         || {
 LL | |             let _y = &mut x;
 LL | |         }
-   | |_________^ returning this value requires that `'1` must outlive `'2`
+   | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |
-   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
 
 error: aborting due to previous error
 
index 2fe72365bab1cbf5e9d045b13789ac8b985cc18b..944d57b5ba8f5866860e639ca29ae3ee5bde6f29 100644 (file)
@@ -109,6 +109,10 @@ fn bar() { //~ ERROR: function is never used
     foo();
 }
 
+fn baz() -> impl Copy { //~ ERROR: function is never used
+    "I'm unused, too"
+}
+
 // Code with #[allow(dead_code)] should be marked live (and thus anything it
 // calls is marked live)
 #[allow(dead_code)]
index 9802b7e8f383b4ed31eed7c2fa1663108266fc8d..9d8e44c25d87e3a8f3a52e4a8927ea45954d09d0 100644 (file)
@@ -58,5 +58,11 @@ error: function is never used: `bar`
 LL | fn bar() { //~ ERROR: function is never used
    | ^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: function is never used: `baz`
+  --> $DIR/lint-dead-code-1.rs:112:1
+   |
+LL | fn baz() -> impl Copy { //~ ERROR: function is never used
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
 
index ce2dfb906c5ce3cf648b728576c023a37a7f18cc..1eb82a20729ca8b60bfffdc7fa14ea1a98fa3a8a 100644 (file)
@@ -1,15 +1,4 @@
-// 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.
-
-// normalize-stderr-test: "The system cannot find the file specified\." -> "No such file or directory"
-// ignore-tidy-linelength
+// normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG ("
 
 // test that errors in a (selection) of macros don't kill compilation
 // immediately, so that we get more errors listed at a time.
index 81e250d5ea09e43ee780b4593039ba7f6ccbb514..ce7035ee2746130b8b390dda956193a615cb853a 100644 (file)
@@ -1,47 +1,47 @@
 error[E0665]: `Default` cannot be derived for enums, only structs
-  --> $DIR/macros-nonfatal-errors.rs:20:10
+  --> $DIR/macros-nonfatal-errors.rs:9:10
    |
 LL | #[derive(Default)] //~ ERROR
    |          ^^^^^^^
 
 error: inline assembly must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:24:10
+  --> $DIR/macros-nonfatal-errors.rs:13:10
    |
 LL |     asm!(invalid); //~ ERROR
    |          ^^^^^^^
 
 error: concat_idents! requires ident args.
-  --> $DIR/macros-nonfatal-errors.rs:26:5
+  --> $DIR/macros-nonfatal-errors.rs:15:5
    |
 LL |     concat_idents!("not", "idents"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:28:17
+  --> $DIR/macros-nonfatal-errors.rs:17:17
    |
 LL |     option_env!(invalid); //~ ERROR
    |                 ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:29:10
+  --> $DIR/macros-nonfatal-errors.rs:18:10
    |
 LL |     env!(invalid); //~ ERROR
    |          ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:30:10
+  --> $DIR/macros-nonfatal-errors.rs:19:10
    |
 LL |     env!(foo, abr, baz); //~ ERROR
    |          ^^^
 
 error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
-  --> $DIR/macros-nonfatal-errors.rs:31:5
+  --> $DIR/macros-nonfatal-errors.rs:20:5
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: format argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:33:13
+  --> $DIR/macros-nonfatal-errors.rs:22:13
    |
 LL |     format!(invalid); //~ ERROR
    |             ^^^^^^^
@@ -51,37 +51,37 @@ LL |     format!("{}", invalid); //~ ERROR
    |             ^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:35:14
+  --> $DIR/macros-nonfatal-errors.rs:24:14
    |
 LL |     include!(invalid); //~ ERROR
    |              ^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:37:18
+  --> $DIR/macros-nonfatal-errors.rs:26:18
    |
 LL |     include_str!(invalid); //~ ERROR
    |                  ^^^^^^^
 
-error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: No such file or directory (os error 2)
-  --> $DIR/macros-nonfatal-errors.rs:38:5
+error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/macros-nonfatal-errors.rs:27:5
    |
 LL |     include_str!("i'd be quite surprised if a file with this name existed"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:39:20
+  --> $DIR/macros-nonfatal-errors.rs:28:20
    |
 LL |     include_bytes!(invalid); //~ ERROR
    |                    ^^^^^^^
 
-error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: No such file or directory (os error 2)
-  --> $DIR/macros-nonfatal-errors.rs:40:5
+error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/macros-nonfatal-errors.rs:29:5
    |
 LL |     include_bytes!("i'd be quite surprised if a file with this name existed"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trace_macros! accepts only `true` or `false`
-  --> $DIR/macros-nonfatal-errors.rs:42:5
+  --> $DIR/macros-nonfatal-errors.rs:31:5
    |
 LL |     trace_macros!(invalid); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^
index 700c0dffb70115e70d6dfa5969307258414c7c91..3f7e400ed436008d2b4b4c26d0e77b58704c507a 100644 (file)
@@ -51,10 +51,10 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 #[rustc_regions]
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-        //~^ ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
index 2e1249a5e81264e07e6859ce9b8c333f95d1362c..ef84820de38eb4be589bb9f371ce1472b1c462cb 100644 (file)
@@ -3,10 +3,10 @@ note: External requirements
    |
 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(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -24,8 +24,8 @@ note: No external requirements
    |
 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 unsatisfied lifetime constraints
 LL | |
+LL | |         // Only works if 'x: 'y:
 ...  |
 LL | |     });
 LL | | }
@@ -34,20 +34,15 @@ LL | | }
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-ref.rs:53:47
+  --> $DIR/propagate-approximated-ref.rs:56:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --  -- lifetime `'b` defined here
-   |             |
-   |             lifetime `'a` defined here
-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(x, y, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
index 9963954c9c2d46a868b9bff6e9fe3f113214dd6f..49b6258164013b80f97ba02e7c0d4f9995c2926e 100644 (file)
@@ -44,10 +44,10 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
         //~^ ERROR borrowed data escapes outside of function
-        //~| ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
index 9f1d9d21d11c00a8cb006838fdeea0a6544c42e7..7ebd36e10b5645fe05dff563e6242584caa5f077 100644 (file)
@@ -4,10 +4,10 @@ note: External requirements
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |  _______________________________________________^
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -26,7 +26,7 @@ note: No external requirements
 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 | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
+LL | |
 ...  |
 LL | |     });
 LL | | }
@@ -41,29 +41,23 @@ LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |                     ------ `cell_a` is a reference that is only valid in the function body
 LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |______^ `cell_a` escapes the function body here
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:49:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --  -- lifetime `'b` defined here
-   |             |
-   |             lifetime `'a` defined here
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-   |  _______________________________________________^
-LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to 2 previous errors
 
index d35b5c34a91811fefefc796833fad76fefcdabae..0181792cbdcfff908312fd4ded11da193ac03c8c 100644 (file)
@@ -47,9 +47,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
         //~^ ERROR borrowed data escapes outside of function
-        //~| ERROR unsatisfied lifetime constraints
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
index 4e72fe4bb28aa9caf70face2b5626deac2481496..d62910576b0c3a886dfc47df5afd83aaf810a113 100644 (file)
@@ -4,9 +4,9 @@ note: External requirements
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
    |  _______________________________________________^
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -25,7 +25,7 @@ note: No external requirements
 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 borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
+LL | |         // Only works if 'x: 'y:
 ...  |
 LL | |     });
 LL | | }
@@ -40,27 +40,22 @@ LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |                     ------ `cell_a` is a reference that is only valid in the function body
 LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |______^ `cell_a` escapes the function body here
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:51:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --  -- lifetime `'b` defined here
-   |             |
-   |             lifetime `'a` defined here
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-   |  _______________________________________________^
-LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to 2 previous errors
 
index 75641943f2fac9bda57f92827d686f46114251a9..1a0531cbd42f65a9f7cf5b8a06178dadccc55796 100644 (file)
@@ -44,10 +44,10 @@ fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y:
 #[rustc_regions]
 fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-        //~^ ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
         demand_y(outlives1, outlives2, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
index de60b23ef6b974eb3f1931fc78e66ea0606e1f2b..aa193682404184e9fd05ba353d8830a443e4b7f2 100644 (file)
@@ -3,10 +3,10 @@ note: External requirements
    |
 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())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -24,8 +24,8 @@ note: No external requirements
    |
 LL | / fn test<'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 unsatisfied lifetime constraints
 LL | |
+LL | |         // Only works if 'x: 'y:
 ...  |
 LL | |     });
 LL | | }
@@ -34,20 +34,15 @@ LL | | }
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-val.rs:46:45
+  --> $DIR/propagate-approximated-val.rs:49:9
    |
-LL |   fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-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())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |         demand_y(outlives1, outlives2, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-52663-trait-object.rs b/src/test/ui/nll/issue-52663-trait-object.rs
new file mode 100644 (file)
index 0000000..65d73ee
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+#![feature(box_syntax)]
+#![feature(nll)]
+
+trait Foo { fn get(&self); }
+
+impl<A> Foo for A {
+    fn get(&self) { }
+}
+
+fn main() {
+    let _ = {
+        let tmp0 = 3;
+        let tmp1 = &tmp0;
+        box tmp1 as Box<Foo + '_>
+    };
+    //~^^^ ERROR `tmp0` does not live long enough
+}
diff --git a/src/test/ui/nll/issue-52663-trait-object.stderr b/src/test/ui/nll/issue-52663-trait-object.stderr
new file mode 100644 (file)
index 0000000..035422f
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0597]: `tmp0` does not live long enough
+  --> $DIR/issue-52663-trait-object.rs:23:20
+   |
+LL |         let tmp1 = &tmp0;
+   |                    ^^^^^ borrowed value does not live long enough
+LL |         box tmp1 as Box<Foo + '_>
+   |         ------------------------- borrow later captured here by trait object
+LL |     };
+   |     - `tmp0` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-53040.rs b/src/test/ui/nll/issue-53040.rs
new file mode 100644 (file)
index 0000000..2b6e67b
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+fn main() {
+    let mut v: Vec<()> = Vec::new();
+    || &mut v;
+}
diff --git a/src/test/ui/nll/issue-53040.stderr b/src/test/ui/nll/issue-53040.stderr
new file mode 100644 (file)
index 0000000..fac9969
--- /dev/null
@@ -0,0 +1,13 @@
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-53040.rs:15:8
+   |
+LL |     || &mut v;
+   |      - ^^^^^^ returns a reference to a captured variable which escapes the closure body
+   |      |
+   |      inferred to be a `FnMut` closure
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+
+error: aborting due to previous error
+
index 455fbba232007482e269fd28cc5ddd66a4fd9f6b..dc7f58fc8f8432f0ebdd4b84be8eb0f32087ebb5 100644 (file)
@@ -41,7 +41,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))`...
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:55:29
+  --> $DIR/projection-one-region-closure.rs:55:39
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          --  -- lifetime `'b` defined here
@@ -49,7 +49,7 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:66:29
@@ -95,7 +95,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:66:29
+  --> $DIR/projection-one-region-closure.rs:66:39
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -103,7 +103,7 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:80:29
index b98aca74058b97d1c915449551e3bafa764eb2dd..18d35d8b9bf68f42bfef091d6b8e5131d5655e70 100644 (file)
@@ -32,7 +32,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          --  -- lifetime `'b` defined here
@@ -40,7 +40,7 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:57:29
@@ -77,7 +77,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:57:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:57:39
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -85,7 +85,7 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:70:29
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
new file mode 100644 (file)
index 0000000..526134b
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar { field: &'a u32 }
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static> { field: _z } = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
new file mode 100644 (file)
index 0000000..5dbbf7c
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:9:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:16:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = 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/nll/user-annotations/pattern_substs_on_brace_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
new file mode 100644 (file)
index 0000000..1c92858
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a> { field: &'a u32 }
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static> { field: _z } = foo;
+}
+
+fn in_main() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
new file mode 100644 (file)
index 0000000..0108a18
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:7:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:14:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = 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/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
new file mode 100644 (file)
index 0000000..d6c364f
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar(&'a u32)
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
new file mode 100644 (file)
index 0000000..b18fdc3
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:9:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:16:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = 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/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
new file mode 100644 (file)
index 0000000..626ca90
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a>(&'a u32);
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
new file mode 100644 (file)
index 0000000..b72fda9
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:7:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:14:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = 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/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed
new file mode 100644 (file)
index 0000000..4d8f671
--- /dev/null
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(&::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(&std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(&::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(&std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(&::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(&std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(&::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(&std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(&::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs
new file mode 100644 (file)
index 0000000..dc21dcb
--- /dev/null
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr
new file mode 100644 (file)
index 0000000..b8811c9
--- /dev/null
@@ -0,0 +1,147 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:16:16
+   |
+LL |     take_range(std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:21:16
+   |
+LL |     take_range(::std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:26:16
+   |
+LL |     take_range(std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:31:16
+   |
+LL |     take_range(::std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:36:16
+   |
+LL |     take_range(std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:41:16
+   |
+LL |     take_range(::std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&::std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:46:16
+   |
+LL |     take_range(std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:51:16
+   |
+LL |     take_range(::std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:56:16
+   |
+LL |     take_range(std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:61:16
+   |
+LL |     take_range(::std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:66:16
+   |
+LL |     take_range(std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:71:16
+   |
+LL |     take_range(::std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
new file mode 100644 (file)
index 0000000..1915fd8
--- /dev/null
@@ -0,0 +1,57 @@
+// error-pattern: `#[panic_handler]` function required, but not found
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+// This test doesn't use std
+// (so all Ranges resolve to core::ops::Range...)
+
+#![no_std]
+#![feature(lang_items)]
+
+use core::ops::RangeBounds;
+
+#[cfg(not(target_arch = "wasm32"))]
+#[lang = "eh_personality"]
+extern fn eh_personality() {}
+
+#[cfg(target_os = "windows")]
+#[lang = "eh_unwind_resume"]
+extern fn eh_unwind_resume() {}
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr
new file mode 100644 (file)
index 0000000..4922e59
--- /dev/null
@@ -0,0 +1,77 @@
+error: `#[panic_handler]` function required, but not found
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:28:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `core::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:33:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:38:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:43:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:48:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:53:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed
new file mode 100644 (file)
index 0000000..f8298c0
--- /dev/null
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&(0..1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(&(1..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(&(..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(&(0..=1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(&(..5));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(&(..=42));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs
new file mode 100644 (file)
index 0000000..0367325
--- /dev/null
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr
new file mode 100644 (file)
index 0000000..d6e1fb0
--- /dev/null
@@ -0,0 +1,75 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:14:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:19:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:24:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:29:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:34:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:39:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 6e4bf26047e4679348f1136cd8b7cbdde748bb95..fd52494b4994746caedaa6eec7893f712c429bfc 100644 (file)
@@ -21,16 +21,13 @@ LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot in
    = note: closure implements `FnMut`, so references to captured variables can't escape the closure
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-addr-of-upvar-self.rs:19:18
+  --> $DIR/regions-addr-of-upvar-self.rs:20:17
    |
-LL |       pub fn chase_cat(&mut self) {
-   |                        - let's call the lifetime of this reference `'1`
-LL |           let _f = || {
-   |  __________________^
-LL | |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
-LL | |             *p = 3;
-LL | |         };
-   | |_________^ closure body requires that `'1` must outlive `'static`
+LL |     pub fn chase_cat(&mut self) {
+   |                      - let's call the lifetime of this reference `'1`
+LL |         let _f = || {
+LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
+   |                 ^ type annotation requires that `'1` must outlive `'static`
 
 error[E0597]: `self` does not live long enough
   --> $DIR/regions-addr-of-upvar-self.rs:20:46
index 4bb602d572fa3e5a650bc335913f0901cfa50e29..cbc1e6b787db508acab16a4b60383571e19c076d 100644 (file)
@@ -36,18 +36,13 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-nested-fns.rs:23:68
+  --> $DIR/regions-nested-fns.rs:24:27
    |
-LL |   fn nested<'x>(x: &'x isize) {
-   |             -- lifetime `'x` defined here
+LL | fn nested<'x>(x: &'x isize) {
+   |           -- lifetime `'x` defined here
 ...
-LL |       ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
-   |  ____________________________________________________________________^
-LL | |         if false { return x; } //~ ERROR E0312
-LL | |         if false { return ay; }
-LL | |         return z;
-LL | |     }));
-   | |_____^ closure body requires that `'x` must outlive `'static`
+LL |         if false { return x; } //~ ERROR E0312
+   |                           ^ returning this value requires that `'x` must outlive `'static`
 
 error: aborting due to 4 previous errors
 
index 35c1da61ae28fba30b4e3297d90cdaf73fd75853..300a563982253df694561b4d814cb2078446799b 100644 (file)
@@ -1,13 +1,13 @@
-error: unsatisfied lifetime constraints
+error: captured variable cannot escape `FnMut` closure body
   --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:17:24
    |
 LL |         let mut f = || &mut x; //~ ERROR cannot infer
-   |                     -- ^^^^^^ returning this value requires that `'1` must outlive `'2`
-   |                     ||
-   |                     |return type of closure is &'2 mut i32
-   |                     lifetime `'1` represents this closure's body
+   |                      - ^^^^^^ returns a reference to a captured variable which escapes the closure body
+   |                      |
+   |                      inferred to be a `FnMut` closure
    |
-   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-54379.rs b/src/test/ui/resolve/issue-54379.rs
new file mode 100644 (file)
index 0000000..24aa758
--- /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.
+struct MyStruct {
+    pub s1: Option<String>,
+}
+
+fn main() {
+    let thing = MyStruct { s1: None };
+
+    match thing {
+        MyStruct { .., Some(_) } => {},
+        _ => {}
+    }
+}
diff --git a/src/test/ui/resolve/issue-54379.stderr b/src/test/ui/resolve/issue-54379.stderr
new file mode 100644 (file)
index 0000000..d1d693a
--- /dev/null
@@ -0,0 +1,24 @@
+error: expected `}`, found `,`
+  --> $DIR/issue-54379.rs:18:22
+   |
+LL |         MyStruct { .., Some(_) } => {},
+   |                    --^
+   |                    | |
+   |                    | expected `}`
+   |                    `..` must be at the end and cannot have a trailing comma
+
+error: expected `,`
+  --> $DIR/issue-54379.rs:18:24
+   |
+LL |         MyStruct { .., Some(_) } => {},
+   |                        ^^^^
+
+error[E0027]: pattern does not mention field `s1`
+  --> $DIR/issue-54379.rs:18:9
+   |
+LL |         MyStruct { .., Some(_) } => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `s1`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
new file mode 100644 (file)
index 0000000..5ba7df8
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+
+// Test that we DO warn when lifetime name is not used at all.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code, unused_variables)]
+
+fn september() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP remove it
+
+fn october<'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP remove it
+    s
+}
+
+fn november<'a>(s: &'a str) -> (&'a str) {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP remove it
+    s
+}
+
+fn main() {}
index 7152d122f79a351b54c2a5df2972a095d37c49a1..a56d7fa8abc0275f40b323c8afc47bf2c948f6ae 100644 (file)
@@ -1,19 +1,24 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+// run-rustfix
 
 // Test that we DO warn when lifetime name is not used at all.
 
 #![deny(unused_lifetimes)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
+#![allow(dead_code, unused_variables)]
 
-fn d<'a>() { } //~ ERROR `'a` never used
+fn september<'a>() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP remove it
 
-fn main() { }
+fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP remove it
+    s
+}
+
+fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP remove it
+    s
+}
+
+fn main() {}
index 322351a0a8e5b4485e1b691cbca7a27444d22d25..566c841cfa96984e853341f0fcc7c866b10e34d5 100644 (file)
@@ -1,14 +1,30 @@
 error: lifetime parameter `'a` never used
-  --> $DIR/zero-uses-in-fn.rs:17:6
+  --> $DIR/zero-uses-in-fn.rs:8:14
    |
-LL | fn d<'a>() { } //~ ERROR `'a` never used
-   |      ^^
+LL | fn september<'a>() {}
+   |             -^^- help: remove it
    |
 note: lint level defined here
-  --> $DIR/zero-uses-in-fn.rs:13:9
+  --> $DIR/zero-uses-in-fn.rs:5:9
    |
 LL | #![deny(unused_lifetimes)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-fn.rs:12:12
+   |
+LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+   |            ^^--
+   |            |
+   |            help: remove it
+
+error: lifetime parameter `'b` never used
+  --> $DIR/zero-uses-in-fn.rs:18:17
+   |
+LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+   |               --^^
+   |               |
+   |               help: remove it
+
+error: aborting due to 3 previous errors
 
index a231c0bf003311ca348746f9481cda5ad78b9578..54803e1d2be4248dd652275b93f01b1d58addddb 100644 (file)
@@ -1,21 +1,10 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
 // Test that we DO warn when lifetime name is not used at all.
 
 #![deny(unused_lifetimes)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
+#![allow(dead_code, unused_variables)]
 
-struct Foo { }
+struct Foo {}
 
-impl<'a> Foo { } //~ ERROR `'a` never used
+impl<'a> Foo {} //~ ERROR `'a` never used
 
-fn main() { }
+fn main() {}
index 34cb15c1339d8837c7b842fb95f58157b8a989b6..1b77ebdec99c6af0986e62cfea945893261dc773 100644 (file)
@@ -1,11 +1,11 @@
 error: lifetime parameter `'a` never used
-  --> $DIR/zero-uses-in-impl.rs:19:6
+  --> $DIR/zero-uses-in-impl.rs:8:6
    |
-LL | impl<'a> Foo { } //~ ERROR `'a` never used
-   |      ^^
+LL | impl<'a> Foo {} //~ ERROR `'a` never used
+   |     -^^- help: remove it
    |
 note: lint level defined here
-  --> $DIR/zero-uses-in-impl.rs:13:9
+  --> $DIR/zero-uses-in-impl.rs:3:9
    |
 LL | #![deny(unused_lifetimes)]
    |         ^^^^^^^^^^^^^^^^
index f8e5e3914eb3cc2fcb64216e89a2be526ce97eae..11fa447b5489a0e7739e0271bde49cd3a9ff647c 100644 (file)
@@ -4,7 +4,7 @@ error[E0597]: `tmp0` does not live long enough
 LL |         let tmp1 = &tmp0;
    |                    ^^^^^ borrowed value does not live long enough
 LL |         repeater3(tmp1)
-   |         --------------- borrow later used here
+   |         --------------- borrow later captured here by trait object
 LL |     };
    |     - `tmp0` dropped here while still borrowed
 
index ea1efab4cb6f87d8a4ec360f5aad74dd7ebdb386..4134fca1ce6caa31be3d148495cd73e50bef8388 100644 (file)
@@ -10,7 +10,7 @@
 
 // Don't allow tool_lints, which aren't scoped
 
-#![feature(tool_lints)]
+
 #![deny(unknown_lints)]
 
 #![deny(clippy)] //~ ERROR: unknown lint: `clippy`
index 71f90b17c18fcefd792a8d6a36ccbab0779db93d..001f2f11e5cb358c17d94222d0ba3fa9214fb956 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_lints)]
+
 
 #[warn(foo::bar)]
 //~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
diff --git a/src/test/ui/traits/conservative_impl_trait.rs b/src/test/ui/traits/conservative_impl_trait.rs
new file mode 100644 (file)
index 0000000..3f119af
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// #39665
+
+fn batches(n: &u32) -> impl Iterator<Item=&u32> {
+    std::iter::once(n)
+}
+
+fn main() {}
diff --git a/src/test/ui/union-ub-fat-ptr.rs b/src/test/ui/union-ub-fat-ptr.rs
deleted file mode 100644 (file)
index 0c42d28..0000000
+++ /dev/null
@@ -1,139 +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.
-
-#![allow(unused)]
-
-// normalize-stderr-test "alignment \d+" -> "alignment N"
-// normalize-stderr-test "offset \d+" -> "offset N"
-// normalize-stderr-test "allocation \d+" -> "allocation N"
-// normalize-stderr-test "size \d+" -> "size N"
-
-union BoolTransmute {
-  val: u8,
-  bl: bool,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct SliceRepr {
-    ptr: *const u8,
-    len: usize,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct BadSliceRepr {
-    ptr: *const u8,
-    len: &'static u8,
-}
-
-union SliceTransmute {
-    repr: SliceRepr,
-    bad: BadSliceRepr,
-    slice: &'static [u8],
-    str: &'static str,
-    my_str: &'static MyStr,
-    my_slice: &'static MySliceBool,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct DynRepr {
-    ptr: *const u8,
-    vtable: *const u8,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct DynRepr2 {
-    ptr: *const u8,
-    vtable: *const u64,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct BadDynRepr {
-    ptr: *const u8,
-    vtable: usize,
-}
-
-union DynTransmute {
-    repr: DynRepr,
-    repr2: DynRepr2,
-    bad: BadDynRepr,
-    rust: &'static Trait,
-}
-
-trait Trait {}
-impl Trait for bool {}
-
-// custom unsized type
-struct MyStr(str);
-
-// custom unsized type with sized fields
-struct MySlice<T: ?Sized>(bool, T);
-type MySliceBool = MySlice<[bool]>;
-
-// OK
-const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
-// bad str
-const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad str
-const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad str in user-defined unsized type
-const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// OK
-const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
-// bad slice
-const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad slice
-const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// bad trait object
-const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad trait object
-const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad trait object
-const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// bad data *inside* the trait object
-const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad data *inside* the slice
-const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// good MySliceBool
-const I1: &MySliceBool = &MySlice(true, [false]);
-// bad: sized field is not okay
-const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad: unsized part is not okay
-const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// invalid UTF-8
-const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
-//~^ ERROR this constant likely exhibits undefined behavior
-// invalid UTF-8 in user-defined str-like
-const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
-//~^ ERROR this constant likely exhibits undefined behavior
-
-fn main() {
-}
diff --git a/src/test/ui/union-ub-fat-ptr.stderr b/src/test/ui/union-ub-fat-ptr.stderr
deleted file mode 100644 (file)
index 5d817dc..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:87:1
-   |
-LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or out-of-bounds memory at .<deref>
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:90:1
-   |
-LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:93:1
-   |
-LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:99:1
-   |
-LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or out-of-bounds memory at .<deref>[1]
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:102:1
-   |
-LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:106:1
-   |
-LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid vtable in fat pointer at .<deref>
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:109:1
-   |
-LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid vtable in fat pointer at .<deref>
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:112:1
-   |
-LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:116:1
-   |
-LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>, but expected something in the range 0..=1
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:119:1
-   |
-LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something in the range 0..=1
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:125:1
-   |
-LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something in the range 0..=1
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:128:1
-   |
-LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something in the range 0..=1
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:132:1
-   |
-LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-UTF-8 data in str at .<deref>
-   |
-   = 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[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:135:1
-   |
-LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-UTF-8 data in str at .<deref>.0
-   |
-   = 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: aborting due to 14 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
index 78b736edcebe6e0699beae6d7deb7c789518718a..a1d6c27e518e514268c2221e2e611ea450161d77 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_lints)]
+
 
 #![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
 
index fe0bb7533a86f316f53ed19a548d763ea4a136bc..88be25066ce40c7e21aeb69ba310dc5b0bce98ff 100644 (file)
@@ -10,8 +10,6 @@
 
 // A quick test of 'unsafe const fn' functionality
 
-#![feature(min_const_fn)]
-
 const unsafe fn dummy(v: u32) -> u32 {
     !v
 }
index d4b3ed687e5e43b956c595f7004e9f29cb1d9e00..d1a267d4f842e723752071c58d0224d3e3d8ff07 100644 (file)
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-const-fn.rs:19:18
+  --> $DIR/unsafe-const-fn.rs:17:18
    |
 LL | const VAL: u32 = dummy(0xFFFF);
    |                  ^^^^^^^^^^^^^ call to unsafe function
index a4d839275c3ebc4bb5f8da11c6b21ce41dd2461a..7006fb9427e1cec2332ee8d4afa2e9d7fcc9c249 100644 (file)
@@ -205,6 +205,9 @@ pub struct Config {
     /// Version of LLDB
     pub lldb_version: Option<String>,
 
+    /// Whether LLDB has native rust support
+    pub lldb_native_rust: bool,
+
     /// Version of LLVM
     pub llvm_version: Option<String>,
 
index 8829d8808366b87f027b2c6df347e800966773f0..688f2babe6e8c2c570306107660cd54db7128269 100644 (file)
@@ -133,6 +133,8 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
                     // Ignore if actual version is smaller the minimum required
                     // version
                     lldb_version_to_int(actual_version) < lldb_version_to_int(min_version)
+                } else if line.starts_with("rust-lldb") && !config.lldb_native_rust {
+                    true
                 } else {
                     false
                 }
index 2fa459bec9455d930b8f5d3176078fba774e2d1c..f46e031d768bd9f6284175d9fe0d9f5345b2baef 100644 (file)
@@ -282,6 +282,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
     let android_cross_path = opt_path(matches, "android-cross-path");
     let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target,
                                                           &android_cross_path);
+    let (lldb_version, lldb_native_rust) = extract_lldb_version(matches.opt_str("lldb-version"));
 
     let color = match matches.opt_str("color").as_ref().map(|x| &**x) {
         Some("auto") | None => ColorConfig::AutoColor,
@@ -326,7 +327,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         gdb,
         gdb_version,
         gdb_native_rust,
-        lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
+        lldb_version,
+        lldb_native_rust,
         llvm_version: matches.opt_str("llvm-version"),
         system_llvm: matches.opt_present("system-llvm"),
         android_cross_path: android_cross_path,
@@ -906,17 +908,27 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
     None
 }
 
-fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
+/// Returns (LLDB version, LLDB is rust-enabled)
+fn extract_lldb_version(full_version_line: Option<String>) -> (Option<String>, bool) {
     // Extract the major LLDB version from the given version string.
     // LLDB version strings are different for Apple and non-Apple platforms.
-    // At the moment, this function only supports the Apple variant, which looks
-    // like this:
+    // The Apple variant looks like this:
     //
     // LLDB-179.5 (older versions)
     // lldb-300.2.51 (new versions)
     //
     // We are only interested in the major version number, so this function
     // will return `Some("179")` and `Some("300")` respectively.
+    //
+    // Upstream versions look like:
+    // lldb version 6.0.1
+    //
+    // There doesn't seem to be a way to correlate the Apple version
+    // with the upstream version, and since the tests were originally
+    // written against Apple versions, we make a fake Apple version by
+    // multiplying the first number by 100.  This is a hack, but
+    // normally fine because the only non-Apple version we test is
+    // rust-enabled.
 
     if let Some(ref full_version_line) = full_version_line {
         if !full_version_line.trim().is_empty() {
@@ -951,12 +963,22 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
                     .take_while(|c| c.is_digit(10))
                     .collect::<String>();
                 if !vers.is_empty() {
-                    return Some(vers);
+                    return (Some(vers), full_version_line.contains("rust-enabled"));
+                }
+            }
+
+            if full_version_line.starts_with("lldb version ") {
+                let vers = full_version_line[13..]
+                    .chars()
+                    .take_while(|c| c.is_digit(10))
+                    .collect::<String>();
+                if !vers.is_empty() {
+                    return (Some(vers + "00"), full_version_line.contains("rust-enabled"));
                 }
             }
         }
     }
-    None
+    (None, false)
 }
 
 fn is_blacklisted_lldb_version(version: &str) -> bool {
index 63a282c227c246b764ccb46abaaaceb747993fe2..4cb6f6b83bdd10e40a1ce0f576acdf109e85688f 100644 (file)
@@ -945,13 +945,23 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
             }
         }
 
+        let prefixes = if self.config.lldb_native_rust {
+            static PREFIXES: &'static [&'static str] = &["lldb", "lldbr"];
+            println!("NOTE: compiletest thinks it is using LLDB with native rust support");
+            PREFIXES
+        } else {
+            static PREFIXES: &'static [&'static str] = &["lldb", "lldbg"];
+            println!("NOTE: compiletest thinks it is using LLDB without native rust support");
+            PREFIXES
+        };
+
         // Parse debugger commands etc from test files
         let DebuggerCommands {
             commands,
             check_lines,
             breakpoint_lines,
             ..
-        } = self.parse_debugger_commands(&["lldb"]);
+        } = self.parse_debugger_commands(prefixes);
 
         // Write debugger script:
         // We don't want to hang when calling `quit` while the process is still running
index e8f6973e2d40ab39e30cdbe0cf8e77a72c867d4f..cc275c63a90d4bea394e76607b2e10611eb1be36 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e8f6973e2d40ab39e30cdbe0cf8e77a72c867d4f
+Subproject commit cc275c63a90d4bea394e76607b2e10611eb1be36