]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix
authorbors <bors@rust-lang.org>
Fri, 25 Jan 2019 14:25:37 +0000 (14:25 +0000)
committerbors <bors@rust-lang.org>
Fri, 25 Jan 2019 14:25:37 +0000 (14:25 +0000)
[NLL] Clean up handling of type annotations

* Renames (Canonical)?UserTypeAnnotation -> (Canonical)?UserType so that the name CanonicalUserTypeAnnotation is free.
* Keep the inferred type associated to user type annotations in the MIR, so that it can be compared against the annotated type, even when the annotated expression gets removed from the MIR. (#54943)
* Use the inferred type to allow infallible handling of user type projections (#57531)
* Uses revisions for the tests in #56993
* Check the types of `Unevaluated` constants with no annotations (#46702)
* Some drive-by cleanup

Closes #46702
Closes #54943
Closes #57531
Closes #57731
cc #56993 leaving this open to track the underlying issue: we are not running tests with full NLL enabled on CI at the moment

r? @nikomatsakis

452 files changed:
.gitattributes
Cargo.lock
appveyor.yml
config.toml.example
src/README.md
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/mk/Makefile.in
src/bootstrap/native.rs
src/bootstrap/test.rs
src/ci/docker/dist-various-1/install-x86_64-redox.sh
src/ci/docker/dist-various-2/Dockerfile
src/ci/docker/scripts/android-sdk.sh
src/doc/unstable-book/src/language-features/plugin.md
src/doc/unstable-book/src/library-features/is-sorted.md [new file with mode: 0644]
src/etc/gdb_rust_pretty_printing.py
src/libcore/any.rs
src/libcore/benches/fmt.rs [new file with mode: 0644]
src/libcore/benches/lib.rs
src/libcore/convert.rs
src/libcore/fmt/mod.rs
src/libcore/iter/iterator.rs
src/libcore/lib.rs
src/libcore/num/dec2flt/mod.rs
src/libcore/num/mod.rs
src/libcore/ops/index.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/tests/iter.rs
src/libcore/tests/lib.rs
src/libcore/tests/nonzero.rs
src/libcore/tests/slice.rs
src/libfmt_macros/lib.rs
src/librustc/cfg/construct.rs
src/librustc/dep_graph/graph.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/higher_ranked/README.md
src/librustc/infer/lexical_region_resolve/README.md
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/region_constraints/README.md
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/session/config.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/select.rs
src/librustc/ty/item_path.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/README.md
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/lib.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/lib.rs
src/librustc_codegen_ssa/mir/constant.rs
src/librustc_codegen_ssa/mono_item.rs
src/librustc_codegen_utils/lib.rs
src/librustc_data_structures/obligation_forest/README.md [deleted file]
src/librustc_data_structures/obligation_forest/mod.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/universal_regions.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/hair/constant.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/snapshot.rs
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/util/pretty.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/powerpc64_unknown_freebsd.rs [new file with mode: 0644]
src/librustc_traits/lowering/mod.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/favicon.ico [new file with mode: 0644]
src/librustdoc/html/static/rust-logo.png [new file with mode: 0644]
src/librustdoc/html/static_files.rs
src/librustdoc/lib.rs
src/librustdoc/passes/check_code_block_syntax.rs [new file with mode: 0644]
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/mod.rs
src/libstd/future.rs
src/libstd/lib.rs
src/libstd/os/fortanix_sgx/mod.rs
src/libstd/sys/sgx/ext/ffi.rs [new file with mode: 0644]
src/libstd/sys/sgx/ext/mod.rs
src/libstd/sys/sgx/rwlock.rs
src/libstd/sys/unix/fast_thread_local.rs
src/libstd/sys/windows/time.rs
src/libstd/thread/local.rs
src/libstd/time.rs
src/libsyntax/ast.rs
src/libsyntax/attr/mod.rs
src/libsyntax/ext/quote.rs [deleted file]
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/ptr.rs
src/libsyntax/tokenstream.rs
src/libsyntax/util/parser_testing.rs
src/libsyntax/visit.rs
src/libsyntax_ext/concat.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_server.rs
src/libsyntax_pos/lib.rs
src/test/codegen/simd-intrinsic-generic-bitmask.rs [new file with mode: 0644]
src/test/run-fail-fulldeps/qquote.rs [deleted file]
src/test/run-pass-fulldeps/auxiliary/issue-16723.rs [deleted file]
src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
src/test/run-pass-fulldeps/auxiliary/plugin_with_plugin_lib.rs [deleted file]
src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs [deleted file]
src/test/run-pass-fulldeps/auxiliary/syntax_extension_with_dll_deps_2.rs [deleted file]
src/test/run-pass-fulldeps/issue-16723.rs [deleted file]
src/test/run-pass-fulldeps/issue-16992.rs [deleted file]
src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs [deleted file]
src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs [deleted file]
src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs [deleted file]
src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs
src/test/run-pass-fulldeps/macro-crate.rs [deleted file]
src/test/run-pass-fulldeps/mbe_matching_test_macro.rs [deleted file]
src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs [deleted file]
src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs [deleted file]
src/test/run-pass-fulldeps/qquote.rs [deleted file]
src/test/run-pass-fulldeps/quote-tokens.rs [deleted file]
src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs [deleted file]
src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs [deleted file]
src/test/run-pass/simd/simd-intrinsic-generic-bitmask.rs [new file with mode: 0644]
src/test/run-pass/try_from.rs [new file with mode: 0644]
src/test/rustdoc-ui/invalid-syntax.rs
src/test/rustdoc-ui/invalid-syntax.stderr
src/test/rustdoc/bad-codeblock-syntax.rs [new file with mode: 0644]
src/test/rustdoc/proc-macro.rs
src/test/ui-fulldeps/auxiliary/macro_crate_test.rs [deleted file]
src/test/ui-fulldeps/gated-plugin.rs
src/test/ui-fulldeps/gated-plugin.stderr
src/test/ui-fulldeps/gated-quote.rs [deleted file]
src/test/ui-fulldeps/gated-quote.stderr [deleted file]
src/test/ui-fulldeps/issue-48941.rs [deleted file]
src/test/ui-fulldeps/issue-48941.stderr [deleted file]
src/test/ui-fulldeps/macro-crate-doesnt-resolve.rs [deleted file]
src/test/ui-fulldeps/macro-crate-doesnt-resolve.stderr [deleted file]
src/test/ui-fulldeps/macro-crate-unexported-macro.rs [deleted file]
src/test/ui-fulldeps/macro-crate-unexported-macro.stderr [deleted file]
src/test/ui-fulldeps/plugin-as-extern-crate.rs
src/test/ui-fulldeps/plugin-as-extern-crate.stderr
src/test/ui-fulldeps/plugin-plus-extern-crate.rs [deleted file]
src/test/ui-fulldeps/plugin-plus-extern-crate.stderr [deleted file]
src/test/ui-fulldeps/qquote.rs [deleted file]
src/test/ui-fulldeps/qquote.stderr [deleted file]
src/test/ui/auto-ref-slice-plus-ref.stderr
src/test/ui/binop/binop-consume-args.nll.stderr [new file with mode: 0644]
src/test/ui/binop/binop-move-semantics.nll.stderr
src/test/ui/block-result/issue-3563.stderr
src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
src/test/ui/borrowck/borrowck-asm.mir.stderr
src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr
src/test/ui/borrowck/borrowck-drop-from-guard.stderr
src/test/ui/borrowck/borrowck-issue-48962.stderr
src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr
src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr
src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr
src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr
src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr
src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr
src/test/ui/borrowck/borrowck-reinit.stderr
src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr
src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr
src/test/ui/borrowck/borrowck-union-move.nll.stderr
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr
src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
src/test/ui/cast/cast-ptr-to-int-const.rs
src/test/ui/cast/cast-ptr-to-int-const.stderr
src/test/ui/codemap_tests/tab_3.nll.stderr
src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
src/test/ui/consts/const-eval/ub-nonnull.rs
src/test/ui/consts/const-eval/ub-nonnull.stderr
src/test/ui/consts/const-size_of-cycle.stderr
src/test/ui/consts/match_ice.rs [new file with mode: 0644]
src/test/ui/consts/match_ice.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
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/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
src/test/ui/e0119/conflict-with-std.stderr
src/test/ui/empty/empty-struct-braces-expr.stderr
src/test/ui/error-codes/E0214.stderr
src/test/ui/error-codes/E0395.rs
src/test/ui/error-codes/E0395.stderr
src/test/ui/existential_types/auxiliary/cross_crate_ice.rs [new file with mode: 0644]
src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs [new file with mode: 0644]
src/test/ui/existential_types/cross_crate_ice.rs [new file with mode: 0644]
src/test/ui/existential_types/cross_crate_ice2.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-is_sorted.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-is_sorted.stderr [new file with mode: 0644]
src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/equality.stderr
src/test/ui/index-help.stderr
src/test/ui/indexing-requires-a-uint.rs
src/test/ui/indexing-requires-a-uint.stderr
src/test/ui/integral-indexing.rs
src/test/ui/integral-indexing.stderr
src/test/ui/issues/auxiliary/issue-56943.rs [new file with mode: 0644]
src/test/ui/issues/issue-17385.nll.stderr
src/test/ui/issues/issue-17458.rs
src/test/ui/issues/issue-17458.stderr
src/test/ui/issues/issue-18294.rs
src/test/ui/issues/issue-18294.stderr
src/test/ui/issues/issue-23217.stderr
src/test/ui/issues/issue-23589.rs
src/test/ui/issues/issue-23589.stderr
src/test/ui/issues/issue-24357.nll.stderr
src/test/ui/issues/issue-25700.nll.stderr [new file with mode: 0644]
src/test/ui/issues/issue-25826.rs
src/test/ui/issues/issue-25826.stderr
src/test/ui/issues/issue-26548.stderr
src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr
src/test/ui/issues/issue-28344.stderr
src/test/ui/issues/issue-28971.stderr
src/test/ui/issues/issue-29723.stderr
src/test/ui/issues/issue-32995-2.rs
src/test/ui/issues/issue-32995-2.stderr
src/test/ui/issues/issue-32995.rs
src/test/ui/issues/issue-32995.stderr
src/test/ui/issues/issue-34721.rs [new file with mode: 0644]
src/test/ui/issues/issue-34721.stderr [new file with mode: 0644]
src/test/ui/issues/issue-42796.nll.stderr
src/test/ui/issues/issue-44415.stderr
src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
src/test/ui/issues/issue-52496.rs [new file with mode: 0644]
src/test/ui/issues/issue-52496.stderr [new file with mode: 0644]
src/test/ui/issues/issue-54521-1.rs [new file with mode: 0644]
src/test/ui/issues/issue-54521-2.fixed [new file with mode: 0644]
src/test/ui/issues/issue-54521-2.rs [new file with mode: 0644]
src/test/ui/issues/issue-54521-2.stderr [new file with mode: 0644]
src/test/ui/issues/issue-54521.fixed [new file with mode: 0644]
src/test/ui/issues/issue-54521.rs [new file with mode: 0644]
src/test/ui/issues/issue-54521.stderr [new file with mode: 0644]
src/test/ui/issues/issue-54582.rs [new file with mode: 0644]
src/test/ui/issues/issue-56488.rs [new file with mode: 0644]
src/test/ui/issues/issue-56943.rs [new file with mode: 0644]
src/test/ui/issues/issue-56943.stderr [new file with mode: 0644]
src/test/ui/issues/issue-57684.fixed [new file with mode: 0644]
src/test/ui/issues/issue-57684.rs [new file with mode: 0644]
src/test/ui/issues/issue-57684.stderr [new file with mode: 0644]
src/test/ui/issues/issue-57741-1.rs [new file with mode: 0644]
src/test/ui/issues/issue-57741-1.stderr [new file with mode: 0644]
src/test/ui/issues/issue-57741.fixed [new file with mode: 0644]
src/test/ui/issues/issue-57741.rs [new file with mode: 0644]
src/test/ui/issues/issue-57741.stderr [new file with mode: 0644]
src/test/ui/lint/lint-incoherent-auto-trait-objects.rs [new file with mode: 0644]
src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr [new file with mode: 0644]
src/test/ui/liveness/liveness-forgot-ret.stderr
src/test/ui/liveness/liveness-move-call-arg.nll.stderr
src/test/ui/liveness/liveness-move-in-loop.nll.stderr
src/test/ui/liveness/liveness-move-in-while.nll.stderr
src/test/ui/liveness/liveness-use-after-move.nll.stderr
src/test/ui/liveness/liveness-use-after-send.nll.stderr
src/test/ui/moves/move-guard-same-consts.nll.stderr [new file with mode: 0644]
src/test/ui/moves/move-in-guard-1.nll.stderr [new file with mode: 0644]
src/test/ui/moves/move-in-guard-2.nll.stderr
src/test/ui/moves/move-into-dead-array-2.nll.stderr
src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr
src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr
src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr
src/test/ui/moves/moves-based-on-type-exprs.nll.stderr
src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr
src/test/ui/moves/moves-based-on-type-tuple.stderr
src/test/ui/nll/closure-access-spans.stderr
src/test/ui/nll/closure-move-spans.stderr
src/test/ui/nll/closures-in-loops.stderr
src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
src/test/ui/nll/issue-21232-partial-init-and-use.stderr
src/test/ui/nll/issue-51512.stderr
src/test/ui/nll/issue-52669.stderr
src/test/ui/no-capture-arc.nll.stderr
src/test/ui/no-reuse-move-arc.nll.stderr
src/test/ui/on-unimplemented/slice-index.stderr
src/test/ui/once-cant-call-twice-on-heap.nll.stderr [new file with mode: 0644]
src/test/ui/parenthesised-deref-suggestion.rs [deleted file]
src/test/ui/parenthesised-deref-suggestion.stderr [deleted file]
src/test/ui/parenthesized-deref-suggestion.rs [new file with mode: 0644]
src/test/ui/parenthesized-deref-suggestion.stderr [new file with mode: 0644]
src/test/ui/parser/doc-before-eof.stderr
src/test/ui/parser/doc-before-extern-rbrace.stderr
src/test/ui/parser/doc-before-mod-rbrace.stderr
src/test/ui/parser/issue-17718-const-mut.rs
src/test/ui/parser/issue-17718-const-mut.stderr
src/test/ui/parser/lex-bad-char-literals-2.rs
src/test/ui/parser/lex-bad-char-literals-2.stderr
src/test/ui/parser/lex-bad-char-literals-3.rs
src/test/ui/parser/lex-bad-char-literals-3.stderr
src/test/ui/parser/lex-bad-char-literals-4.rs
src/test/ui/parser/lex-bad-char-literals-4.stderr
src/test/ui/parser/lex-bad-char-literals-5.rs
src/test/ui/parser/lex-bad-char-literals-5.stderr
src/test/ui/parser/lex-bad-char-literals-6.rs [new file with mode: 0644]
src/test/ui/parser/lex-bad-char-literals-6.stderr [new file with mode: 0644]
src/test/ui/parser/removed-syntax-with-1.rs
src/test/ui/parser/removed-syntax-with-1.stderr
src/test/ui/parser/removed-syntax-with-2.rs
src/test/ui/parser/removed-syntax-with-2.stderr
src/test/ui/parser/struct-field-numeric-shorthand.rs
src/test/ui/parser/struct-field-numeric-shorthand.stderr
src/test/ui/parser/type-parameters-in-field-exprs.stderr
src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs [new file with mode: 0644]
src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr [new file with mode: 0644]
src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs [new file with mode: 0644]
src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr [new file with mode: 0644]
src/test/ui/privacy/private-in-public-assoc-ty.rs
src/test/ui/privacy/private-in-public-assoc-ty.stderr
src/test/ui/privacy/private-in-public-existential.rs
src/test/ui/proc-macro/span-preservation.stderr
src/test/ui/quote-with-interpolated.rs [deleted file]
src/test/ui/quote-with-interpolated.stderr [deleted file]
src/test/ui/ref-suggestion.nll.stderr
src/test/ui/return/return-from-diverging.stderr
src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr
src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs [new file with mode: 0644]
src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr [new file with mode: 0644]
src/test/ui/span/macro-ty-params.stderr
src/test/ui/str/str-as-char.fixed
src/test/ui/str/str-as-char.rs
src/test/ui/str/str-as-char.stderr
src/test/ui/str/str-idx.rs
src/test/ui/str/str-idx.stderr
src/test/ui/str/str-mut-idx.rs
src/test/ui/str/str-mut-idx.stderr
src/test/ui/suggestions/recover-invalid-float.rs [new file with mode: 0644]
src/test/ui/suggestions/recover-invalid-float.stderr [new file with mode: 0644]
src/test/ui/suggestions/suggest-methods.stderr
src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs [new file with mode: 0644]
src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr [new file with mode: 0644]
src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed [new file with mode: 0644]
src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs [new file with mode: 0644]
src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr [new file with mode: 0644]
src/test/ui/tail-typeck.stderr
src/test/ui/traits/auxiliary/trait_alias.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-cross-crate.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-cross-crate.stderr [new file with mode: 0644]
src/test/ui/traits/trait-privacy.rs
src/test/ui/try-block/try-block-bad-lifetime.stderr
src/test/ui/try-block/try-block-bad-type.stderr
src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs [new file with mode: 0644]
src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr [new file with mode: 0644]
src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs
src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr
src/test/ui/unop-move-semantics.nll.stderr
src/test/ui/unsized-locals/borrow-after-move.nll.stderr
src/test/ui/unsized-locals/double-move.nll.stderr
src/test/ui/use/use-after-move-based-on-type.nll.stderr
src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr
src/test/ui/use/use-after-move-self-based-on-type.nll.stderr
src/test/ui/use/use-after-move-self.nll.stderr
src/test/ui/walk-struct-literal-with.nll.stderr
src/test/ui/wrong-ret-type.stderr
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy
src/tools/miri
src/tools/rls
src/tools/rustc-workspace-hack/Cargo.toml

index b223c8ac5fb841ed167a8c376eb1b6d5753ac0ec..f0b1c67bd0fdd22c92f1498e14e4174772892f5d 100644 (file)
@@ -9,3 +9,7 @@ src/etc/installer/gfx/* binary
 *.woff binary
 src/vendor/** -text
 Cargo.lock -merge linguist-generated=false
+
+# Older git versions try to fix line endings on images, this prevents it.
+*.png binary
+*.ico binary
index d4593c1ad234bf8637e9dfe3f1e7f4ebef5cb67b..01216deabba31967512da2a10f0d4c0c76da2e0e 100644 (file)
@@ -42,6 +42,11 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "arc-swap"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "arena"
 version = "0.0.0"
@@ -183,6 +188,15 @@ name = "byteorder"
 version = "1.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bytes"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "bytesize"
 version = "1.0.0"
@@ -520,6 +534,18 @@ dependencies = [
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "crossbeam-channel"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "crossbeam-deque"
 version = "0.2.0"
@@ -529,6 +555,15 @@ dependencies = [
  "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "crossbeam-deque"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "crossbeam-epoch"
 version = "0.3.1"
@@ -556,6 +591,19 @@ dependencies = [
  "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "crossbeam-epoch"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "crossbeam-utils"
 version = "0.2.2"
@@ -1054,6 +1102,15 @@ dependencies = [
  "xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "iovec"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "is-match"
 version = "0.1.0"
@@ -1067,6 +1124,14 @@ dependencies = [
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "itoa"
 version = "0.4.3"
@@ -1118,21 +1183,6 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "languageserver-types"
-version = "0.51.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "lazy_static"
 version = "0.2.11"
@@ -1232,6 +1282,31 @@ dependencies = [
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "lsp-codec"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lsp-types"
+version = "0.54.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "lzma-sys"
 version = "0.1.10"
@@ -1366,6 +1441,56 @@ dependencies = [
  "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "mio"
+version = "0.6.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "mio-named-pipes"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "mio-uds"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "miow"
 version = "0.3.3"
@@ -1391,6 +1516,16 @@ dependencies = [
  "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "net2"
+version = "0.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "new_debug_unreachable"
 version = "1.0.1"
@@ -1544,6 +1679,15 @@ dependencies = [
  "parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "parking_lot"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "parking_lot_core"
 version = "0.3.0"
@@ -1555,6 +1699,18 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "parking_lot_core"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "percent-encoding"
 version = "1.0.1"
@@ -1960,20 +2116,22 @@ dependencies = [
  "cargo 0.34.0",
  "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy_lints 0.0.212",
- "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lsp-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lsp-types 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-analysis 0.16.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1990,6 +2148,9 @@ dependencies = [
  "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2860,11 +3021,25 @@ name = "shlex"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "signal-hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "siphasher"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "slab"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "smallvec"
 version = "0.6.7"
@@ -3154,6 +3329,194 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "tokio"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-codec"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-current-thread"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-executor"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-fs"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-io"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-process"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-reactor"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-signal"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-tcp"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-threadpool"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-timer"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-udp"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-uds"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "toml"
 version = "0.4.10"
@@ -3365,6 +3728,15 @@ dependencies = [
  "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "xattr"
 version = "0.2.2"
@@ -3391,6 +3763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
 "checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+"checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
 "checksum assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98589b0e465a6c510d95fceebd365bb79bedece7f6e18a480897f2015f85ec51"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
@@ -3404,6 +3777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
 "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f"
 "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
+"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
 "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010"
 "checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2"
 "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
@@ -3424,9 +3798,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
 "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
 "checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827"
+"checksum crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2a9ea8f77c7f9efd317a8a5645f515d903a2d86ee14d2337a5facd1bd52c12"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
+"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416"
+"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
 "checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72"
@@ -3480,15 +3857,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec"
 "checksum ignore 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36ecfc5ad80f0b1226df948c562e2cddd446096be3f644c95106400eae8a5e01"
 "checksum im-rc 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4591152fd573cf453a890b5f9fdc5c328a751a0785539316739d5f85e5c468c"
+"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
 "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
+"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
 "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
 "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae"
 "checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace"
 "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be"
 "checksum jsonrpc-core 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e9cbeda300803d381390fb65e8158437728c39e6987ed23bee82728b73511a7"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68de833188ada4e175d04a028f03f244f6370eedbcc75a05604d47d925933f69"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
 "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
 "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
@@ -3500,6 +3878,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
 "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
+"checksum lsp-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b29e3d1632fef13c1286b0b2f8545a7d894ae565a7fac013b90a17ee5bfbc91"
+"checksum lsp-types 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a252cc2be87d9329dd91c505a951996b3263582ba304870960faaae77b642183"
 "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510"
@@ -3514,7 +3894,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
 "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
 "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
+"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
+"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
+"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
+"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
+"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
 "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d"
@@ -3532,7 +3917,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc"
 "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
+"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
 "checksum parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06a2b6aae052309c2fd2161ef58f5067bc17bb758377a0de9d4b279d603fdd8a"
+"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
 "checksum pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4"
@@ -3613,7 +4000,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
 "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
+"checksum signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
+"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
 "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
 "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
 "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
@@ -3636,6 +4025,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
+"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5"
+"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f"
+"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6"
+"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0"
+"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d"
+"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f"
+"checksum tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88e1281e412013f1ff5787def044a9577a0bed059f451e835f1643201f8b777d"
+"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f"
+"checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296"
+"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119"
+"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa"
+"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8"
+"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92"
+"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445"
 "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
 "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8"
 "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
@@ -3665,6 +4068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
+"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
 "checksum xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "df8bf41d3030c3577c9458fd6640a05afbf43b150d0b531b16bd77d3f794f27a"
 "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
index f043b8bfefca7aa639454ecb610254ef31c4cb7c..d70ad54b1c812ee6ef9b293cbfa9f434f4fb882b 100644 (file)
@@ -5,12 +5,6 @@ environment:
   # server goes down presumably. See #43333 for more info
   CARGO_HTTP_CHECK_REVOKE: false
 
-  # Recommended by AppVeyor this moves our builds to GCE which incurs a 3-4
-  # minute startup overhead, but that's paltry compared to our overall build
-  # times so we're will to eat the cost. This is intended to give us better
-  # performance I believe!
-  appveyor_build_worker_cloud: gce
-
   matrix:
   # 32/64 bit MSVC tests
   - MSYS_BITS: 64
index 23943d34b7ca8fc596737ddfbfae45da9d0987a8..24293fc864c5f9a90db9cbf5d44fbb056ef01f32 100644 (file)
 # with clang-cl, so this is special in that it only compiles LLVM with clang-cl
 #clang-cl = '/path/to/clang-cl.exe'
 
+# Pass extra compiler and linker flags to the LLVM CMake build.
+#cflags = "-fextra-flag"
+#cxxflags = "-fextra-flag"
+#ldflags = "-Wl,extra-flag"
+
 # Use libc++ when building LLVM instead of libstdc++. This is the default on
 # platforms already use libc++ as the default C++ library, but this option
 # allows you to use libc++ even on platforms when it's not. You need to ensure
index 65228915866eafc47bada4483d39cf129cd4ed32..14e773286bc6a21ccf06c6d281f641f787675630 100644 (file)
@@ -8,7 +8,6 @@ For more information on how various parts of the compiler work, see the [rustc g
 There is also useful content in the following READMEs, which are gradually being moved over to the guide:
 - https://github.com/rust-lang/rust/tree/master/src/librustc/ty/query
 - https://github.com/rust-lang/rust/tree/master/src/librustc/dep_graph
-- https://github.com/rust-lang/rust/blob/master/src/librustc/infer/region_constraints
 - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked
 - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/lexical_region_resolve
 
index f3dbae6909a4d0d8add289e5eba224b6b7a73640..e8c1594bda343fba4449f11b99665ae4e913442a 100644 (file)
@@ -230,6 +230,9 @@ def default_build_triple():
         err = "unknown OS type: {}".format(ostype)
         sys.exit(err)
 
+    if cputype == 'powerpc' and ostype == 'unknown-freebsd':
+        cputype = subprocess.check_output(
+              ['uname', '-p']).strip().decode(default_encoding)
     cputype_mapper = {
         'BePC': 'i686',
         'aarch64': 'aarch64',
index 9c58f5b179fd8b2afdadd48d4e4c31137b8157e1..a69ba207495ae5cb13e4a85734206b274311b2e1 100644 (file)
@@ -378,14 +378,11 @@ macro_rules! describe {
                 test::Debuginfo,
                 test::UiFullDeps,
                 test::RunPassFullDeps,
-                test::RunFailFullDeps,
                 test::Rustdoc,
                 test::Pretty,
                 test::RunPassPretty,
                 test::RunFailPretty,
                 test::RunPassValgrindPretty,
-                test::RunPassFullDepsPretty,
-                test::RunFailFullDepsPretty,
                 test::Crate,
                 test::CrateLibrustc,
                 test::CrateRustdoc,
@@ -660,6 +657,15 @@ pub fn rustc(&self, compiler: Compiler) -> PathBuf {
         }
     }
 
+    /// Get the paths to all of the compiler's codegen backends.
+    fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
+        fs::read_dir(self.sysroot_codegen_backends(compiler))
+            .into_iter()
+            .flatten()
+            .filter_map(Result::ok)
+            .map(|entry| entry.path())
+    }
+
     pub fn rustdoc(&self, host: Interned<String>) -> PathBuf {
         self.ensure(tool::Rustdoc { host })
     }
@@ -750,6 +756,9 @@ pub fn cargo(
             match mode {
                 Mode::Std => {
                     self.clear_if_dirty(&my_out, &self.rustc(compiler));
+                    for backend in self.codegen_backends(compiler) {
+                        self.clear_if_dirty(&my_out, &backend);
+                    }
                 },
                 Mode::Test => {
                     self.clear_if_dirty(&my_out, &libstd_stamp);
@@ -982,6 +991,9 @@ pub fn cargo(
 
         if self.config.incremental {
             cargo.env("CARGO_INCREMENTAL", "1");
+        } else {
+            // Don't rely on any default setting for incr. comp. in Cargo
+            cargo.env("CARGO_INCREMENTAL", "0");
         }
 
         if let Some(ref on_fail) = self.config.on_fail {
index 9421817ae6d8e644583263bb49bda30bb240fa15..a2989f0cffa6e712210fcb9b50a098b4c0580429 100644 (file)
@@ -82,6 +82,9 @@ pub struct Config {
     pub lldb_enabled: bool,
     pub llvm_tools_enabled: bool,
 
+    pub llvm_cflags: Option<String>,
+    pub llvm_cxxflags: Option<String>,
+    pub llvm_ldflags: Option<String>,
     pub llvm_use_libcxx: bool,
 
     // rust codegen options
@@ -254,6 +257,9 @@ struct Llvm {
     link_shared: Option<bool>,
     version_suffix: Option<String>,
     clang_cl: Option<String>,
+    cflags: Option<String>,
+    cxxflags: Option<String>,
+    ldflags: Option<String>,
     use_libcxx: Option<bool>,
 }
 
@@ -516,6 +522,10 @@ pub fn parse(args: &[String]) -> Config {
             config.llvm_link_jobs = llvm.link_jobs;
             config.llvm_version_suffix = llvm.version_suffix.clone();
             config.llvm_clang_cl = llvm.clang_cl.clone();
+
+            config.llvm_cflags = llvm.cflags.clone();
+            config.llvm_cxxflags = llvm.cxxflags.clone();
+            config.llvm_ldflags = llvm.ldflags.clone();
             set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
         }
 
index b0c3c9702498dcbb20dee72d2fc23d6900c73197..7b70236dfe8e6aafdd7c884d7526007271161ebd 100755 (executable)
@@ -64,6 +64,10 @@ o("lldb", "rust.lldb", "build lldb")
 o("missing-tools", "dist.missing-tools", "allow failures when building tools")
 o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++")
 
+o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
+o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
+o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags")
+
 # Optimization and debugging options. These may be overridden by the release
 # channel, etc.
 o("optimize", "rust.optimize", "build optimized rust code")
index df34dfe4544ae4e550b5c8981a2006e1c0688944..71662e8b9414910f507f2ade13ae60e23e4e65dc 100644 (file)
@@ -602,6 +602,8 @@ fn run(self, builder: &Builder) {
             // gdb debugger scripts
             builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
                     0o755);
+            builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"),
+                    0o755);
 
             cp_debugger_script("gdb_load_rust_pretty_printers.py");
             cp_debugger_script("gdb_rust_pretty_printing.py");
index 8ff1456f0f47c262871556f9056ca82154a694da..1c27cf3909b1af806184f743e9343cde12656b11 100644 (file)
@@ -53,7 +53,6 @@ check-aux:
                src/test/run-fail/pretty \
                src/test/run-pass-valgrind/pretty \
                src/test/run-pass-fulldeps/pretty \
-               src/test/run-fail-fulldeps/pretty \
                $(AUX_ARGS) \
                $(BOOTSTRAP_ARGS)
 check-bootstrap:
index cb9c86df55080d560f93814e2e777a8acec3770c..f5bacd63e6803a5eda30d9893282ad84154a17cc 100644 (file)
@@ -358,7 +358,11 @@ fn configure_cmake(builder: &Builder,
     }
 
     cfg.build_arg("-j").build_arg(builder.jobs().to_string());
-    cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" "));
+    let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" ");
+    if let Some(ref s) = builder.config.llvm_cxxflags {
+        cflags.push_str(&format!(" {}", s));
+    }
+    cfg.define("CMAKE_C_FLAGS", cflags);
     let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
     if builder.config.llvm_static_stdcpp &&
         !target.contains("windows") &&
@@ -366,6 +370,9 @@ fn configure_cmake(builder: &Builder,
     {
         cxxflags.push_str(" -static-libstdc++");
     }
+    if let Some(ref s) = builder.config.llvm_cxxflags {
+        cxxflags.push_str(&format!(" {}", s));
+    }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
     if let Some(ar) = builder.ar(target) {
         if ar.is_absolute() {
@@ -383,6 +390,12 @@ fn configure_cmake(builder: &Builder,
         }
     }
 
+    if let Some(ref s) = builder.config.llvm_ldflags {
+        cfg.define("CMAKE_SHARED_LINKER_FLAGS", s);
+        cfg.define("CMAKE_MODULE_LINKER_FLAGS", s);
+        cfg.define("CMAKE_EXE_LINKER_FLAGS", s);
+    }
+
     if env::var_os("SCCACHE_ERROR_LOG").is_some() {
         cfg.env("RUST_LOG", "sccache=warn");
     }
index 2edc78ebaa94f67d458caf0e6ea9b2e122da0f58..216649808e2a4a8fa39ce1b634312e9c1b1e6d0d 100644 (file)
@@ -848,12 +848,6 @@ fn run(self, builder: &Builder) {
     suite: "run-pass-fulldeps"
 });
 
-host_test!(RunFailFullDeps {
-    path: "src/test/run-fail-fulldeps",
-    mode: "run-fail",
-    suite: "run-fail-fulldeps"
-});
-
 host_test!(Rustdoc {
     path: "src/test/rustdoc",
     mode: "rustdoc",
@@ -888,20 +882,6 @@ fn run(self, builder: &Builder) {
     default: false,
     host: true
 });
-test!(RunPassFullDepsPretty {
-    path: "src/test/run-pass-fulldeps/pretty",
-    mode: "pretty",
-    suite: "run-pass-fulldeps",
-    default: false,
-    host: true
-});
-test!(RunFailFullDepsPretty {
-    path: "src/test/run-fail-fulldeps/pretty",
-    mode: "pretty",
-    suite: "run-fail-fulldeps",
-    default: false,
-    host: true
-});
 
 default_test!(RunMake {
     path: "src/test/run-make",
index 29222ff60f2a0aa1ac2537ac3f84d339f5c2da15..c39be14941c90f0f6952f738db0e4786ca0e4507 100755 (executable)
@@ -6,7 +6,7 @@ set -ex
 apt-get update
 apt-get install -y --no-install-recommends software-properties-common apt-transport-https
 
-apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F
+apt-key adv --batch --yes --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys AA12E97F0881517F
 add-apt-repository -y 'deb https://static.redox-os.org/toolchain/apt /'
 
 apt-get update
index 906255533ad29355dfc44cb6fb624dbee123a546..952c1ba2ccb76b21ac52e3296b579398d04e8d73 100644 (file)
@@ -32,7 +32,7 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
 COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
 # We pass the commit id of the port of LLVM's libunwind to the build script.
 # Any update to the commit id here, should cause the container image to be re-built from this point on.
-RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "bbe23902411be88d7388f381becefadd6e3ef819"
+RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "13fad13f8ea83a8da58d04a5faa45943151b3398"
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
index e06c57fbab90c946a1e6e2c1feaa5924e434e1f0..179f63fc830a67bd6afc778010a875bb2dac318a 100644 (file)
@@ -20,7 +20,7 @@ download_sysimage() {
     # The output from sdkmanager is so noisy that it will occupy all of the 4 MB
     # log extremely quickly. Thus we must silence all output.
     yes | sdkmanager --licenses > /dev/null
-    sdkmanager platform-tools emulator \
+    yes | sdkmanager platform-tools emulator \
         "platforms;android-$api" \
         "system-images;android-$api;default;$abi" > /dev/null
 }
index 03ea392c863073cd53633ebd6400b051ebeedcc9..cab350381d2bd3029d422b71b9ea4d8e320b83c4 100644 (file)
@@ -52,6 +52,7 @@ that implements Roman numeral integer literals.
 #![feature(plugin_registrar, rustc_private)]
 
 extern crate syntax;
+extern crate syntax_pos;
 extern crate rustc;
 extern crate rustc_plugin;
 
@@ -59,7 +60,7 @@ use syntax::parse::token;
 use syntax::tokenstream::TokenTree;
 use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
 use syntax::ext::build::AstBuilder;  // A trait for expr_usize.
-use syntax::ext::quote::rt::Span;
+use syntax_pos::Span;
 use rustc_plugin::Registry;
 
 fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
diff --git a/src/doc/unstable-book/src/library-features/is-sorted.md b/src/doc/unstable-book/src/library-features/is-sorted.md
new file mode 100644 (file)
index 0000000..e3b7dc3
--- /dev/null
@@ -0,0 +1,11 @@
+# `is_sorted`
+
+The tracking issue for this feature is: [#53485]
+
+[#53485]: https://github.com/rust-lang/rust/issues/53485
+
+------------------------
+
+Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
+add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
+`Iterator`.
index 08ae289d60374a51e42db4a7d42be5ee2fbbd97e..b9413563fd9ff41f7a57c8821aa8df145ca2ea5c 100755 (executable)
@@ -16,7 +16,7 @@ rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to
 # This fix went in 8.1, so check for that.
 # See https://github.com/rust-lang/rust/issues/56730
 gdb_81 = False
-_match = re.match('([0-9]+)\\.([0-9]+)', gdb.VERSION)
+_match = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
 if _match:
     if int(_match.group(1)) > 8 or (int(_match.group(1)) == 8 and int(_match.group(2)) >= 1):
         gdb_81 = True
index 6a863ff369a878b7013abf4a948568c1d3668863..2afd9e0c07237bfc0739d8ba1ff9ea497475757c 100644 (file)
@@ -81,12 +81,10 @@ pub trait Any: 'static {
     /// # Examples
     ///
     /// ```
-    /// #![feature(get_type_id)]
-    ///
     /// use std::any::{Any, TypeId};
     ///
     /// fn is_string(s: &dyn Any) -> bool {
-    ///     TypeId::of::<String>() == s.get_type_id()
+    ///     TypeId::of::<String>() == s.type_id()
     /// }
     ///
     /// fn main() {
@@ -94,15 +92,13 @@ pub trait Any: 'static {
     ///     assert_eq!(is_string(&"cookie monster".to_string()), true);
     /// }
     /// ```
-    #[unstable(feature = "get_type_id",
-               reason = "this method will likely be replaced by an associated static",
-               issue = "27745")]
-    fn get_type_id(&self) -> TypeId;
+    #[stable(feature = "get_type_id", since = "1.34.0")]
+    fn type_id(&self) -> TypeId;
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: 'static + ?Sized > Any for T {
-    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
+    fn type_id(&self) -> TypeId { TypeId::of::<T>() }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -161,10 +157,10 @@ pub fn is<T: Any>(&self) -> bool {
         let t = TypeId::of::<T>();
 
         // Get TypeId of the type in the trait object
-        let boxed = self.get_type_id();
+        let concrete = self.type_id();
 
         // Compare both TypeIds on equality
-        t == boxed
+        t == concrete
     }
 
     /// Returns some reference to the boxed value if it is of type `T`, or
diff --git a/src/libcore/benches/fmt.rs b/src/libcore/benches/fmt.rs
new file mode 100644 (file)
index 0000000..92f10c7
--- /dev/null
@@ -0,0 +1,110 @@
+use std::io::{self, Write as IoWrite};
+use std::fmt::{self, Write as FmtWrite};
+use test::Bencher;
+
+#[bench]
+fn write_vec_value(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        for _ in 0..1000 {
+            mem.write_all("abc".as_bytes()).unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_ref(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            wr.write_all("abc".as_bytes()).unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_macro1(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            write!(wr, "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_macro2(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            write!(wr, "{}", "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_macro_debug(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            write!(wr, "{:?}", "☃").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_value(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        for _ in 0..1000 {
+            mem.write_str("abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_ref(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        let wr = &mut mem as &mut dyn fmt::Write;
+        for _ in 0..1000 {
+            wr.write_str("abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_macro1(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        for _ in 0..1000 {
+            write!(mem, "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_macro2(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        let wr = &mut mem as &mut dyn fmt::Write;
+        for _ in 0..1000 {
+            write!(wr, "{}", "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_macro_debug(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        let wr = &mut mem as &mut dyn fmt::Write;
+        for _ in 0..1000 {
+            write!(wr, "{:?}", "☃").unwrap();
+        }
+    });
+}
index 5b4971c81dd92a043bb1a62bf4bebfc383b764bf..48572af611a5b79a2a8dcdf660289c0c304a28e5 100644 (file)
@@ -11,3 +11,4 @@
 mod num;
 mod ops;
 mod slice;
+mod fmt;
index 08b5ac06f72dece66157a3df2c7bd562a6b6b9a6..203be541e492f1c3d381a94e4ef445b3c45568d3 100644 (file)
@@ -463,11 +463,11 @@ fn try_into(self) -> Result<U, U::Error> {
 // Infallible conversions are semantically equivalent to fallible conversions
 // with an uninhabited error type.
 #[unstable(feature = "try_from", issue = "33417")]
-impl<T, U> TryFrom<U> for T where T: From<U> {
+impl<T, U> TryFrom<U> for T where U: Into<T> {
     type Error = !;
 
     fn try_from(value: U) -> Result<Self, Self::Error> {
-        Ok(T::from(value))
+        Ok(U::into(value))
     }
 }
 
index 214b5d3a84f24c4bb3f88af4cb8063eea18545a0..935579f4943b60f12b5e79b795edb0301ecd54f4 100644 (file)
@@ -211,9 +211,18 @@ fn write_fmt(&mut self, args: Arguments) -> Result {
     }
 }
 
-/// A struct to represent both where to emit formatting strings to and how they
-/// should be formatted. A mutable version of this is passed to all formatting
-/// traits.
+/// Configuration for formatting.
+///
+/// A `Formatter` represents various options related to formatting. Users do not
+/// construct `Formatter`s directly; a mutable reference to one is passed to
+/// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`].
+///
+/// To interact with a `Formatter`, you'll call various methods to change the
+/// various options related to formatting. For examples, please see the
+/// documentation of the methods defined on `Formatter` below.
+///
+/// [`Debug`]: trait.Debug.html
+/// [`Display`]: trait.Display.html
 #[allow(missing_debug_implementations)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Formatter<'a> {
@@ -997,28 +1006,30 @@ pub fn write(output: &mut dyn Write, args: Arguments) -> Result {
         curarg: args.args.iter(),
     };
 
-    let mut pieces = args.pieces.iter();
+    let mut idx = 0;
 
     match args.fmt {
         None => {
             // We can use default formatting parameters for all arguments.
-            for (arg, piece) in args.args.iter().zip(pieces.by_ref()) {
+            for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {
                 formatter.buf.write_str(*piece)?;
                 (arg.formatter)(arg.value, &mut formatter)?;
+                idx += 1;
             }
         }
         Some(fmt) => {
             // Every spec has a corresponding argument that is preceded by
             // a string piece.
-            for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
+            for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
                 formatter.buf.write_str(*piece)?;
                 formatter.run(arg)?;
+                idx += 1;
             }
         }
     }
 
     // There can be only one trailing string piece left.
-    if let Some(piece) = pieces.next() {
+    if let Some(piece) = args.pieces.get(idx) {
         formatter.buf.write_str(*piece)?;
     }
 
index 0ad29afbadeacff0589750ffcea2914cadbe6828..ac21586c0b8a91f40a8914c2b14fb0d282386bf6 100644 (file)
@@ -2605,6 +2605,95 @@ fn ge<I>(mut self, other: I) -> bool where
             }
         }
     }
+
+    /// Checks if the elements of this iterator are sorted.
+    ///
+    /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+    /// iterator yields exactly zero or one element, `true` is returned.
+    ///
+    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+    /// implies that this function returns `false` if any two consecutive items are not
+    /// comparable.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!([1, 2, 2, 9].iter().is_sorted());
+    /// assert!(![1, 3, 2, 4].iter().is_sorted());
+    /// assert!([0].iter().is_sorted());
+    /// assert!(std::iter::empty::<i32>().is_sorted());
+    /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    fn is_sorted(self) -> bool
+    where
+        Self: Sized,
+        Self::Item: PartialOrd,
+    {
+        self.is_sorted_by(|a, b| a.partial_cmp(b))
+    }
+
+    /// Checks if the elements of this iterator are sorted using the given comparator function.
+    ///
+    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+    /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+    /// [`is_sorted`]; see its documentation for more information.
+    ///
+    /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    fn is_sorted_by<F>(mut self, mut compare: F) -> bool
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>
+    {
+        let mut last = match self.next() {
+            Some(e) => e,
+            None => return true,
+        };
+
+        while let Some(curr) = self.next() {
+            if compare(&last, &curr)
+                .map(|o| o == Ordering::Greater)
+                .unwrap_or(true)
+            {
+                return false;
+            }
+            last = curr;
+        }
+
+        true
+    }
+
+    /// Checks if the elements of this iterator are sorted using the given key extraction
+    /// function.
+    ///
+    /// Instead of comparing the iterator's elements directly, this function compares the keys of
+    /// the elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see
+    /// its documentation for more information.
+    ///
+    /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
+    /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    fn is_sorted_by_key<F, K>(self, mut f: F) -> bool
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item) -> K,
+        K: PartialOrd
+    {
+        self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+    }
 }
 
 /// Select an element from an iterator based on the given "projection"
index 33c0da8a540491953bd7d037853436a832baaab7..df32cfa337313ab2eb2e1e796451bd070d24c8bf 100644 (file)
@@ -79,6 +79,7 @@
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
+#![feature(is_sorted)]
 #![feature(iter_once_with)]
 #![feature(lang_items)]
 #![feature(link_llvm_intrinsics)]
index 58b196a6eac3d18f97bfe4383935edcc8453f7b6..14a912872be35bfefc46e8d3e398d73f7d1a864c 100644 (file)
@@ -112,11 +112,35 @@ impl FromStr for $t {
             /// * '2.5E10', or equivalently, '2.5e10'
             /// * '2.5E-10'
             /// * '5.'
-            /// * '.5', or, equivalently,  '0.5'
+            /// * '.5', or, equivalently, '0.5'
             /// * 'inf', '-inf', 'NaN'
             ///
             /// Leading and trailing whitespace represent an error.
             ///
+            /// # Grammar
+            ///
+            /// All strings that adhere to the following [EBNF] grammar
+            /// will result in an [`Ok`] being returned:
+            ///
+            /// ```txt
+            /// Float  ::= Sign? ( 'inf' | 'NaN' | Number )
+            /// Number ::= ( Digit+ |
+            ///              Digit+ '.' Digit* |
+            ///              Digit* '.' Digit+ ) Exp?
+            /// Exp    ::= [eE] Sign? Digit+
+            /// Sign   ::= [+-]
+            /// Digit  ::= [0-9]
+            /// ```
+            ///
+            /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation
+            ///
+            /// # Known bugs
+            ///
+            /// In some situations, some strings that should create a valid float
+            /// instead return an error. See [issue #31407] for details.
+            ///
+            /// [issue #31407]: https://github.com/rust-lang/rust/issues/31407
+            ///
             /// # Arguments
             ///
             /// * src - A string
index 6827364c0f805d34f153596b93d8cefe9cefe5f3..423b800d5852f98d3f75826d80c145712d7655e9 100644 (file)
@@ -10,9 +10,9 @@
 use str::FromStr;
 
 macro_rules! impl_nonzero_fmt {
-    ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
+    ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
         $(
-            #[stable(feature = "nonzero", since = "1.28.0")]
+            #[$stability]
             impl fmt::$Trait for $Ty {
                 #[inline]
                 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -31,7 +31,7 @@ macro_rules! doc_comment {
 }
 
 macro_rules! nonzero_integers {
-    ( $( $Ty: ident($Int: ty); )+ ) => {
+    ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
         $(
             doc_comment! {
                 concat!("An integer that is known not to equal zero.
@@ -41,10 +41,10 @@ macro_rules! nonzero_integers {
 
 ```rust
 use std::mem::size_of;
-assert_eq!(size_of::<Option<std::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
+assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
 ">());
 ```"),
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
                 #[repr(transparent)]
                 #[rustc_layout_scalar_valid_range_start(1)]
@@ -57,14 +57,14 @@ impl $Ty {
                 /// # Safety
                 ///
                 /// The value must not be zero.
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[inline]
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
                     $Ty(n)
                 }
 
                 /// Create a non-zero if the given value is not zero.
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[inline]
                 pub fn new(n: $Int) -> Option<Self> {
                     if n != 0 {
@@ -75,7 +75,7 @@ pub fn new(n: $Int) -> Option<Self> {
                 }
 
                 /// Returns the value as a primitive type.
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[inline]
                 pub const fn get(self) -> $Int {
                     self.0
@@ -91,19 +91,25 @@ fn from(nonzero: $Ty) -> Self {
             }
 
             impl_nonzero_fmt! {
-                (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
+                #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
             }
         )+
     }
 }
 
 nonzero_integers! {
-    NonZeroU8(u8);
-    NonZeroU16(u16);
-    NonZeroU32(u32);
-    NonZeroU64(u64);
-    NonZeroU128(u128);
-    NonZeroUsize(usize);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
 }
 
 /// Provides intentionally-wrapped arithmetic on `T`.
@@ -841,13 +847,12 @@ pub fn checked_abs(self) -> Option<Self> {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));
 assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);",
 $EndFeature, "
 ```"),
 
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
                 let mut base = self;
@@ -960,7 +965,6 @@ pub fn saturating_mul(self, rhs: Self) -> Self {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "use std::", stringify!($SelfT), ";
 
 assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);
@@ -968,7 +972,7 @@ pub fn saturating_mul(self, rhs: Self) -> Self {
 assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn saturating_pow(self, exp: u32) -> Self {
                 match self.checked_pow(exp) {
@@ -1291,13 +1295,12 @@ pub fn wrapping_abs(self) -> Self {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);
 assert_eq!(3i8.wrapping_pow(5), -13);
 assert_eq!(3i8.wrapping_pow(6), -39);",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn wrapping_pow(self, mut exp: u32) -> Self {
                 let mut base = self;
@@ -1663,12 +1666,11 @@ pub fn overflowing_abs(self) -> (Self, bool) {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));
 assert_eq!(3i8.overflowing_pow(5), (-13, true));",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
                 let mut base = self;
@@ -2783,11 +2785,10 @@ pub fn checked_shr(self, rhs: u32) -> Option<Self> {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));
 assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
                 let mut base = self;
@@ -2887,14 +2888,13 @@ pub fn saturating_mul(self, rhs: Self) -> Self {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "use std::", stringify!($SelfT), ";
 
 assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);
 assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn saturating_pow(self, exp: u32) -> Self {
                 match self.checked_pow(exp) {
@@ -3172,11 +3172,10 @@ pub const fn wrapping_shr(self, rhs: u32) -> Self {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);
 assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn wrapping_pow(self, mut exp: u32) -> Self {
                 let mut base = self;
@@ -3491,11 +3490,10 @@ pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
 Basic usage:
 
 ```
-#![feature(no_panic_pow)]
 ", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));
 assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
 ```"),
-            #[unstable(feature = "no_panic_pow", issue = "48320")]
+            #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[inline]
             pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
                 let mut base = self;
index 6cfa36741d0ca61363d3bdfba0df1233a94a1153..d4ed86142768d418bf83ea28c5de10be0527f09d 100644 (file)
 /// ```
 #[lang = "index"]
 #[rustc_on_unimplemented(
-    on(
-        _Self="&str",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
-    on(
-        _Self="str",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
-    on(
-        _Self="std::string::String",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
     message="the type `{Self}` cannot be indexed by `{Idx}`",
     label="`{Self}` cannot be indexed by `{Idx}`",
 )]
index 7fdc2acb8cc92e22acb136ae39769233889cbea4..9f9515e6d9b7c4e372eee8beb937aac3dd89fc6b 100644 (file)
@@ -1783,7 +1783,7 @@ pub fn partition_dedup_by_key<K, F>(&mut self, mut key: F) -> (&mut [T], &mut [T
     /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
     /// a[1..5].rotate_left(1);
     /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
-   /// ```
+    /// ```
     #[stable(feature = "slice_rotate", since = "1.26.0")]
     pub fn rotate_left(&mut self, mid: usize) {
         assert!(mid <= self.len());
@@ -2250,6 +2250,77 @@ pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
              from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len))
         }
     }
+
+    /// Checks if the elements of this slice are sorted.
+    ///
+    /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+    /// slice yields exactly zero or one element, `true` is returned.
+    ///
+    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+    /// implies that this function returns `false` if any two consecutive items are not
+    /// comparable.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    /// let empty: [i32; 0] = [];
+    ///
+    /// assert!([1, 2, 2, 9].is_sorted());
+    /// assert!(![1, 3, 2, 4].is_sorted());
+    /// assert!([0].is_sorted());
+    /// assert!(empty.is_sorted());
+    /// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted(&self) -> bool
+    where
+        T: PartialOrd,
+    {
+        self.is_sorted_by(|a, b| a.partial_cmp(b))
+    }
+
+    /// Checks if the elements of this slice are sorted using the given comparator function.
+    ///
+    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+    /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+    /// [`is_sorted`]; see its documentation for more information.
+    ///
+    /// [`is_sorted`]: #method.is_sorted
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
+    where
+        F: FnMut(&T, &T) -> Option<Ordering>
+    {
+        self.iter().is_sorted_by(|a, b| compare(*a, *b))
+    }
+
+    /// Checks if the elements of this slice are sorted using the given key extraction function.
+    ///
+    /// Instead of comparing the slice's elements directly, this function compares the keys of the
+    /// elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see its
+    /// documentation for more information.
+    ///
+    /// [`is_sorted`]: #method.is_sorted
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+    /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted_by_key<F, K>(&self, mut f: F) -> bool
+    where
+        F: FnMut(&T) -> K,
+        K: PartialOrd
+    {
+        self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+    }
 }
 
 #[lang = "slice_u8"]
@@ -2312,7 +2383,6 @@ pub fn make_ascii_lowercase(&mut self) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::Index<I> for [T]
     where I: SliceIndex<[T]>
 {
@@ -2325,7 +2395,6 @@ fn index(&self, index: I) -> &I::Output {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::IndexMut<I> for [T]
     where I: SliceIndex<[T]>
 {
@@ -2376,7 +2445,19 @@ impl Sealed for ops::RangeToInclusive<usize> {}
 
 /// A helper trait used for indexing operations.
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
+#[rustc_on_unimplemented(
+    on(
+        T = "str",
+        label = "string indices are ranges of `usize`",
+    ),
+    on(
+        all(any(T = "str", T = "&str", T = "std::string::String"), _Self="{integer}"),
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    message = "the type `{T}` cannot be indexed by `{Self}`",
+    label = "slice indices are of type `usize` or ranges of `usize`",
+)]
 pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     /// The output type returned by methods.
     #[stable(feature = "slice_get_slice", since = "1.28.0")]
@@ -2773,7 +2854,13 @@ macro_rules! len {
 
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
-    (struct $name:ident -> $ptr:ty, $elem:ty, $raw_mut:tt, $( $mut_:tt )*) => {
+    (
+        struct $name:ident -> $ptr:ty,
+        $elem:ty,
+        $raw_mut:tt,
+        {$( $mut_:tt )*},
+        {$($extra:tt)*}
+    ) => {
         impl<'a, T> $name<'a, T> {
             // Helper function for creating a slice from the iterator.
             #[inline(always)]
@@ -2950,6 +3037,8 @@ fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
                         i
                     })
             }
+
+            $($extra)*
         }
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -3087,7 +3176,17 @@ pub fn as_slice(&self) -> &'a [T] {
     }
 }
 
-iterator!{struct Iter -> *const T, &'a T, const, /* no mut */}
+iterator!{struct Iter -> *const T, &'a T, const, {/* no mut */}, {
+    fn is_sorted_by<F>(self, mut compare: F) -> bool
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
+    {
+        self.as_slice().windows(2).all(|w| {
+            compare(&&w[0], &&w[1]).map(|o| o != Ordering::Greater).unwrap_or(false)
+        })
+    }
+}}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Iter<'_, T> {
@@ -3188,7 +3287,7 @@ pub fn into_slice(self) -> &'a mut [T] {
     }
 }
 
-iterator!{struct IterMut -> *mut T, &'a mut T, mut, mut}
+iterator!{struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}}
 
 /// An internal abstraction over the splitting iterators, so that
 /// splitn, splitn_mut etc can be implemented once.
index bdde187d931cc4654264a42c21a7f2f21c4c89d5..1ee8b7735c17d19fcb85b82555dab48fcca784fe 100644 (file)
@@ -1621,190 +1621,26 @@ fn partial_cmp(&self, other: &str) -> Option<Ordering> {
         }
     }
 
-    /// Implements substring slicing with syntax `&self[begin .. end]`.
-    ///
-    /// Returns a slice of the given string from the byte range
-    /// [`begin`..`end`).
-    ///
-    /// This operation is `O(1)`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `begin` or `end` does not point to the starting
-    /// byte offset of a character (as defined by `is_char_boundary`).
-    /// Requires that `begin <= end` and `end <= len` where `len` is the
-    /// length of the string.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// assert_eq!(&s[0 .. 1], "L");
-    ///
-    /// assert_eq!(&s[1 .. 9], "öwe 老");
-    ///
-    /// // these will panic:
-    /// // byte 2 lies within `ö`:
-    /// // &s[2 ..3];
-    ///
-    /// // byte 8 lies within `老`
-    /// // &s[1 .. 8];
-    ///
-    /// // byte 100 is outside the string
-    /// // &s[3 .. 100];
-    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::Range<usize>> for str {
-        type Output = str;
-        #[inline]
-        fn index(&self, index: ops::Range<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax
-    /// `&mut self[begin .. end]`.
-    ///
-    /// Returns a mutable slice of the given string from the byte range
-    /// [`begin`..`end`).
-    ///
-    /// This operation is `O(1)`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `begin` or `end` does not point to the starting
-    /// byte offset of a character (as defined by `is_char_boundary`).
-    /// Requires that `begin <= end` and `end <= len` where `len` is the
-    /// length of the string.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::Range<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[.. end]`.
-    ///
-    /// Returns a slice of the string from the beginning to byte offset
-    /// `end`.
-    ///
-    /// Equivalent to `&self[0 .. end]`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeTo<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeTo<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[.. end]`.
-    ///
-    /// Returns a mutable slice of the string from the beginning to byte offset
-    /// `end`.
-    ///
-    /// Equivalent to `&mut self[0 .. end]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeTo<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[begin ..]`.
-    ///
-    /// Returns a slice of the string from byte offset `begin`
-    /// to the end of the string.
-    ///
-    /// Equivalent to `&self[begin .. len]`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeFrom<usize>> for str {
-        type Output = str;
+    impl<I> ops::Index<I> for str
+    where
+        I: SliceIndex<str>,
+    {
+        type Output = I::Output;
 
         #[inline]
-        fn index(&self, index: ops::RangeFrom<usize>) -> &str {
+        fn index(&self, index: I) -> &I::Output {
             index.index(self)
         }
     }
 
-    /// Implements mutable substring slicing with syntax `&mut self[begin ..]`.
-    ///
-    /// Returns a mutable slice of the string from byte offset `begin`
-    /// to the end of the string.
-    ///
-    /// Equivalent to `&mut self[begin .. len]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeFrom<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[..]`.
-    ///
-    /// Returns a slice of the whole string. This operation can
-    /// never panic.
-    ///
-    /// Equivalent to `&self[0 .. len]`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeFull> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, _index: ops::RangeFull) -> &str {
-            self
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[..]`.
-    ///
-    /// Returns a mutable slice of the whole string. This operation can
-    /// never panic.
-    ///
-    /// Equivalent to `&mut self[0 .. len]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeFull> for str {
-        #[inline]
-        fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
-            self
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::Index<ops::RangeInclusive<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::Index<ops::RangeToInclusive<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::IndexMut<ops::RangeInclusive<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::IndexMut<ops::RangeToInclusive<usize>> for str {
+    impl<I> ops::IndexMut<I> for str
+    where
+        I: SliceIndex<str>,
+    {
         #[inline]
-        fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
+        fn index_mut(&mut self, index: I) -> &mut I::Output {
             index.index_mut(self)
         }
     }
@@ -1815,6 +1651,18 @@ fn str_index_overflow_fail() -> ! {
         panic!("attempted to index str up to maximum usize");
     }
 
+    /// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`.
+    ///
+    /// Returns a slice of the whole string, i.e., returns `&self` or `&mut
+    /// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike
+    /// other indexing operations, this can never panic.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`.
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::RangeFull {
         type Output = str;
@@ -1844,6 +1692,41 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin .. end]` or `&mut
+    /// self[begin .. end]`.
+    ///
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`, `end`).
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` or `end` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), if `begin > end`, or if
+    /// `end > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert_eq!(&s[0 .. 1], "L");
+    ///
+    /// assert_eq!(&s[1 .. 9], "öwe 老");
+    ///
+    /// // these will panic:
+    /// // byte 2 lies within `ö`:
+    /// // &s[2 ..3];
+    ///
+    /// // byte 8 lies within `老`
+    /// // &s[1 .. 8];
+    ///
+    /// // byte 100 is outside the string
+    /// // &s[3 .. 100];
+    /// ```
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::Range<usize> {
         type Output = str;
@@ -1898,6 +1781,21 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
         }
     }
 
+    /// Implements substring slicing with syntax `&self[.. end]` or `&mut
+    /// self[.. end]`.
+    ///
+    /// Returns a slice of the given string from the byte range [`0`, `end`).
+    /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `end` does not point to the starting byte offset of a
+    /// character (as defined by `is_char_boundary`), or if `end > len`.
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::RangeTo<usize> {
         type Output = str;
@@ -1943,6 +1841,22 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin ..]` or `&mut
+    /// self[begin ..]`.
+    ///
+    /// Returns a slice of the given string from the byte range [`begin`,
+    /// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin ..
+    /// len]`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), or if `begin >= len`.
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::RangeFrom<usize> {
         type Output = str;
@@ -1990,6 +1904,22 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin ..= end]` or `&mut
+    /// self[begin ..= end]`.
+    ///
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`, `end`]. Equivalent to `&self [begin .. end + 1]` or `&mut
+    /// self[begin .. end + 1]`, except if `end` has the maximum value for
+    /// `usize`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), if `end` does not point
+    /// to the ending byte offset of a character (`end + 1` is either a starting
+    /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`.
     #[stable(feature = "inclusive_range", since = "1.26.0")]
     impl SliceIndex<str> for ops::RangeInclusive<usize> {
         type Output = str;
@@ -2023,8 +1953,20 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
         }
     }
 
-
-
+    /// Implements substring slicing with syntax `&self[..= end]` or `&mut
+    /// self[..= end]`.
+    ///
+    /// Returns a slice of the given string from the byte range [0, `end`].
+    /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
+    /// value for `usize`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `end` does not point to the ending byte offset of a character
+    /// (`end + 1` is either a starting byte offset as defined by
+    /// `is_char_boundary`, or equal to `len`), or if `end >= len`.
     #[stable(feature = "inclusive_range", since = "1.26.0")]
     impl SliceIndex<str> for ops::RangeToInclusive<usize> {
         type Output = str;
index 3944bc749d0296b75fbdbc5e49bcb527c24b7e63..0fa99745d9065ab75c860690203f22c00165378c 100644 (file)
@@ -2235,3 +2235,16 @@ fn g(x: usize) -> impl Iterator<Item = usize> { (0..x).rev() }
     assert_eq!((0..10).flat_map(f).flat_map(g).sum::<usize>(),
                 (0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>());
 }
+
+#[test]
+fn test_is_sorted() {
+    assert!([1, 2, 2, 9].iter().is_sorted());
+    assert!(![1, 3, 2].iter().is_sorted());
+    assert!([0].iter().is_sorted());
+    assert!(std::iter::empty::<i32>().is_sorted());
+    assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+    assert!([-2, -1, 0, 3].iter().is_sorted());
+    assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    assert!(!["c", "bb", "aaa"].iter().is_sorted());
+    assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
+}
index a9b8decfd0262beb381f0bffbf55e1b5a0c1a2da..3e8549f8ae366da46c5b1a02f1289e30636866e3 100644 (file)
@@ -10,6 +10,7 @@
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
+#![feature(is_sorted)]
 #![feature(iter_copied)]
 #![feature(iter_nth_back)]
 #![feature(iter_once_with)]
index c813bf20cb61ae5712b5326002f4b70ede260389..4532568ee0c1630179c64b008abc99278be1aac4 100644 (file)
@@ -1,4 +1,4 @@
-use core::num::NonZeroU32;
+use core::num::{NonZeroU32, NonZeroI32};
 use core::option::Option;
 use core::option::Option::{Some, None};
 use std::mem::size_of;
@@ -13,6 +13,7 @@ fn test_create_nonzero_instance() {
 #[test]
 fn test_size_nonzero_in_option() {
     assert_eq!(size_of::<NonZeroU32>(), size_of::<Option<NonZeroU32>>());
+    assert_eq!(size_of::<NonZeroI32>(), size_of::<Option<NonZeroI32>>());
 }
 
 #[test]
@@ -118,3 +119,10 @@ fn test_from_nonzero() {
     let num: u32 = nz.into();
     assert_eq!(num, 1u32);
 }
+
+#[test]
+fn test_from_signed_nonzero() {
+    let nz = NonZeroI32::new(1).unwrap();
+    let num: i32 = nz.into();
+    assert_eq!(num, 1i32);
+}
index 2c96efbda76738383b17b33c4e3df56a148ef93e..e210e83122c47537e6a09e9459bc14526e1ebbed 100644 (file)
@@ -1317,3 +1317,18 @@ fn test_copy_within_panics_src_inverted() {
     // 2 is greater than 1, so this range is invalid.
     bytes.copy_within(2..1, 0);
 }
+
+#[test]
+fn test_is_sorted() {
+    let empty: [i32; 0] = [];
+
+    assert!([1, 2, 2, 9].is_sorted());
+    assert!(![1, 3, 2].is_sorted());
+    assert!([0].is_sorted());
+    assert!(empty.is_sorted());
+    assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    assert!([-2, -1, 0, 3].is_sorted());
+    assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    assert!(!["c", "bb", "aaa"].is_sorted());
+    assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+}
index 32ae878909f30676a76a4738b20400611f19148d..da440cdd72f8065d7266a09d8feaff3959dfdb15 100644 (file)
@@ -72,6 +72,15 @@ pub enum Position<'a> {
     ArgumentNamed(&'a str),
 }
 
+impl Position<'_> {
+    pub fn index(&self) -> Option<usize> {
+        match self {
+            ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
+            _ => None,
+        }
+    }
+}
+
 /// Enum of alignments which are supported.
 #[derive(Copy, Clone, PartialEq)]
 pub enum Alignment {
index 978d20ea9478956de1ba8fca15f72e2690e37b18..6122fe6370940cd9d2d89e19e8b86daa7fee58e7 100644 (file)
@@ -99,30 +99,21 @@ fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex {
     }
 
     fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
-        let hir_id = self.tcx.hir().node_to_hir_id(stmt.node.id());
-        match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                let exit = self.decl(&decl, pred);
-                self.add_ast_node(hir_id.local_id, &[exit])
-            }
-
-            hir::StmtKind::Expr(ref expr, _) |
-            hir::StmtKind::Semi(ref expr, _) => {
-                let exit = self.expr(&expr, pred);
-                self.add_ast_node(hir_id.local_id, &[exit])
-            }
-        }
-    }
-
-    fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex) -> CFGIndex {
-        match decl.node {
-            hir::DeclKind::Local(ref local) => {
+        let hir_id = self.tcx.hir().node_to_hir_id(stmt.id);
+        let exit = match stmt.node {
+            hir::StmtKind::Local(ref local) => {
                 let init_exit = self.opt_expr(&local.init, pred);
                 self.pat(&local.pat, init_exit)
             }
-
-            hir::DeclKind::Item(_) => pred,
-        }
+            hir::StmtKind::Item(_) => {
+                pred
+            }
+            hir::StmtKind::Expr(ref expr) |
+            hir::StmtKind::Semi(ref expr) => {
+                self.expr(&expr, pred)
+            }
+        };
+        self.add_ast_node(hir_id.local_id, &[exit])
     }
 
     fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
index a9e80ddf4ba2a47d1e0f49512c19ee46ddebc2fd..63857d6c9189af63fc1306cf31f701d05d31c220 100644 (file)
@@ -1,4 +1,4 @@
-use errors::DiagnosticBuilder;
+use errors::{Diagnostic, DiagnosticBuilder};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
@@ -9,6 +9,7 @@
 use std::collections::hash_map::Entry;
 use ty::{self, TyCtxt};
 use util::common::{ProfileQueriesMsg, profq_msg};
+use parking_lot::{Mutex, Condvar};
 
 use ich::{StableHashingContext, StableHashingContextProvider, Fingerprint};
 
@@ -60,6 +61,12 @@ struct DepGraphData {
 
     colors: DepNodeColorMap,
 
+    /// A set of loaded diagnostics which has been emitted.
+    emitted_diagnostics: Mutex<FxHashSet<DepNodeIndex>>,
+
+    /// Used to wait for diagnostics to be emitted.
+    emitted_diagnostics_cond_var: Condvar,
+
     /// When we load, there may be `.o` files, cached mir, or other such
     /// things available to us. If we find that they are not dirty, we
     /// load the path to the file storing those work-products here into
@@ -83,6 +90,8 @@ pub fn new(prev_graph: PreviousDepGraph,
                 previous_work_products: prev_work_products,
                 dep_node_debug: Default::default(),
                 current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
+                emitted_diagnostics: Default::default(),
+                emitted_diagnostics_cond_var: Condvar::new(),
                 previous: prev_graph,
                 colors: DepNodeColorMap::new(prev_graph_node_count),
                 loaded_from_cache: Default::default(),
@@ -718,28 +727,18 @@ fn try_mark_previous_green<'tcx>(
         };
 
         // ... emitting any stored diagnostic ...
-        if did_allocation {
-            // Only the thread which did the allocation emits the error messages
-
-            // FIXME: Ensure that these are printed before returning for all threads.
-            // Currently threads where did_allocation = false can continue on
-            // and emit other diagnostics before these diagnostics are emitted.
-            // Such diagnostics should be emitted after these.
-            // See https://github.com/rust-lang/rust/issues/48685
-            let diagnostics = tcx.queries.on_disk_cache
-                                 .load_diagnostics(tcx, prev_dep_node_index);
 
-            if diagnostics.len() > 0 {
-                let handle = tcx.sess.diagnostic();
+        let diagnostics = tcx.queries.on_disk_cache
+                                .load_diagnostics(tcx, prev_dep_node_index);
 
-                // Promote the previous diagnostics to the current session.
-                tcx.queries.on_disk_cache
-                   .store_diagnostics(dep_node_index, diagnostics.clone().into());
-
-                for diagnostic in diagnostics {
-                    DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
-                }
-            }
+        if unlikely!(diagnostics.len() > 0) {
+            self.emit_diagnostics(
+                tcx,
+                data,
+                dep_node_index,
+                did_allocation,
+                diagnostics
+            );
         }
 
         // ... and finally storing a "Green" entry in the color map.
@@ -755,6 +754,49 @@ fn try_mark_previous_green<'tcx>(
         Some(dep_node_index)
     }
 
+    /// Atomically emits some loaded diagnotics assuming that this only gets called with
+    /// did_allocation set to true on one thread
+    #[cold]
+    #[inline(never)]
+    fn emit_diagnostics<'tcx>(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, 'tcx>,
+        data: &DepGraphData,
+        dep_node_index: DepNodeIndex,
+        did_allocation: bool,
+        diagnostics: Vec<Diagnostic>,
+    ) {
+        if did_allocation || !cfg!(parallel_queries) {
+            // Only the thread which did the allocation emits the error messages
+            let handle = tcx.sess.diagnostic();
+
+            // Promote the previous diagnostics to the current session.
+            tcx.queries.on_disk_cache
+                .store_diagnostics(dep_node_index, diagnostics.clone().into());
+
+            for diagnostic in diagnostics {
+                DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
+            }
+
+            #[cfg(parallel_queries)]
+            {
+                // Mark the diagnostics and emitted and wake up waiters
+                data.emitted_diagnostics.lock().insert(dep_node_index);
+                data.emitted_diagnostics_cond_var.notify_all();
+            }
+        } else {
+            // The other threads will wait for the diagnostics to be emitted
+
+            let mut emitted_diagnostics = data.emitted_diagnostics.lock();
+            loop {
+                if emitted_diagnostics.contains(&dep_node_index) {
+                    break;
+                }
+                data.emitted_diagnostics_cond_var.wait(&mut emitted_diagnostics);
+            }
+        }
+    }
+
     // Returns true if the given node has been marked as green during the
     // current compilation session. Used in various assertions
     pub fn is_green(&self, dep_node: &DepNode) -> bool {
index b4a00715c0f22b6903556d81d214ba6b0f648df0..df111b2be319f8bab3e36644215a4cbae44fb1a3 100644 (file)
@@ -283,8 +283,8 @@ fn emit_repr_error(
 
     fn check_stmt_attributes(&self, stmt: &hir::Stmt) {
         // When checking statements ignore expressions, they will be checked later
-        if let hir::StmtKind::Decl(_, _) = stmt.node {
-            for attr in stmt.node.attrs() {
+        if let hir::StmtKind::Local(ref l) = stmt.node {
+            for attr in l.attrs.iter() {
                 if attr.check_name("inline") {
                     self.check_inline(attr, &stmt.span, Target::Statement);
                 }
index 041291e80eee989d0aa804cdf94a5048187057b6..592fb7898f3e60a05f35b1a626fc3420ff5e2d44 100644 (file)
@@ -258,9 +258,6 @@ fn visit_arm(&mut self, a: &'v Arm) {
     fn visit_pat(&mut self, p: &'v Pat) {
         walk_pat(self, p)
     }
-    fn visit_decl(&mut self, d: &'v Decl) {
-        walk_decl(self, d)
-    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) {
         walk_anon_const(self, c)
     }
@@ -951,26 +948,17 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
+    visitor.visit_id(statement.id);
     match statement.node {
-        StmtKind::Decl(ref declaration, id) => {
-            visitor.visit_id(id);
-            visitor.visit_decl(declaration)
-        }
-        StmtKind::Expr(ref expression, id) |
-        StmtKind::Semi(ref expression, id) => {
-            visitor.visit_id(id);
+        StmtKind::Local(ref local) => visitor.visit_local(local),
+        StmtKind::Item(ref item) => visitor.visit_nested_item(**item),
+        StmtKind::Expr(ref expression) |
+        StmtKind::Semi(ref expression) => {
             visitor.visit_expr(expression)
         }
     }
 }
 
-pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
-    match declaration.node {
-        DeclKind::Local(ref local) => visitor.visit_local(local),
-        DeclKind::Item(item) => visitor.visit_nested_item(item),
-    }
-}
-
 pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
     visitor.visit_id(constant.id);
     visitor.visit_nested_body(constant.body);
index 8cdc493e6fda7763a64f9ee99e9148aa9d36d8d1..905a3ceed81c9d04bd957241a773c7de0102ca70 100644 (file)
@@ -31,6 +31,7 @@
 //! in the HIR, especially for multiple identifiers.
 
 use dep_graph::DepGraph;
+use errors::Applicability;
 use hir::{self, ParamName};
 use hir::HirVec;
 use hir::map::{DefKey, DefPathData, Definitions};
@@ -1806,7 +1807,7 @@ fn lower_path_segment(
         explicit_owner: Option<NodeId>,
     ) -> hir::PathSegment {
         let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
-            let msg = "parenthesized parameters may only be used with a trait";
+            let msg = "parenthesized type parameters may only be used with a `Fn` trait";
             match **generic_args {
                 GenericArgs::AngleBracketed(ref data) => {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
@@ -1823,10 +1824,25 @@ fn lower_path_segment(
                         (hir::GenericArgs::none(), true)
                     }
                     ParenthesizedGenericArgs::Err => {
-                        struct_span_err!(self.sess, data.span, E0214, "{}", msg)
-                            .span_label(data.span, "only traits may use parentheses")
-                            .emit();
-                        (hir::GenericArgs::none(), true)
+                        let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
+                        err.span_label(data.span, "only `Fn` traits may use parentheses");
+                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
+                            // Do not suggest going from `Trait()` to `Trait<>`
+                            if data.inputs.len() > 0 {
+                                err.span_suggestion_with_applicability(
+                                    data.span,
+                                    "use angle brackets instead",
+                                    format!("<{}>", &snippet[1..snippet.len() - 1]),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        };
+                        err.emit();
+                        (self.lower_angle_bracketed_parameter_data(
+                            &data.as_angle_bracketed_args(),
+                            param_mode,
+                            itctx).0,
+                         false)
                     }
                 },
             }
@@ -1915,7 +1931,7 @@ fn lower_angle_bracketed_parameter_data(
 
     fn lower_parenthesized_parameter_data(
         &mut self,
-        data: &ParenthesisedArgs,
+        data: &ParenthesizedArgs,
     ) -> (hir::GenericArgs, bool) {
         // Switch to `PassThrough` mode for anonymous lifetimes: this
         // means that we permit things like `&Ref<T>`, where `Ref` has
@@ -1925,7 +1941,7 @@ fn lower_parenthesized_parameter_data(
         self.with_anonymous_lifetime_mode(
             AnonymousLifetimeMode::PassThrough,
             |this| {
-                let &ParenthesisedArgs { ref inputs, ref output, span } = data;
+                let &ParenthesizedArgs { ref inputs, ref output, span } = data;
                 let inputs = inputs
                     .iter()
                     .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
@@ -1957,7 +1973,7 @@ fn lower_parenthesized_parameter_data(
         )
     }
 
-    fn lower_local(&mut self, l: &Local) -> (P<hir::Local>, SmallVec<[hir::ItemId; 1]>) {
+    fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) {
         let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
         let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
         if self.sess.features_untracked().impl_trait_in_bindings {
@@ -1967,7 +1983,7 @@ fn lower_parenthesized_parameter_data(
             }
         }
         let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
-        (P(hir::Local {
+        (hir::Local {
             id: node_id,
             hir_id,
             ty: l.ty
@@ -1984,7 +2000,7 @@ fn lower_parenthesized_parameter_data(
             span: l.span,
             attrs: l.attrs.clone(),
             source: hir::LocalSource::Normal,
-        }), ids)
+        }, ids)
     }
 
     fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
@@ -4331,10 +4347,11 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                         ThinVec::new(),
                     ))
                 };
-                let match_stmt = respan(
-                    head_sp,
-                    hir::StmtKind::Expr(match_expr, self.next_id().node_id)
-                );
+                let match_stmt = hir::Stmt {
+                    id: self.next_id().node_id,
+                    node: hir::StmtKind::Expr(match_expr),
+                    span: head_sp,
+                };
 
                 let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
 
@@ -4357,10 +4374,11 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
                 let body_expr = P(self.expr_block(body_block, ThinVec::new()));
-                let body_stmt = respan(
-                    body.span,
-                    hir::StmtKind::Expr(body_expr, self.next_id().node_id)
-                );
+                let body_stmt = hir::Stmt {
+                    id: self.next_id().node_id,
+                    node: hir::StmtKind::Expr(body_expr),
+                    span: body.span,
+                };
 
                 let loop_block = P(self.block_all(
                     e.span,
@@ -4533,25 +4551,15 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let (l, item_ids) = self.lower_local(l);
                 let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
                     .into_iter()
-                    .map(|item_id| Spanned {
-                        node: hir::StmtKind::Decl(
-                            P(Spanned {
-                                node: hir::DeclKind::Item(item_id),
-                                span: s.span,
-                            }),
-                            self.next_id().node_id,
-                        ),
+                    .map(|item_id| hir::Stmt {
+                        id: self.next_id().node_id,
+                        node: hir::StmtKind::Item(P(item_id)),
                         span: s.span,
                     })
                     .collect();
-                ids.push(Spanned {
-                    node: hir::StmtKind::Decl(
-                        P(Spanned {
-                            node: hir::DeclKind::Local(l),
-                            span: s.span,
-                        }),
-                        self.lower_node_id(s.id).node_id,
-                    ),
+                ids.push(hir::Stmt {
+                    id: self.lower_node_id(s.id).node_id,
+                    node: hir::StmtKind::Local(P(l)),
                     span: s.span,
                 });
                 return ids;
@@ -4561,26 +4569,23 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let mut id = Some(s.id);
                 return self.lower_item_id(it)
                     .into_iter()
-                    .map(|item_id| Spanned {
-                        node: hir::StmtKind::Decl(
-                            P(Spanned {
-                                node: hir::DeclKind::Item(item_id),
-                                span: s.span,
-                            }),
-                            id.take()
+                    .map(|item_id| hir::Stmt {
+                        id: id.take()
                               .map(|id| self.lower_node_id(id).node_id)
                               .unwrap_or_else(|| self.next_id().node_id),
-                        ),
+                        node: hir::StmtKind::Item(P(item_id)),
                         span: s.span,
                     })
                     .collect();
             }
-            StmtKind::Expr(ref e) => Spanned {
-                node: hir::StmtKind::Expr(P(self.lower_expr(e)), self.lower_node_id(s.id).node_id),
+            StmtKind::Expr(ref e) => hir::Stmt {
+                id: self.lower_node_id(s.id).node_id,
+                node: hir::StmtKind::Expr(P(self.lower_expr(e))),
                 span: s.span,
             },
-            StmtKind::Semi(ref e) => Spanned {
-                node: hir::StmtKind::Semi(P(self.lower_expr(e)), self.lower_node_id(s.id).node_id),
+            StmtKind::Semi(ref e) => hir::Stmt {
+                id: self.lower_node_id(s.id).node_id,
+                node: hir::StmtKind::Semi(P(self.lower_expr(e))),
                 span: s.span,
             },
             StmtKind::Mac(..) => panic!("Shouldn't exist here"),
@@ -4795,7 +4800,7 @@ fn stmt_let_pat(
     ) -> hir::Stmt {
         let LoweredNodeId { node_id, hir_id } = self.next_id();
 
-        let local = P(hir::Local {
+        let local = hir::Local {
             pat,
             ty: None,
             init: ex,
@@ -4804,9 +4809,12 @@ fn stmt_let_pat(
             span: sp,
             attrs: ThinVec::new(),
             source,
-        });
-        let decl = respan(sp, hir::DeclKind::Local(local));
-        respan(sp, hir::StmtKind::Decl(P(decl), self.next_id().node_id))
+        };
+        hir::Stmt {
+            id: self.next_id().node_id,
+            node: hir::StmtKind::Local(P(local)),
+            span: sp
+        }
     }
 
     fn stmt_let(
index ae9bb37842990f393562ac56686e566e7b1aa810..7cc5d756ff311730fc4d3e77af2e84e515b9910e 100644 (file)
@@ -426,7 +426,7 @@ fn visit_expr(&mut self, expr: &'hir Expr) {
     }
 
     fn visit_stmt(&mut self, stmt: &'hir Stmt) {
-        let id = stmt.node.id();
+        let id = stmt.id;
         self.insert(stmt.span, id, Node::Stmt(stmt));
 
         self.with_parent(id, |this| {
index bc0a64ae7c5d84ca537766f55957e15f1d40be39..c9b4b2bb997178184d8a5dc8eaa5f2620f103cab 100644 (file)
@@ -120,10 +120,10 @@ fn visit_item(&mut self, i: &'a Item) {
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
             ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
+            ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
-            ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
-            ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.as_interned_str()),
+            ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
+            ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
index 6b707dd2dcc80a2c5a6f9d2368ca119a07159ca8..1b7445199475c4ccaf215afc2336fad9681148c9 100644 (file)
@@ -373,7 +373,9 @@ pub enum DefPathData {
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
     /// are only supposed to show up right below the crate root.
-    GlobalMetaData(InternedString)
+    GlobalMetaData(InternedString),
+    /// A trait alias.
+    TraitAlias(InternedString),
 }
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -615,6 +617,7 @@ pub fn get_opt_name(&self) -> Option<InternedString> {
         match *self {
             TypeNs(name) |
             Trait(name) |
+            TraitAlias(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
             AssocExistentialInImpl(name) |
@@ -642,6 +645,7 @@ pub fn as_interned_str(&self) -> InternedString {
         let s = match *self {
             TypeNs(name) |
             Trait(name) |
+            TraitAlias(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
             AssocExistentialInImpl(name) |
index d9ca37c937bc76ab3b856f3ba8c98c0ae4311f6a..c3e4f0c05014c745155902958dee598b16e17df6 100644 (file)
@@ -455,11 +455,20 @@ pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
             Node::AnonConst(_) => {
                 BodyOwnerKind::Const
             }
+            Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
+            Node::StructCtor(..) |
+            Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
+            Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
+            Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
+                BodyOwnerKind::Fn
+            }
             Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => {
                 BodyOwnerKind::Static(m)
             }
-            // Default to function if it's not a constant or static.
-            _ => BodyOwnerKind::Fn
+            Node::Expr(&Expr { node: ExprKind::Closure(..), .. }) => {
+                BodyOwnerKind::Closure
+            }
+            node => bug!("{:#?} is not a body node", node),
         }
     }
 
index aaef1c722be9695db03e144f374832078e7620bd..b58b1d359f98bb915d23ef466a591b91d4ddf54e 100644 (file)
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 
+use errors::FatalError;
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
 use util::nodemap::{NodeMap, FxHashSet};
 use mir::mono::Linkage;
 
 use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
-use syntax::source_map::{self, Spanned};
+use syntax::source_map::Spanned;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy};
@@ -1133,45 +1134,41 @@ pub fn is_by_value(self) -> bool {
 }
 
 /// A statement
-pub type Stmt = Spanned<StmtKind>;
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub struct Stmt {
+    pub id: NodeId,
+    pub node: StmtKind,
+    pub span: Span,
+}
 
-impl fmt::Debug for StmtKind {
+impl fmt::Debug for Stmt {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Sadness.
-        let spanned = source_map::dummy_spanned(self.clone());
-        write!(f,
-               "stmt({}: {})",
-               spanned.node.id(),
-               print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned)))
+        write!(f, "stmt({}: {})", self.id,
+               print::to_string(print::NO_ANN, |s| s.print_stmt(self)))
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub enum StmtKind {
-    /// Could be an item or a local (let) binding:
-    Decl(P<Decl>, NodeId),
+    /// A local (let) binding:
+    Local(P<Local>),
+    /// An item binding:
+    Item(P<ItemId>),
 
     /// Expr without trailing semi-colon (must have unit type):
-    Expr(P<Expr>, NodeId),
+    Expr(P<Expr>),
 
     /// Expr with trailing semi-colon (may have any type):
-    Semi(P<Expr>, NodeId),
+    Semi(P<Expr>),
 }
 
 impl StmtKind {
     pub fn attrs(&self) -> &[Attribute] {
         match *self {
-            StmtKind::Decl(ref d, _) => d.node.attrs(),
-            StmtKind::Expr(ref e, _) |
-            StmtKind::Semi(ref e, _) => &e.attrs,
-        }
-    }
-
-    pub fn id(&self) -> NodeId {
-        match *self {
-            StmtKind::Decl(_, id) |
-            StmtKind::Expr(_, id) |
-            StmtKind::Semi(_, id) => id,
+            StmtKind::Local(ref l) => &l.attrs,
+            StmtKind::Item(_) => &[],
+            StmtKind::Expr(ref e) |
+            StmtKind::Semi(ref e) => &e.attrs,
         }
     }
 }
@@ -1190,32 +1187,6 @@ pub struct Local {
     pub source: LocalSource,
 }
 
-pub type Decl = Spanned<DeclKind>;
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum DeclKind {
-    /// A local (let) binding:
-    Local(P<Local>),
-    /// An item binding:
-    Item(ItemId),
-}
-
-impl DeclKind {
-    pub fn attrs(&self) -> &[Attribute] {
-        match *self {
-            DeclKind::Local(ref l) => &l.attrs,
-            DeclKind::Item(_) => &[]
-        }
-    }
-
-    pub fn is_local(&self) -> bool {
-        match *self {
-            DeclKind::Local(_) => true,
-            _ => false,
-        }
-    }
-}
-
 /// represents one arm of a 'match'
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Arm {
@@ -1299,6 +1270,9 @@ pub enum BodyOwnerKind {
     /// Functions and methods.
     Fn,
 
+    /// Closures
+    Closure,
+
     /// Constants and associated constants.
     Const,
 
@@ -1306,6 +1280,15 @@ pub enum BodyOwnerKind {
     Static(Mutability),
 }
 
+impl BodyOwnerKind {
+    pub fn is_fn_or_closure(self) -> bool {
+        match self {
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
+            BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
+        }
+    }
+}
+
 /// A constant (expression) that's not an item or associated item,
 /// but needs its own `DefId` for type-checking, const-eval, etc.
 /// These are usually found nested inside types (e.g., array lengths)
@@ -2055,6 +2038,20 @@ pub struct TraitRef {
     pub hir_ref_id: HirId,
 }
 
+impl TraitRef {
+    /// Get the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
+    pub fn trait_def_id(&self) -> DefId {
+        match self.path.def {
+            Def::Trait(did) => did,
+            Def::TraitAlias(did) => did,
+            Def::Err => {
+                FatalError.raise();
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct PolyTraitRef {
     /// The `'a` in `<'a> Foo<&'a T>`
index d7acdefcc7d7119ccb36866b91f79d745a5a7ef5..e950f25c2ac9ae8697dbc969d91dc54ea30c9625 100644 (file)
@@ -992,14 +992,29 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
     pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
         self.maybe_print_comment(st.span.lo())?;
         match st.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                self.print_decl(&decl)?;
+            hir::StmtKind::Local(ref loc) => {
+                self.space_if_not_bol()?;
+                self.ibox(indent_unit)?;
+                self.word_nbsp("let")?;
+
+                self.ibox(indent_unit)?;
+                self.print_local_decl(&loc)?;
+                self.end()?;
+                if let Some(ref init) = loc.init {
+                    self.nbsp()?;
+                    self.word_space("=")?;
+                    self.print_expr(&init)?;
+                }
+                self.end()?
+            }
+            hir::StmtKind::Item(ref item) => {
+                self.ann.nested(self, Nested::Item(**item))?
             }
-            hir::StmtKind::Expr(ref expr, _) => {
+            hir::StmtKind::Expr(ref expr) => {
                 self.space_if_not_bol()?;
                 self.print_expr(&expr)?;
             }
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Semi(ref expr) => {
                 self.space_if_not_bol()?;
                 self.print_expr(&expr)?;
                 self.s.word(";")?;
@@ -1562,30 +1577,6 @@ pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> {
         Ok(())
     }
 
-    pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
-        self.maybe_print_comment(decl.span.lo())?;
-        match decl.node {
-            hir::DeclKind::Local(ref loc) => {
-                self.space_if_not_bol()?;
-                self.ibox(indent_unit)?;
-                self.word_nbsp("let")?;
-
-                self.ibox(indent_unit)?;
-                self.print_local_decl(&loc)?;
-                self.end()?;
-                if let Some(ref init) = loc.init {
-                    self.nbsp()?;
-                    self.word_space("=")?;
-                    self.print_expr(&init)?;
-                }
-                self.end()
-            }
-            hir::DeclKind::Item(item) => {
-                self.ann.nested(self, Nested::Item(item))
-            }
-        }
-    }
-
     pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
         self.s.word(i.to_string())
     }
@@ -2401,18 +2392,10 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
 /// seen the semicolon, and thus don't need another.
 fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool {
     match *stmt {
-        hir::StmtKind::Decl(ref d, _) => {
-            match d.node {
-                hir::DeclKind::Local(_) => true,
-                hir::DeclKind::Item(_) => false,
-            }
-        }
-        hir::StmtKind::Expr(ref e, _) => {
-            expr_requires_semi_to_be_stmt(&e)
-        }
-        hir::StmtKind::Semi(..) => {
-            false
-        }
+        hir::StmtKind::Local(_) => true,
+        hir::StmtKind::Item(_) => false,
+        hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
+        hir::StmtKind::Semi(..) => false,
     }
 }
 
index f48059b328ff3631ae97c0fee29b9e188b7ab131..159067663d42e1402e5ee6f77e296c61a2cae8b0 100644 (file)
@@ -483,7 +483,12 @@ fn hash_stable<W: StableHasherResult>(&self,
     UnNeg
 });
 
-impl_stable_hash_for_spanned!(hir::StmtKind);
+impl_stable_hash_for!(struct hir::Stmt {
+    id,
+    node,
+    span,
+});
+
 
 impl_stable_hash_for!(struct hir::Local {
     pat,
@@ -496,12 +501,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     source
 });
 
-impl_stable_hash_for_spanned!(hir::DeclKind);
-impl_stable_hash_for!(enum hir::DeclKind {
-    Local(local),
-    Item(item_id)
-});
-
 impl_stable_hash_for!(struct hir::Arm {
     attrs,
     pats,
@@ -941,9 +940,10 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl_stable_hash_for!(enum hir::StmtKind {
-    Decl(decl, id),
-    Expr(expr, id),
-    Semi(expr, id)
+    Local(local),
+    Item(item_id),
+    Expr(expr),
+    Semi(expr)
 });
 
 impl_stable_hash_for!(struct hir::Arg {
index 70ec72d73bc6cc9a83f8c15ecf2e8c4a26239641..7e48554067a95b2d3bca2e46e7203abc3b535081 100644 (file)
@@ -164,6 +164,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
     Str(value, style),
+    Err(value),
     ByteStr(value),
     Byte(value),
     Char(value),
@@ -258,7 +259,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
                 span.hash_stable(hcx, hasher);
                 std_hash::Hash::hash(&delim, hasher);
-                for sub_tt in tts.stream().trees() {
+                for sub_tt in tts.trees() {
                     sub_tt.hash_stable(hcx, hasher);
                 }
             }
@@ -329,6 +330,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
             match *lit {
                 token::Lit::Byte(val) |
                 token::Lit::Char(val) |
+                token::Lit::Err(val) |
                 token::Lit::Integer(val) |
                 token::Lit::Float(val) |
                 token::Lit::Str_(val) |
index 2995b25308d4c9f455565cf6278f92fa3e3fd988..35f6e6aa610ad8d052f4f35ca78fc96596fd2579 100644 (file)
@@ -485,12 +485,29 @@ fn check_and_note_conflicting_crates(
         }
     }
 
-    fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
+    fn note_error_origin(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        cause: &ObligationCause<'tcx>,
+        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
+    ) {
         match cause.code {
             ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
                 if ty.is_suggestable() {  // don't show type `_`
                     err.span_label(span, format!("this match expression has type `{}`", ty));
                 }
+                if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
+                    if ty.is_box() && ty.boxed_ty() == found {
+                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "consider dereferencing the boxed value",
+                                format!("*{}", snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    }
+                }
             }
             ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
                 hir::MatchSource::IfLetDesugar { .. } => {
@@ -1013,7 +1030,7 @@ pub fn note_type_err(
 
         // It reads better to have the error origin as the final
         // thing.
-        self.note_error_origin(diag, &cause);
+        self.note_error_origin(diag, &cause, exp_found);
     }
 
     /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
index b1ac8bae4fb986bbbfd8239c7d8173a542e95a82..e7afaa5beb0a75adcc35dca489ddbfe834cc0419 100644 (file)
@@ -1,403 +1,8 @@
-# Skolemization and functions
+To learn more about how Higher-ranked trait bounds work in the _old_ trait
+solver, see [this chapter][oldhrtb] of the rustc-guide.
 
-One of the trickiest and most subtle aspects of regions is dealing
-with higher-ranked things which include bound region variables, such
-as function types. I strongly suggest that if you want to understand
-the situation, you read this paper (which is, admittedly, very long,
-but you don't have to read the whole thing):
+To learn more about how they work in the _new_ trait solver, see [this
+chapter][newhrtb].
 
-http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/
-
-Although my explanation will never compete with SPJ's (for one thing,
-his is approximately 100 pages), I will attempt to explain the basic
-problem and also how we solve it. Note that the paper only discusses
-subtyping, not the computation of LUB/GLB.
-
-The problem we are addressing is that there is a kind of subtyping
-between functions with bound region parameters. Consider, for
-example, whether the following relation holds:
-
-    for<'a> fn(&'a isize) <: for<'b> fn(&'b isize)? (Yes, a => b)
-
-The answer is that of course it does. These two types are basically
-the same, except that in one we used the name `a` and one we used
-the name `b`.
-
-In the examples that follow, it becomes very important to know whether
-a lifetime is bound in a function type (that is, is a lifetime
-parameter) or appears free (is defined in some outer scope).
-Therefore, from now on I will always write the bindings explicitly,
-using the Rust syntax `for<'a> fn(&'a isize)` to indicate that `a` is a
-lifetime parameter.
-
-Now let's consider two more function types. Here, we assume that the
-`'b` lifetime is defined somewhere outside and hence is not a lifetime
-parameter bound by the function type (it "appears free"):
-
-    for<'a> fn(&'a isize) <: fn(&'b isize)? (Yes, a => b)
-
-This subtyping relation does in fact hold. To see why, you have to
-consider what subtyping means. One way to look at `T1 <: T2` is to
-say that it means that it is always ok to treat an instance of `T1` as
-if it had the type `T2`. So, with our functions, it is always ok to
-treat a function that can take pointers with any lifetime as if it
-were a function that can only take a pointer with the specific
-lifetime `'b`. After all, `'b` is a lifetime, after all, and
-the function can take values of any lifetime.
-
-You can also look at subtyping as the *is a* relationship. This amounts
-to the same thing: a function that accepts pointers with any lifetime
-*is a* function that accepts pointers with some specific lifetime.
-
-So, what if we reverse the order of the two function types, like this:
-
-    fn(&'b isize) <: for<'a> fn(&'a isize)? (No)
-
-Does the subtyping relationship still hold?  The answer of course is
-no. In this case, the function accepts *only the lifetime `'b`*,
-so it is not reasonable to treat it as if it were a function that
-accepted any lifetime.
-
-What about these two examples:
-
-    for<'a,'b> fn(&'a isize, &'b isize) <: for<'a>    fn(&'a isize, &'a isize)? (Yes)
-    for<'a>    fn(&'a isize, &'a isize) <: for<'a,'b> fn(&'a isize, &'b isize)? (No)
-
-Here, it is true that functions which take two pointers with any two
-lifetimes can be treated as if they only accepted two pointers with
-the same lifetime, but not the reverse.
-
-## The algorithm
-
-Here is the algorithm we use to perform the subtyping check:
-
-1. Replace all bound regions in the subtype with new variables
-2. Replace all bound regions in the supertype with placeholder
-   equivalents. A "placeholder" region is just a new fresh region
-   name.
-3. Check that the parameter and return types match as normal
-4. Ensure that no placeholder regions 'leak' into region variables
-   visible from "the outside"
-
-Let's walk through some examples and see how this algorithm plays out.
-
-#### First example
-
-We'll start with the first example, which was:
-
-    1. for<'a> fn(&'a T) <: for<'b> fn(&'b T)?        Yes: a -> b
-
-After steps 1 and 2 of the algorithm we will have replaced the types
-like so:
-
-    1. fn(&'A T) <: fn(&'x T)?
-
-Here the upper case `&A` indicates a *region variable*, that is, a
-region whose value is being inferred by the system. I also replaced
-`&b` with `&x`---I'll use letters late in the alphabet (`x`, `y`, `z`)
-to indicate placeholder region names. We can assume they don't appear
-elsewhere. Note that neither the sub- nor the supertype bind any
-region names anymore (as indicated by the absence of `<` and `>`).
-
-The next step is to check that the parameter types match. Because
-parameters are contravariant, this means that we check whether:
-
-    &'x T <: &'A T
-
-Region pointers are contravariant so this implies that
-
-    &A <= &x
-
-must hold, where `<=` is the subregion relationship. Processing
-*this* constrain simply adds a constraint into our graph that `&A <=
-&x` and is considered successful (it can, for example, be satisfied by
-choosing the value `&x` for `&A`).
-
-So far we have encountered no error, so the subtype check succeeds.
-
-#### The third example
-
-Now let's look first at the third example, which was:
-
-    3. fn(&'a T)    <: for<'b> fn(&'b T)?        No!
-
-After steps 1 and 2 of the algorithm we will have replaced the types
-like so:
-
-    3. fn(&'a T) <: fn(&'x T)?
-
-This looks pretty much the same as before, except that on the LHS
-`'a` was not bound, and hence was left as-is and not replaced with
-a variable. The next step is again to check that the parameter types
-match. This will ultimately require (as before) that `'a` <= `&x`
-must hold: but this does not hold. `self` and `x` are both distinct
-free regions. So the subtype check fails.
-
-#### Checking for placeholder leaks
-
-You may be wondering about that mysterious last step in the algorithm.
-So far it has not been relevant. The purpose of that last step is to
-catch something like *this*:
-
-    for<'a> fn() -> fn(&'a T) <: fn() -> for<'b> fn(&'b T)?   No.
-
-Here the function types are the same but for where the binding occurs.
-The subtype returns a function that expects a value in precisely one
-region. The supertype returns a function that expects a value in any
-region. If we allow an instance of the subtype to be used where the
-supertype is expected, then, someone could call the fn and think that
-the return value has type `fn<b>(&'b T)` when it really has type
-`fn(&'a T)` (this is case #3, above). Bad.
-
-So let's step through what happens when we perform this subtype check.
-We first replace the bound regions in the subtype (the supertype has
-no bound regions). This gives us:
-
-    fn() -> fn(&'A T) <: fn() -> for<'b> fn(&'b T)?
-
-Now we compare the return types, which are covariant, and hence we have:
-
-    fn(&'A T) <: for<'b> fn(&'b T)?
-
-Here we replace the bound region in the supertype with a placeholder to yield:
-
-    fn(&'A T) <: fn(&'x T)?
-
-And then proceed to compare the argument types:
-
-    &'x T <: &'A T
-    'A <= 'x
-
-Finally, this is where it gets interesting!  This is where an error
-*should* be reported. But in fact this will not happen. The reason why
-is that `A` is a variable: we will infer that its value is the fresh
-region `x` and think that everything is happy. In fact, this behavior
-is *necessary*, it was key to the first example we walked through.
-
-The difference between this example and the first one is that the variable
-`A` already existed at the point where the placeholders were added. In
-the first example, you had two functions:
-
-    for<'a> fn(&'a T) <: for<'b> fn(&'b T)
-
-and hence `&A` and `&x` were created "together". In general, the
-intention of the placeholder names is that they are supposed to be
-fresh names that could never be equal to anything from the outside.
-But when inference comes into play, we might not be respecting this
-rule.
-
-So the way we solve this is to add a fourth step that examines the
-constraints that refer to placeholder names. Basically, consider a
-non-directed version of the constraint graph. Let `Tainted(x)` be the
-set of all things reachable from a placeholder variable `x`.
-`Tainted(x)` should not contain any regions that existed before the
-step at which the placeholders were created. So this case here
-would fail because `&x` was created alone, but is relatable to `&A`.
-
-## Computing the LUB and GLB
-
-The paper I pointed you at is written for Haskell. It does not
-therefore considering subtyping and in particular does not consider
-LUB or GLB computation. We have to consider this. Here is the
-algorithm I implemented.
-
-First though, let's discuss what we are trying to compute in more
-detail. The LUB is basically the "common supertype" and the GLB is
-"common subtype"; one catch is that the LUB should be the
-*most-specific* common supertype and the GLB should be *most general*
-common subtype (as opposed to any common supertype or any common
-subtype).
-
-Anyway, to help clarify, here is a table containing some function
-pairs and their LUB/GLB (for conciseness, in this table, I'm just
-including the lifetimes here, not the rest of the types, and I'm
-writing `fn<>` instead of `for<> fn`):
-
-```
-Type 1                Type 2                LUB                    GLB
-fn<'a>('a)            fn('X)                fn('X)                 fn<'a>('a)
-fn('a)                fn('X)                --                     fn<'a>('a)
-fn<'a,'b>('a, 'b)     fn<'x>('x, 'x)        fn<'a>('a, 'a)         fn<'a,'b>('a, 'b)
-fn<'a,'b>('a, 'b, 'a) fn<'x,'y>('x, 'y, 'y) fn<'a>('a, 'a, 'a)     fn<'a,'b,'c>('a,'b,'c)
-```
-
-### Conventions
-
-I use lower-case letters (e.g., `&a`) for bound regions and upper-case
-letters for free regions (`&A`).  Region variables written with a
-dollar-sign (e.g., `$a`).  I will try to remember to enumerate the
-bound-regions on the fn type as well (e.g., `for<'a> fn(&a)`).
-
-### High-level summary
-
-Both the LUB and the GLB algorithms work in a similar fashion.  They
-begin by replacing all bound regions (on both sides) with fresh region
-inference variables.  Therefore, both functions are converted to types
-that contain only free regions.  We can then compute the LUB/GLB in a
-straightforward way, as described in `combine.rs`.  This results in an
-interim type T.  The algorithms then examine the regions that appear
-in T and try to, in some cases, replace them with bound regions to
-yield the final result.
-
-To decide whether to replace a region `R` that appears in `T` with
-a bound region, the algorithms make use of two bits of
-information.  First is a set `V` that contains all region
-variables created as part of the LUB/GLB computation (roughly; see
-`region_vars_confined_to_snapshot()` for full details). `V` will
-contain the region variables created to replace the bound regions
-in the input types, but it also contains 'intermediate' variables
-created to represent the LUB/GLB of individual regions.
-Basically, when asked to compute the LUB/GLB of a region variable
-with another region, the inferencer cannot oblige immediately
-since the values of that variables are not known.  Therefore, it
-creates a new variable that is related to the two regions.  For
-example, the LUB of two variables `$x` and `$y` is a fresh
-variable `$z` that is constrained such that `$x <= $z` and `$y <=
-$z`.  So `V` will contain these intermediate variables as well.
-
-The other important factor in deciding how to replace a region in T is
-the function `Tainted($r)` which, for a region variable, identifies
-all regions that the region variable is related to in some way
-(`Tainted()` made an appearance in the subtype computation as well).
-
-### LUB
-
-The LUB algorithm proceeds in three steps:
-
-1. Replace all bound regions (on both sides) with fresh region
-   inference variables.
-2. Compute the LUB "as normal", meaning compute the GLB of each
-   pair of argument types and the LUB of the return types and
-   so forth.  Combine those to a new function type `F`.
-3. Replace each region `R` that appears in `F` as follows:
-   - Let `V` be the set of variables created during the LUB
-     computational steps 1 and 2, as described in the previous section.
-   - If `R` is not in `V`, replace `R` with itself.
-   - If `Tainted(R)` contains a region that is not in `V`,
-     replace `R` with itself.
-   - Otherwise, select the earliest variable in `Tainted(R)` that originates
-     from the left-hand side and replace `R` with the bound region that
-     this variable was a replacement for.
-
-So, let's work through the simplest example: `fn(&A)` and `for<'a> fn(&a)`.
-In this case, `&a` will be replaced with `$a` and the interim LUB type
-`fn($b)` will be computed, where `$b=GLB(&A,$a)`.  Therefore, `V =
-{$a, $b}` and `Tainted($b) = { $b, $a, &A }`.  When we go to replace
-`$b`, we find that since `&A \in Tainted($b)` is not a member of `V`,
-we leave `$b` as is.  When region inference happens, `$b` will be
-resolved to `&A`, as we wanted.
-
-Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`.  In
-this case, we'll end up with a (pre-replacement) LUB type of `fn(&g,
-&h)` and a graph that looks like:
-
-```
-     $a        $b     *--$x
-       \        \    /  /
-        \        $h-*  /
-         $g-----------*
-```
-
-Here `$g` and `$h` are fresh variables that are created to represent
-the LUB/GLB of things requiring inference.  This means that `V` and
-`Tainted` will look like:
-
-```
-V = {$a, $b, $g, $h, $x}
-Tainted($g) = Tainted($h) = { $a, $b, $h, $g, $x }
-```
-
-Therefore we replace both `$g` and `$h` with `$a`, and end up
-with the type `fn(&a, &a)`.
-
-### GLB
-
-The procedure for computing the GLB is similar.  The difference lies
-in computing the replacements for the various variables. For each
-region `R` that appears in the type `F`, we again compute `Tainted(R)`
-and examine the results:
-
-1. If `R` is not in `V`, it is not replaced.
-2. Else, if `Tainted(R)` contains only variables in `V`, and it
-   contains exactly one variable from the LHS and one variable from
-   the RHS, then `R` can be mapped to the bound version of the
-   variable from the LHS.
-3. Else, if `Tainted(R)` contains no variable from the LHS and no
-   variable from the RHS, then `R` can be mapped to itself.
-4. Else, `R` is mapped to a fresh bound variable.
-
-These rules are pretty complex.  Let's look at some examples to see
-how they play out.
-
-Out first example was `fn(&a)` and `fn(&X)`.  In this case, `&a` will
-be replaced with `$a` and we will ultimately compute a
-(pre-replacement) GLB type of `fn($g)` where `$g=LUB($a,&X)`.
-Therefore, `V={$a,$g}` and `Tainted($g)={$g,$a,&X}.  To find the
-replacement for `$g` we consult the rules above:
-- Rule (1) does not apply because `$g \in V`
-- Rule (2) does not apply because `&X \in Tainted($g)`
-- Rule (3) does not apply because `$a \in Tainted($g)`
-- Hence, by rule (4), we replace `$g` with a fresh bound variable `&z`.
-So our final result is `fn(&z)`, which is correct.
-
-The next example is `fn(&A)` and `fn(&Z)`. In this case, we will again
-have a (pre-replacement) GLB of `fn(&g)`, where `$g = LUB(&A,&Z)`.
-Therefore, `V={$g}` and `Tainted($g) = {$g, &A, &Z}`.  In this case,
-by rule (3), `$g` is mapped to itself, and hence the result is
-`fn($g)`.  This result is correct (in this case, at least), but it is
-indicative of a case that *can* lead us into concluding that there is
-no GLB when in fact a GLB does exist.  See the section "Questionable
-Results" below for more details.
-
-The next example is `fn(&a, &b)` and `fn(&c, &c)`. In this case, as
-before, we'll end up with `F=fn($g, $h)` where `Tainted($g) =
-Tainted($h) = {$g, $h, $a, $b, $c}`.  Only rule (4) applies and hence
-we'll select fresh bound variables `y` and `z` and wind up with
-`fn(&y, &z)`.
-
-For the last example, let's consider what may seem trivial, but is
-not: `fn(&a, &a)` and `fn(&b, &b)`.  In this case, we'll get `F=fn($g,
-$h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a,
-$x}`.  Both of these sets contain exactly one bound variable from each
-side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`, which
-is the desired result.
-
-### Shortcomings and correctness
-
-You may be wondering whether this algorithm is correct.  The answer is
-"sort of".  There are definitely cases where they fail to compute a
-result even though a correct result exists.  I believe, though, that
-if they succeed, then the result is valid, and I will attempt to
-convince you.  The basic argument is that the "pre-replacement" step
-computes a set of constraints.  The replacements, then, attempt to
-satisfy those constraints, using bound identifiers where needed.
-
-For now I will briefly go over the cases for LUB/GLB and identify
-their intent:
-
-- LUB:
-  - The region variables that are substituted in place of bound regions
-    are intended to collect constraints on those bound regions.
-  - If Tainted(R) contains only values in V, then this region is unconstrained
-    and can therefore be generalized, otherwise it cannot.
-- GLB:
-  - The region variables that are substituted in place of bound regions
-    are intended to collect constraints on those bound regions.
-  - If Tainted(R) contains exactly one variable from each side, and
-    only variables in V, that indicates that those two bound regions
-    must be equated.
-  - Otherwise, if Tainted(R) references any variables from left or right
-    side, then it is trying to combine a bound region with a free one or
-    multiple bound regions, so we need to select fresh bound regions.
-
-Sorry this is more of a shorthand to myself.  I will try to write up something
-more convincing in the future.
-
-#### Where are the algorithms wrong?
-
-- The pre-replacement computation can fail even though using a
-  bound-region would have succeeded.
-- We will compute GLB(fn(fn($a)), fn(fn($b))) as fn($c) where $c is the
-  GLB of $a and $b.  But if inference finds that $a and $b must be mapped
-  to regions without a GLB, then this is effectively a failure to compute
-  the GLB.  However, the result `fn<$c>(fn($c))` is a valid GLB.
+[oldhrtb]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
+[newhrtb]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html#placeholders-and-universes
index 4483e522f3a1f59b40aa56d809903821ff3ac8b4..56320636a67431a88e7616cfb7c9189936977ec3 100644 (file)
@@ -2,8 +2,12 @@
 
 > WARNING: This README is obsolete and will be removed soon! For
 > more info on how the current borrowck works, see the [rustc guide].
+>
+> As of edition 2018, region inference is done using Non-lexical lifetimes,
+> which is described in the guide and [this RFC].
 
 [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
+[this RFC]: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md
 
 ## Terminology
 
index 39ce8cc621b49d9215de6dfe3998085a937eead7..c0952fefac0e18dcdecb203969b404a6780c54b6 100644 (file)
@@ -186,34 +186,39 @@ fn expand_givens(&mut self, graph: &RegionGraph<'_>) {
     }
 
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
-        self.iterate_until_fixed_point("Expansion", |constraint, origin| {
-            debug!("expansion: constraint={:?} origin={:?}", constraint, origin);
-            match *constraint {
+        self.iterate_until_fixed_point("Expansion", |constraint| {
+            debug!("expansion: constraint={:?}", constraint);
+            let (a_region, b_vid, b_data, retain) = match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    (self.expand_node(a_region, b_vid, b_data), false)
+                    (a_region, b_vid, b_data, false)
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
-                    VarValue::ErrorValue => (false, false),
+                    VarValue::ErrorValue => return (false, false),
                     VarValue::Value(a_region) => {
-                        let b_node = var_values.value_mut(b_vid);
-                        let changed = self.expand_node(a_region, b_vid, b_node);
-                        let retain = match *b_node {
+                        let b_data = var_values.value_mut(b_vid);
+                        let retain = match *b_data {
                             VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
                             _ => true
                         };
-                        (changed, retain)
+                        (a_region, b_vid, b_data, retain)
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    (false, false)
+                    return (false, false)
                 }
-            }
+            };
+
+            let changed = self.expand_node(a_region, b_vid, b_data);
+            (changed, retain)
         })
     }
 
+    // This function is very hot in some workloads. There's a single callsite
+    // so always inlining is ok even though it's large.
+    #[inline(always)]
     fn expand_node(
         &self,
         a_region: Region<'tcx>,
@@ -236,6 +241,14 @@ fn expand_node(
 
         match *b_data {
             VarValue::Value(cur_region) => {
+                // Identical scopes can show up quite often, if the fixed point
+                // iteration converges slowly, skip them
+                if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
+                    if a_scope == cur_scope {
+                        return false;
+                    }
+                }
+
                 let mut lub = self.lub_concrete_regions(a_region, cur_region);
                 if lub == cur_region {
                     return false;
@@ -275,12 +288,6 @@ fn expand_node(
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
         let tcx = self.tcx();
 
-        // Equal scopes can show up quite often, if the fixed point
-        // iteration converges slowly, skip them
-        if a == b {
-            return a;
-        }
-
         match (a, b) {
             (&ty::ReClosureBound(..), _)
             | (_, &ty::ReClosureBound(..))
@@ -722,18 +729,17 @@ fn process_edges<'tcx>(
     }
 
     fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
-    where
-        F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool),
+        where F: FnMut(&Constraint<'tcx>) -> (bool, bool),
     {
-        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect();
+        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
         let mut iteration = 0;
         let mut changed = true;
         while changed {
             changed = false;
             iteration += 1;
             debug!("---- {} Iteration {}{}", "#", tag, iteration);
-            constraints.retain(|(constraint, origin)| {
-                let (edge_changed, retain) = body(constraint, origin);
+            constraints.retain(|constraint| {
+                let (edge_changed, retain) = body(constraint);
                 if edge_changed {
                     debug!("Updated due to constraint {:?}", constraint);
                     changed = true;
index 775bbf955b830efd558623056a450e20cd8bb481..ea7fffe9dc1c6fdc25b673ff7b248cc1bcea9203 100644 (file)
@@ -1,77 +1,3 @@
-# Region constraint collection
-
-> WARNING: This README is obsolete and will be removed soon! For
-> more info on how the current borrowck works, see the [rustc guide].
+For info on how the current borrowck works, see the [rustc guide].
 
 [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
-
-## Terminology
-
-Note that we use the terms region and lifetime interchangeably.
-
-## Introduction
-
-As described in the rustc guide [chapter on type inference][ti], and unlike
-normal type inference, which is similar in spirit to H-M and thus
-works progressively, the region type inference works by accumulating
-constraints over the course of a function.  Finally, at the end of
-processing a function, we process and solve the constraints all at
-once.
-
-[ti]: https://rust-lang.github.io/rustc-guide/type-inference.html
-
-The constraints are always of one of three possible forms:
-
-- `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be
-  a subregion of Rj
-- `ConstrainRegSubVar(R, Ri)` states that the concrete region R (which
-  must not be a variable) must be a subregion of the variable Ri
-- `ConstrainVarSubReg(Ri, R)` states the variable Ri should be less
-  than the concrete region R. This is kind of deprecated and ought to
-  be replaced with a verify (they essentially play the same role).
-
-In addition to constraints, we also gather up a set of "verifys"
-(what, you don't think Verify is a noun? Get used to it my
-friend!). These represent relations that must hold but which don't
-influence inference proper. These take the form of:
-
-- `VerifyRegSubReg(Ri, Rj)` indicates that Ri <= Rj must hold,
-  where Rj is not an inference variable (and Ri may or may not contain
-  one). This doesn't influence inference because we will already have
-  inferred Ri to be as small as possible, so then we just test whether
-  that result was less than Rj or not.
-- `VerifyGenericBound(R, Vb)` is a more complex expression which tests
-  that the region R must satisfy the bound `Vb`. The bounds themselves
-  may have structure like "must outlive one of the following regions"
-  or "must outlive ALL of the following regions. These bounds arise
-  from constraints like `T: 'a` -- if we know that `T: 'b` and `T: 'c`
-  (say, from where clauses), then we can conclude that `T: 'a` if `'b:
-  'a` *or* `'c: 'a`.
-
-## Building up the constraints
-
-Variables and constraints are created using the following methods:
-
-- `new_region_var()` creates a new, unconstrained region variable;
-- `make_subregion(Ri, Rj)` states that Ri is a subregion of Rj
-- `lub_regions(Ri, Rj) -> Rk` returns a region Rk which is
-  the smallest region that is greater than both Ri and Rj
-- `glb_regions(Ri, Rj) -> Rk` returns a region Rk which is
-  the greatest region that is smaller than both Ri and Rj
-
-The actual region resolution algorithm is not entirely
-obvious, though it is also not overly complex.
-
-## Snapshotting
-
-It is also permitted to try (and rollback) changes to the graph.  This
-is done by invoking `start_snapshot()`, which returns a value.  Then
-later you can call `rollback_to()` which undoes the work.
-Alternatively, you can call `commit()` which ends all snapshots.
-Snapshots can be recursive---so you can start a snapshot when another
-is in progress, but only the root snapshot can "commit".
-
-## Skolemization
-
-For a discussion on skolemization and higher-ranked subtyping, please
-see the module `middle::infer::higher_ranked::doc`.
index fba9b8527677ca1538d0250708d5fddb671eff29..7ecec0b9a69acc724e4d27c3712c56ff1dac1dad 100644 (file)
@@ -41,7 +41,6 @@
 #![feature(nll)]
 #![feature(non_exhaustive)]
 #![feature(proc_macro_internals)]
-#![feature(quote)]
 #![feature(optin_builtin_traits)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
index f5a7919ef09c82b75f07b450efff709f13c36c00..837a3645d1c94d3c455bcb2c8523e827875ad69e 100644 (file)
@@ -941,11 +941,6 @@ fn visit_arm(&mut self, a: &'tcx hir::Arm) {
         hir_visit::walk_arm(self, a);
     }
 
-    fn visit_decl(&mut self, d: &'tcx hir::Decl) {
-        run_lints!(self, check_decl, d);
-        hir_visit::walk_decl(self, d);
-    }
-
     fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) {
         run_lints!(self, check_generic_param, p);
         hir_visit::walk_generic_param(self, p);
index 730ce919bd295ba65cdef8f9511e81c4f5045470..e83ba7402b5791cdbcac62f5853742367e8b8e73 100644 (file)
@@ -192,7 +192,6 @@ macro_rules! late_lint_methods {
             fn check_stmt(a: &$hir hir::Stmt);
             fn check_arm(a: &$hir hir::Arm);
             fn check_pat(a: &$hir hir::Pat);
-            fn check_decl(a: &$hir hir::Decl);
             fn check_expr(a: &$hir hir::Expr);
             fn check_expr_post(a: &$hir hir::Expr);
             fn check_ty(a: &$hir hir::Ty);
index c1aa25b6b75c20f842ed1ed28e0e395ee93e2053..08210c3f075ce453e3a5fc4c06a80e8207ecee6d 100644 (file)
@@ -589,21 +589,17 @@ fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
 
     fn walk_stmt(&mut self, stmt: &hir::Stmt) {
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                match decl.node {
-                    hir::DeclKind::Local(ref local) => {
-                        self.walk_local(&local);
-                    }
+            hir::StmtKind::Local(ref local) => {
+                self.walk_local(&local);
+            }
 
-                    hir::DeclKind::Item(_) => {
-                        // we don't visit nested items in this visitor,
-                        // only the fn body we were given.
-                    }
-                }
+            hir::StmtKind::Item(_) => {
+                // we don't visit nested items in this visitor,
+                // only the fn body we were given.
             }
 
-            hir::StmtKind::Expr(ref expr, _) |
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Expr(ref expr) |
+            hir::StmtKind::Semi(ref expr) => {
                 self.consume_expr(&expr);
             }
         }
index e73677d21b0adcdbea81ae5ef9e910df2cd324a2..220bec735a47360b828ed4482c24f8d183181717 100644 (file)
@@ -962,46 +962,31 @@ fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
     fn propagate_through_stmt(&mut self, stmt: &hir::Stmt, succ: LiveNode)
                               -> LiveNode {
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                self.propagate_through_decl(&decl, succ)
-            }
+            hir::StmtKind::Local(ref local) => {
+                // Note: we mark the variable as defined regardless of whether
+                // there is an initializer.  Initially I had thought to only mark
+                // the live variable as defined if it was initialized, and then we
+                // could check for uninit variables just by scanning what is live
+                // at the start of the function. But that doesn't work so well for
+                // immutable variables defined in a loop:
+                //     loop { let x; x = 5; }
+                // because the "assignment" loops back around and generates an error.
+                //
+                // So now we just check that variables defined w/o an
+                // initializer are not live at the point of their
+                // initialization, which is mildly more complex than checking
+                // once at the func header but otherwise equivalent.
 
-            hir::StmtKind::Expr(ref expr, _) | hir::StmtKind::Semi(ref expr, _) => {
-                self.propagate_through_expr(&expr, succ)
+                let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
+                self.define_bindings_in_pat(&local.pat, succ)
             }
-        }
-    }
-
-    fn propagate_through_decl(&mut self, decl: &hir::Decl, succ: LiveNode)
-                              -> LiveNode {
-        match decl.node {
-            hir::DeclKind::Local(ref local) => {
-                self.propagate_through_local(&local, succ)
+            hir::StmtKind::Item(..) => succ,
+            hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
+                self.propagate_through_expr(&expr, succ)
             }
-            hir::DeclKind::Item(_) => succ,
         }
     }
 
-    fn propagate_through_local(&mut self, local: &hir::Local, succ: LiveNode)
-                               -> LiveNode {
-        // Note: we mark the variable as defined regardless of whether
-        // there is an initializer.  Initially I had thought to only mark
-        // the live variable as defined if it was initialized, and then we
-        // could check for uninit variables just by scanning what is live
-        // at the start of the function. But that doesn't work so well for
-        // immutable variables defined in a loop:
-        //     loop { let x; x = 5; }
-        // because the "assignment" loops back around and generates an error.
-        //
-        // So now we just check that variables defined w/o an
-        // initializer are not live at the point of their
-        // initialization, which is mildly more complex than checking
-        // once at the func header but otherwise equivalent.
-
-        let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
-        self.define_bindings_in_pat(&local.pat, succ)
-    }
-
     fn propagate_through_exprs(&mut self, exprs: &[Expr], succ: LiveNode)
                                -> LiveNode {
         exprs.iter().rev().fold(succ, |succ, expr| {
index ce2a34895062226715c33b8ec9c114cce4e92840..31f91a1bae57fa16982e955a5bea1f0dcd1aa12b 100644 (file)
@@ -784,20 +784,25 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
         // index information.)
 
         for (i, statement) in blk.stmts.iter().enumerate() {
-            if let hir::StmtKind::Decl(..) = statement.node {
-                // Each StmtKind::Decl introduces a subscope for bindings
-                // introduced by the declaration; this subscope covers
-                // a suffix of the block . Each subscope in a block
-                // has the previous subscope in the block as a parent,
-                // except for the first such subscope, which has the
-                // block itself as a parent.
-                visitor.enter_scope(
-                    Scope {
-                        id: blk.hir_id.local_id,
-                        data: ScopeData::Remainder(FirstStatementIndex::new(i))
-                    }
-                );
-                visitor.cx.var_parent = visitor.cx.parent;
+            match statement.node {
+                hir::StmtKind::Local(..) |
+                hir::StmtKind::Item(..) => {
+                    // Each declaration introduces a subscope for bindings
+                    // introduced by the declaration; this subscope covers a
+                    // suffix of the block. Each subscope in a block has the
+                    // previous subscope in the block as a parent, except for
+                    // the first such subscope, which has the block itself as a
+                    // parent.
+                    visitor.enter_scope(
+                        Scope {
+                            id: blk.hir_id.local_id,
+                            data: ScopeData::Remainder(FirstStatementIndex::new(i))
+                        }
+                    );
+                    visitor.cx.var_parent = visitor.cx.parent;
+                }
+                hir::StmtKind::Expr(..) |
+                hir::StmtKind::Semi(..) => {}
             }
             visitor.visit_stmt(statement)
         }
@@ -835,7 +840,7 @@ fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &
 }
 
 fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
-    let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.node.id()).local_id;
+    let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.id).local_id;
     debug!("resolve_stmt(stmt.id={:?})", stmt_id);
 
     // Every statement will clean up the temporaries created during
@@ -1263,8 +1268,8 @@ fn visit_body(&mut self, body: &'tcx hir::Body) {
 
         // The body of the every fn is a root scope.
         self.cx.parent = self.cx.var_parent;
-        if let hir::BodyOwnerKind::Fn = self.tcx.hir().body_owner_kind(owner_id) {
-            self.visit_expr(&body.value);
+        if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
+            self.visit_expr(&body.value)
         } else {
             // Only functions have an outer terminating (drop) scope, while
             // temporaries in constant initializers may be 'static, but only
index 0f14049ef2cca36748255e8de01d850a9b070fe5..cdbef568a6005012eda2742af76e05312092e59c 100644 (file)
@@ -1353,10 +1353,15 @@ fn parse_merge_functions(slot: &mut Option<MergeFunctions>, v: Option<&str>) ->
     unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
         "Present the input source, unstable (and less-pretty) variants;
         valid types are any of the types for `--pretty`, as well as:
+        `expanded`, `expanded,identified`,
+        `expanded,hygiene` (with internal representations),
         `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+        `flowgraph,unlabelled=<nodeid>` (unlabelled graphviz formatted flowgraph for node),
         `everybody_loops` (all function bodies replaced with `loop {}`),
-        `hir` (the HIR), `hir,identified`, or
-        `hir,typed` (HIR with types for each node)."),
+        `hir` (the HIR), `hir,identified`,
+        `hir,typed` (HIR with types for each node),
+        `hir-tree` (dump the raw HIR),
+        `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
     run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
index 367a7eacdfcaf50dd4e61a592f163f65a79e82ad..1c92e2da588a0a19caac1dacf3af6ce851ee7f11 100644 (file)
@@ -471,7 +471,7 @@ fn find_similar_impl_candidates(&self,
     }
 
     fn report_similar_impl_candidates(&self,
-                                      mut impl_candidates: Vec<ty::TraitRef<'tcx>>,
+                                      impl_candidates: Vec<ty::TraitRef<'tcx>>,
                                       err: &mut DiagnosticBuilder<'_>)
     {
         if impl_candidates.is_empty() {
@@ -497,14 +497,18 @@ fn report_similar_impl_candidates(&self,
         });
 
         // Sort impl candidates so that ordering is consistent for UI tests.
-        let normalized_impl_candidates = &mut impl_candidates[0..end]
+        let mut normalized_impl_candidates = impl_candidates
             .iter()
             .map(normalize)
             .collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
         normalized_impl_candidates.sort();
 
         err.help(&format!("the following implementations were found:{}{}",
-                          normalized_impl_candidates.join(""),
+                          normalized_impl_candidates[..end].join(""),
                           if len > 5 {
                               format!("\nand {} others", len - 4)
                           } else {
index 05a6cce895d1f3fd759e4e425aec562836f84071..9a0610f45dec2053ebe81d1b8c44a998c1fdb553 100644 (file)
@@ -2198,7 +2198,7 @@ fn assemble_candidates_for_trait_alias(
 
         let def_id = obligation.predicate.def_id();
 
-        if ty::is_trait_alias(self.tcx(), def_id) {
+        if self.tcx().is_trait_alias(def_id) {
             candidates.vec.push(TraitAliasCandidate(def_id.clone()));
         }
 
index 417e14054d24f260668bbb84edcc0b03593df614..0ddc5ae87208dcf2a61a51e868837794f34b1e2e 100644 (file)
@@ -210,12 +210,12 @@ pub fn try_push_visible_item_path<T>(
 
             let visible_parent = visible_parent_map.get(&cur_def).cloned();
             let actual_parent = self.parent(cur_def);
-            debug!(
-                "try_push_visible_item_path: visible_parent={:?} actual_parent={:?}",
-                visible_parent, actual_parent,
-            );
 
             let data = cur_def_key.disambiguated_data.data;
+            debug!(
+                "try_push_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}",
+                data, visible_parent, actual_parent,
+            );
             let symbol = match data {
                 // In order to output a path that could actually be imported (valid and visible),
                 // we need to handle re-exports correctly.
@@ -248,16 +248,16 @@ pub fn try_push_visible_item_path<T>(
                 // the children of the visible parent (as was done when computing
                 // `visible_parent_map`), looking for the specific child we currently have and then
                 // have access to the re-exported name.
-                DefPathData::Module(module_name) if visible_parent != actual_parent => {
-                    let mut name: Option<ast::Ident> = None;
-                    if let Some(visible_parent) = visible_parent {
-                        for child in self.item_children(visible_parent).iter() {
-                            if child.def.def_id() == cur_def {
-                                name = Some(child.ident);
-                            }
-                        }
-                    }
-                    name.map(|n| n.as_str()).unwrap_or(module_name.as_str())
+                DefPathData::Module(actual_name) |
+                DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => {
+                    visible_parent
+                        .and_then(|parent| {
+                            self.item_children(parent)
+                                .iter()
+                                .find(|child| child.def.def_id() == cur_def)
+                                .map(|child| child.ident.as_str())
+                        })
+                        .unwrap_or_else(|| actual_name.as_str())
                 },
                 _ => {
                     data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
@@ -311,6 +311,7 @@ pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId, pushed_prelude_cra
             data @ DefPathData::Misc |
             data @ DefPathData::TypeNs(..) |
             data @ DefPathData::Trait(..) |
+            data @ DefPathData::TraitAlias(..) |
             data @ DefPathData::AssocTypeInTrait(..) |
             data @ DefPathData::AssocTypeInImpl(..) |
             data @ DefPathData::AssocExistentialInImpl(..) |
index dc91a30ef9273fa8487ff5c05cde0f1534db2971..930bbc0888517a0e78f9d72b20eaa88cc1817574 100644 (file)
@@ -3170,18 +3170,6 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
     None
 }
 
-/// Returns `true` if `def_id` is a trait alias.
-pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
-    if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
-        if let Node::Item(item) = tcx.hir().get(node_id) {
-            if let hir::ItemKind::TraitAlias(..) = item.node {
-                return true;
-            }
-        }
-    }
-    false
-}
-
 /// See `ParamEnv` struct definition for details.
 fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        def_id: DefId)
index 0fcaef5de54c2dbaa93b881c9c73d93302647b7a..4b5e08cecd99c0719783fd538fe5e8044c293b3f 100644 (file)
@@ -1,302 +1,3 @@
-# The Rust Compiler Query System
-
-The Compiler Query System is the key to our new demand-driven
-organization.  The idea is pretty simple. You have various queries
-that compute things about the input -- for example, there is a query
-called `type_of(def_id)` that, given the def-id of some item, will
-compute the type of that item and return it to you.
-
-Query execution is **memoized** -- so the first time you invoke a
-query, it will go do the computation, but the next time, the result is
-returned from a hashtable. Moreover, query execution fits nicely into
-**incremental computation**; the idea is roughly that, when you do a
-query, the result **may** be returned to you by loading stored data
-from disk (but that's a separate topic we won't discuss further here).
-
-The overall vision is that, eventually, the entire compiler
-control-flow will be query driven. There will effectively be one
-top-level query ("compile") that will run compilation on a crate; this
-will in turn demand information about that crate, starting from the
-*end*.  For example:
-
-- This "compile" query might demand to get a list of codegen-units
-  (i.e., modules that need to be compiled by LLVM).
-- But computing the list of codegen-units would invoke some subquery
-  that returns the list of all modules defined in the Rust source.
-- That query in turn would invoke something asking for the HIR.
-- This keeps going further and further back until we wind up doing the
-  actual parsing.
-
-However, that vision is not fully realized. Still, big chunks of the
-compiler (for example, generating MIR) work exactly like this.
-
-### Invoking queries
-
-To invoke a query is simple. The tcx ("type context") offers a method
-for each defined query. So, for example, to invoke the `type_of`
-query, you would just do this:
-
-```rust
-let ty = tcx.type_of(some_def_id);
-```
-
-### Cycles between queries
-
-Currently, cycles during query execution should always result in a
-compilation error. Typically, they arise because of illegal programs
-that contain cyclic references they shouldn't (though sometimes they
-arise because of compiler bugs, in which case we need to factor our
-queries in a more fine-grained fashion to avoid them).
-
-However, it is nonetheless often useful to *recover* from a cycle
-(after reporting an error, say) and try to soldier on, so as to give a
-better user experience. In order to recover from a cycle, you don't
-get to use the nice method-call-style syntax. Instead, you invoke
-using the `try_get` method, which looks roughly like this:
-
-```rust
-use ty::query::queries;
-...
-match queries::type_of::try_get(tcx, DUMMY_SP, self.did) {
-  Ok(result) => {
-    // no cycle occurred! You can use `result`
-  }
-  Err(err) => {
-    // A cycle occurred! The error value `err` is a `DiagnosticBuilder`,
-    // meaning essentially an "in-progress", not-yet-reported error message.
-    // See below for more details on what to do here.
-  }
-}
-```
-
-So, if you get back an `Err` from `try_get`, then a cycle *did* occur. This means that
-you must ensure that a compiler error message is reported. You can do that in two ways:
-
-The simplest is to invoke `err.emit()`. This will emit the cycle error to the user.
-
-However, often cycles happen because of an illegal program, and you
-know at that point that an error either already has been reported or
-will be reported due to this cycle by some other bit of code. In that
-case, you can invoke `err.cancel()` to not emit any error. It is
-traditional to then invoke:
-
-```
-tcx.sess.delay_span_bug(some_span, "some message")
-```
-
-`delay_span_bug()` is a helper that says: we expect a compilation
-error to have happened or to happen in the future; so, if compilation
-ultimately succeeds, make an ICE with the message `"some
-message"`. This is basically just a precaution in case you are wrong.
-
-### How the compiler executes a query
-
-So you may be wondering what happens when you invoke a query
-method. The answer is that, for each query, the compiler maintains a
-cache -- if your query has already been executed, then, the answer is
-simple: we clone the return value out of the cache and return it
-(therefore, you should try to ensure that the return types of queries
-are cheaply cloneable; insert a `Rc` if necessary).
-
-#### Providers
-
-If, however, the query is *not* in the cache, then the compiler will
-try to find a suitable **provider**. A provider is a function that has
-been defined and linked into the compiler somewhere that contains the
-code to compute the result of the query.
-
-**Providers are defined per-crate.** The compiler maintains,
-internally, a table of providers for every crate, at least
-conceptually. Right now, there are really two sets: the providers for
-queries about the **local crate** (that is, the one being compiled)
-and providers for queries about **external crates** (that is,
-dependencies of the local crate). Note that what determines the crate
-that a query is targeting is not the *kind* of query, but the *key*.
-For example, when you invoke `tcx.type_of(def_id)`, that could be a
-local query or an external query, depending on what crate the `def_id`
-is referring to (see the `self::keys::Key` trait for more information
-on how that works).
-
-Providers always have the same signature:
-
-```rust
-fn provider<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx, 'tcx>,
-                       key: QUERY_KEY)
-                       -> QUERY_RESULT
-{
-    ...
-}
-```
-
-Providers take two arguments: the `tcx` and the query key. Note also
-that they take the *global* tcx (i.e., they use the `'tcx` lifetime
-twice), rather than taking a tcx with some active inference context.
-They return the result of the query.
-
-####  How providers are setup
-
-When the tcx is created, it is given the providers by its creator using
-the `Providers` struct. This struct is generate by the macros here, but it
-is basically a big list of function pointers:
-
-```rust
-struct Providers {
-    type_of: for<'cx, 'tcx> fn(TyCtxt<'cx, 'tcx, 'tcx>, DefId) -> Ty<'tcx>,
-    ...
-}
-```
-
-At present, we have one copy of the struct for local crates, and one
-for external crates, though the plan is that we may eventually have
-one per crate.
-
-These `Provider` structs are ultimately created and populated by
-`librustc_driver`, but it does this by distributing the work
-throughout the other `rustc_*` crates. This is done by invoking
-various `provide` functions. These functions tend to look something
-like this:
-
-```rust
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        type_of,
-        ..*providers
-    };
-}
-```
-
-That is, they take an `&mut Providers` and mutate it in place. Usually
-we use the formulation above just because it looks nice, but you could
-as well do `providers.type_of = type_of`, which would be equivalent.
-(Here, `type_of` would be a top-level function, defined as we saw
-before.) So, if we want to add a provider for some other query,
-let's call it `fubar`, into the crate above, we might modify the `provide()`
-function like so:
-
-```rust
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        type_of,
-        fubar,
-        ..*providers
-    };
-}
-
-fn fubar<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>, key: DefId) -> Fubar<'tcx> { .. }
-```
-
-NB. Most of the `rustc_*` crates only provide **local
-providers**. Almost all **extern providers** wind up going through the
-`rustc_metadata` crate, which loads the information from the crate
-metadata.  But in some cases there are crates that provide queries for
-*both* local and external crates, in which case they define both a
-`provide` and a `provide_extern` function that `rustc_driver` can
-invoke.
-
-### Adding a new kind of query
-
-So suppose you want to add a new kind of query, how do you do so?
-Well, defining a query takes place in two steps:
-
-1. first, you have to specify the query name and arguments; and then,
-2. you have to supply query providers where needed.
-
-To specify the query name and arguments, you simply add an entry
-to the big macro invocation in `mod.rs`. This will probably have changed
-by the time you read this README, but at present it looks something
-like:
-
-```
-define_queries! { <'tcx>
-    /// Records the type of every item.
-    [] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
-
-    ...
-}
-```
-
-Each line of the macro defines one query. The name is broken up like this:
-
-```
-[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
-^^    ^^^^^^^  ^^^^^^^^^^ ^^^^^     ^^^^^^^^
-|     |        |          |         |
-|     |        |          |         result type of query
-|     |        |          query key type
-|     |        dep-node constructor
-|     name of query
-query flags
-```
-
-Let's go over them one by one:
-
-- **Query flags:** these are largely unused right now, but the intention
-  is that we'll be able to customize various aspects of how the query is
-  processed.
-- **Name of query:** the name of the query method
-  (`tcx.type_of(..)`). Also used as the name of a struct
-  (`ty::query::queries::type_of`) that will be generated to represent
-  this query.
-- **Dep-node constructor:** indicates the constructor function that
-  connects this query to incremental compilation. Typically, this is a
-  `DepNode` variant, which can be added by modifying the
-  `define_dep_nodes!` macro invocation in
-  `librustc/dep_graph/dep_node.rs`.
-  - However, sometimes we use a custom function, in which case the
-    name will be in snake case and the function will be defined at the
-    bottom of the file. This is typically used when the query key is
-    not a def-id, or just not the type that the dep-node expects.
-- **Query key type:** the type of the argument to this query.
-  This type must implement the `ty::query::keys::Key` trait, which
-  defines (for example) how to map it to a crate, and so forth.
-- **Result type of query:** the type produced by this query. This type
-  should (a) not use `RefCell` or other interior mutability and (b) be
-  cheaply cloneable. Interning or using `Rc` or `Arc` is recommended for
-  non-trivial data types.
-  - The one exception to those rules is the `ty::steal::Steal` type,
-    which is used to cheaply modify MIR in place. See the definition
-    of `Steal` for more details. New uses of `Steal` should **not** be
-    added without alerting `@rust-lang/compiler`.
-
-So, to add a query:
-
-- Add an entry to `define_queries!` using the format above.
-- Possibly add a corresponding entry to the dep-node macro.
-- Link the provider by modifying the appropriate `provide` method;
-  or add a new one if needed and ensure that `rustc_driver` is invoking it.
-
-#### Query structs and descriptions
-
-For each kind, the `define_queries` macro will generate a "query struct"
-named after the query. This struct is a kind of a place-holder
-describing the query. Each such struct implements the
-`self::config::QueryConfig` trait, which has associated types for the
-key/value of that particular query. Basically the code generated looks something
-like this:
-
-```rust
-// Dummy struct representing a particular kind of query:
-pub struct type_of<'tcx> { phantom: PhantomData<&'tcx ()> }
-
-impl<'tcx> QueryConfig for type_of<'tcx> {
-  type Key = DefId;
-  type Value = Ty<'tcx>;
-}
-```
-
-There is an additional trait that you may wish to implement called
-`self::config::QueryDescription`. This trait is used during cycle
-errors to give a "human readable" name for the query, so that we can
-summarize what was happening when the cycle occurred. Implementing
-this trait is optional if the query key is `DefId`, but if you *don't*
-implement it, you get a pretty generic error ("processing `foo`...").
-You can put new impls into the `config` module. They look something like this:
-
-```rust
-impl<'tcx> QueryDescription for queries::type_of<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: DefId) -> String {
-        format!("computing the type of `{}`", tcx.item_path_str(key))
-    }
-}
-```
+For more information about how the query system works, see the [rustc guide].
 
+[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
index e989ef823e979ea9c1bd09ef049ef9f49b1fb8c6..75fc0f716a2f6424319dc91d720bd0f3354a9a87 100644 (file)
@@ -526,6 +526,15 @@ pub fn is_trait(self, def_id: DefId) -> bool {
         }
     }
 
+    /// True if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`).
+    pub fn is_trait_alias(self, def_id: DefId) -> bool {
+        if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data {
+            true
+        } else {
+            false
+        }
+    }
+
     /// True if this def-id refers to the implicit constructor for
     /// a tuple struct like `struct Foo(u32)`.
     pub fn is_struct_constructor(self, def_id: DefId) -> bool {
index 04e571863d42f8f3142fc98e17f8b1a83d07c783..51e9192cd290d107d0f7d1f1ab12c2469b8f04a1 100644 (file)
@@ -409,6 +409,7 @@ fn parameterized<F: fmt::Write>(&mut self,
                     DefPathData::AssocTypeInImpl(_) |
                     DefPathData::AssocExistentialInImpl(_) |
                     DefPathData::Trait(_) |
+                    DefPathData::TraitAlias(_) |
                     DefPathData::Impl |
                     DefPathData::TypeNs(_) => {
                         break;
index 14e0381dad1a40cc1bb74bb88debb9b9a66802b4..8bdc4e1d5c1ea888338681a7d92f7a47d2851595 100644 (file)
@@ -5,7 +5,6 @@
 #![allow(non_camel_case_types)]
 
 #![feature(nll)]
-#![feature(quote)]
 
 #![recursion_limit="256"]
 
index 6deedd0b5ea33c38e28b1fd582b4393bce3a78b5..9f63038c3623bfc06fe7572632e9516b54df02fa 100644 (file)
@@ -1164,7 +1164,10 @@ fn use_enum_fallback(cx: &CodegenCx) -> bool {
     // On MSVC we have to use the fallback mode, because LLVM doesn't
     // lower variant parts to PDB.
     return cx.sess().target.target.options.is_like_msvc
-        || llvm_util::get_major_version() < 7;
+        // LLVM version 7 did not release with an important bug fix;
+        // but the required patch is in the LLVM 8.  Rust LLVM reports
+        // 8 as well.
+        || llvm_util::get_major_version() < 8;
 }
 
 // Describes the members of an enum value: An enum is described as a union of
index eeb6a64164e9ce2e7133d9e91a759091beb8e22a..201b1684fb9b20fe692c4b276ff6edc07a4f9f49 100644 (file)
@@ -1167,6 +1167,52 @@ macro_rules! require_simd {
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
+    if name == "simd_bitmask" {
+        // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
+        // vector mask and returns an unsigned integer containing the most
+        // significant bit (MSB) of each lane.
+        use rustc_target::abi::HasDataLayout;
+
+        // If the vector has less than 8 lanes, an u8 is returned with zeroed
+        // trailing bits.
+        let expected_int_bits = in_len.max(8);
+        match ret_ty.sty {
+           ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (),
+            _ => return_error!(
+                "bitmask `{}`, expected `u{}`",
+                ret_ty, expected_int_bits
+            ),
+        }
+
+        // Integer vector <i{in_bitwidth} x in_len>:
+        let (i_xn, in_elem_bitwidth) = match in_elem.sty {
+            ty::Int(i) => (
+                args[0].immediate(),
+                i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits() as _)
+            ),
+            ty::Uint(i) => (
+                args[0].immediate(),
+                i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits() as _)
+            ),
+            _ => return_error!(
+                "vector argument `{}`'s element type `{}`, expected integer element type",
+                in_ty, in_elem
+            ),
+        };
+
+        // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
+        let shift_indices = vec![
+            bx.cx.const_int(bx.type_ix(in_elem_bitwidth as _), (in_elem_bitwidth - 1) as _); in_len
+        ];
+        let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice()));
+        // Truncate vector to an <i1 x N>
+        let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len as _));
+        // Bitcast <i1 x N> to iN:
+        let i_ = bx.bitcast(i1xn, bx.type_ix(in_len as _));
+        // Zero-extend iN to the bitmask type:
+        return Ok(bx.zext(i_, bx.type_ix(expected_int_bits as _)));
+    }
+
     fn simd_simple_float_intrinsic(
         name: &str,
         in_elem: &::rustc::ty::TyS,
index 272f34b0b3f16515ed40347312cd31e34f465983..a88b1a8f52e96a9a9d89c7d417b19cf135b8cd71 100644 (file)
@@ -17,7 +17,6 @@
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(nll)]
-#![feature(quote)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
index 97128c2d2a2ce519ab709d49a7a87ce4b2f38bd7..afaeb352cd9926fbcf90f85cf403f64ec15e9e77 100644 (file)
@@ -55,7 +55,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::Str => {
             let mut name = String::with_capacity(32);
             let printer = DefPathBasedNames::new(cx.tcx, true, true);
-            printer.push_type_name(layout.ty, &mut name);
+            printer.push_type_name(layout.ty, &mut name, false);
             if let (&ty::Adt(def, _), &layout::Variants::Single { index })
                  = (&layout.ty.sty, &layout.variants)
             {
index 06d4f940436da82fd0e545cc950815461782dc12..ad61f8f01d8d416692f70e678474e2b0ab15ce07 100644 (file)
@@ -911,9 +911,6 @@ fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a>
         // For now we just never have an entry symbol
         cmd.arg("--no-entry");
 
-        // Make the default table accessible
-        cmd.arg("--export-table");
-
         // Rust code should never have warnings, and warnings are often
         // indicative of bugs, let's prevent them.
         cmd.arg("--fatal-warnings");
index d47bd23766f690f7d7ff09c7b6289900029c0ca1..1accbeb2aa822d2af3cd8ba1cc5adb018a18507c 100644 (file)
@@ -12,7 +12,6 @@
 #![feature(nll)]
 #![allow(unused_attributes)]
 #![allow(dead_code)]
-#![feature(quote)]
 
 #![recursion_limit="256"]
 
index e6d6ef1d7a38b35aebb87984e7b6410381eefe14..56d4342e6e1618094c8f74575996db1f38002339 100644 (file)
@@ -59,7 +59,6 @@ pub fn simd_shuffle_indices(
                     let field = const_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
-                        self.instance,
                         None,
                         mir::Field::new(field as usize),
                         c,
index 21e0044759a5abe359be777df9903e633556df82..8488ab2ae862f7f8970aee4d73f0f05a8d502edf 100644 (file)
@@ -13,7 +13,7 @@
 pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
         debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
-               self.to_string(cx.tcx()),
+               self.to_string(cx.tcx(), true),
                self.to_raw_string(),
                cx.codegen_unit().name());
 
@@ -45,7 +45,7 @@ fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
         }
 
         debug!("END IMPLEMENTING '{} ({})' in cgu {}",
-               self.to_string(cx.tcx()),
+               self.to_string(cx.tcx(), true),
                self.to_raw_string(),
                cx.codegen_unit().name());
     }
@@ -57,7 +57,7 @@ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
         visibility: Visibility
     ) {
         debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
-               self.to_string(cx.tcx()),
+               self.to_string(cx.tcx(), true),
                self.to_raw_string(),
                cx.codegen_unit().name());
 
@@ -76,7 +76,7 @@ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
         }
 
         debug!("END PREDEFINING '{} ({})' in cgu {}",
-               self.to_string(cx.tcx()),
+               self.to_string(cx.tcx(), true),
                self.to_raw_string(),
                cx.codegen_unit().name());
     }
index 5f61852178d0f0c8e9d836b5088e4777727e475c..1f590d46ed8c657bb18b48b173ce8c2b06a75366 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(custom_attribute)]
 #![feature(nll)]
 #![allow(unused_attributes)]
-#![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
diff --git a/src/librustc_data_structures/obligation_forest/README.md b/src/librustc_data_structures/obligation_forest/README.md
deleted file mode 100644 (file)
index 982a2ba..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-The `ObligationForest` is a utility data structure used in trait
-matching to track the set of outstanding obligations (those not yet
-resolved to success or error). It also tracks the "backtrace" of each
-pending obligation (why we are trying to figure this out in the first
-place).
-
-### External view
-
-`ObligationForest` supports two main public operations (there are a
-few others not discussed here):
-
-1. Add a new root obligations (`push_tree`).
-2. Process the pending obligations (`process_obligations`).
-
-When a new obligation `N` is added, it becomes the root of an
-obligation tree. This tree can also carry some per-tree state `T`,
-which is given at the same time. This tree is a singleton to start, so
-`N` is both the root and the only leaf. Each time the
-`process_obligations` method is called, it will invoke its callback
-with every pending obligation (so that will include `N`, the first
-time). The callback also receives a (mutable) reference to the
-per-tree state `T`. The callback should process the obligation `O`
-that it is given and return one of three results:
-
-- `Ok(None)` -> ambiguous result. Obligation was neither a success
-  nor a failure. It is assumed that further attempts to process the
-  obligation will yield the same result unless something in the
-  surrounding environment changes.
-- `Ok(Some(C))` - the obligation was *shallowly successful*. The
-  vector `C` is a list of subobligations. The meaning of this is that
-  `O` was successful on the assumption that all the obligations in `C`
-  are also successful. Therefore, `O` is only considered a "true"
-  success if `C` is empty. Otherwise, `O` is put into a suspended
-  state and the obligations in `C` become the new pending
-  obligations. They will be processed the next time you call
-  `process_obligations`.
-- `Err(E)` -> obligation failed with error `E`. We will collect this
-  error and return it from `process_obligations`, along with the
-  "backtrace" of obligations (that is, the list of obligations up to
-  and including the root of the failed obligation). No further
-  obligations from that same tree will be processed, since the tree is
-  now considered to be in error.
-
-When the call to `process_obligations` completes, you get back an `Outcome`,
-which includes three bits of information:
-
-- `completed`: a list of obligations where processing was fully
-  completed without error (meaning that all transitive subobligations
-  have also been completed). So, for example, if the callback from
-  `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
-  then `O` will be considered completed right away if `C` is the
-  empty vector. Otherwise it will only be considered completed once
-  all the obligations in `C` have been found completed.
-- `errors`: a list of errors that occurred and associated backtraces
-  at the time of error, which can be used to give context to the user.
-- `stalled`: if true, then none of the existing obligations were
-  *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
-  This implies that all obligations were either errors or returned an
-  ambiguous result, which means that any further calls to
-  `process_obligations` would simply yield back further ambiguous
-  results. This is used by the `FulfillmentContext` to decide when it
-  has reached a steady state.
-
-#### Snapshots
-
-The `ObligationForest` supports a limited form of snapshots; see
-`start_snapshot`; `commit_snapshot`; and `rollback_snapshot`. In
-particular, you can use a snapshot to roll back new root
-obligations. However, it is an error to attempt to
-`process_obligations` during a snapshot.
-
-### Implementation details
-
-For the most part, comments specific to the implementation are in the
-code.  This file only contains a very high-level overview. Basically,
-the forest is stored in a vector. Each element of the vector is a node
-in some tree. Each node in the vector has the index of an (optional)
-parent and (for convenience) its root (which may be itself). It also
-has a current state, described by `NodeState`. After each
-processing step, we compress the vector to remove completed and error
-nodes, which aren't needed anymore.
index 59497f0df18e9c593c984e31b8102039b2f46fec..9dd7d204f0373d5ccea71f87c629a3d33b5f6176 100644 (file)
@@ -1,9 +1,84 @@
 //! The `ObligationForest` is a utility data structure used in trait
-//! matching to track the set of outstanding obligations (those not
-//! yet resolved to success or error). It also tracks the "backtrace"
-//! of each pending obligation (why we are trying to figure this out
-//! in the first place). See README.md for a general overview of how
-//! to use this class.
+//! matching to track the set of outstanding obligations (those not yet
+//! resolved to success or error). It also tracks the "backtrace" of each
+//! pending obligation (why we are trying to figure this out in the first
+//! place).
+//!
+//! ### External view
+//!
+//! `ObligationForest` supports two main public operations (there are a
+//! few others not discussed here):
+//!
+//! 1. Add a new root obligations (`push_tree`).
+//! 2. Process the pending obligations (`process_obligations`).
+//!
+//! When a new obligation `N` is added, it becomes the root of an
+//! obligation tree. This tree can also carry some per-tree state `T`,
+//! which is given at the same time. This tree is a singleton to start, so
+//! `N` is both the root and the only leaf. Each time the
+//! `process_obligations` method is called, it will invoke its callback
+//! with every pending obligation (so that will include `N`, the first
+//! time). The callback also receives a (mutable) reference to the
+//! per-tree state `T`. The callback should process the obligation `O`
+//! that it is given and return one of three results:
+//!
+//! - `Ok(None)` -> ambiguous result. Obligation was neither a success
+//!   nor a failure. It is assumed that further attempts to process the
+//!   obligation will yield the same result unless something in the
+//!   surrounding environment changes.
+//! - `Ok(Some(C))` - the obligation was *shallowly successful*. The
+//!   vector `C` is a list of subobligations. The meaning of this is that
+//!   `O` was successful on the assumption that all the obligations in `C`
+//!   are also successful. Therefore, `O` is only considered a "true"
+//!   success if `C` is empty. Otherwise, `O` is put into a suspended
+//!   state and the obligations in `C` become the new pending
+//!   obligations. They will be processed the next time you call
+//!   `process_obligations`.
+//! - `Err(E)` -> obligation failed with error `E`. We will collect this
+//!   error and return it from `process_obligations`, along with the
+//!   "backtrace" of obligations (that is, the list of obligations up to
+//!   and including the root of the failed obligation). No further
+//!   obligations from that same tree will be processed, since the tree is
+//!   now considered to be in error.
+//!
+//! When the call to `process_obligations` completes, you get back an `Outcome`,
+//! which includes three bits of information:
+//!
+//! - `completed`: a list of obligations where processing was fully
+//!   completed without error (meaning that all transitive subobligations
+//!   have also been completed). So, for example, if the callback from
+//!   `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
+//!   then `O` will be considered completed right away if `C` is the
+//!   empty vector. Otherwise it will only be considered completed once
+//!   all the obligations in `C` have been found completed.
+//! - `errors`: a list of errors that occurred and associated backtraces
+//!   at the time of error, which can be used to give context to the user.
+//! - `stalled`: if true, then none of the existing obligations were
+//!   *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
+//!   This implies that all obligations were either errors or returned an
+//!   ambiguous result, which means that any further calls to
+//!   `process_obligations` would simply yield back further ambiguous
+//!   results. This is used by the `FulfillmentContext` to decide when it
+//!   has reached a steady state.
+//!
+//! #### Snapshots
+//!
+//! The `ObligationForest` supports a limited form of snapshots; see
+//! `start_snapshot`; `commit_snapshot`; and `rollback_snapshot`. In
+//! particular, you can use a snapshot to roll back new root
+//! obligations. However, it is an error to attempt to
+//! `process_obligations` during a snapshot.
+//!
+//! ### Implementation details
+//!
+//! For the most part, comments specific to the implementation are in the
+//! code.  This file only contains a very high-level overview. Basically,
+//! the forest is stored in a vector. Each element of the vector is a node
+//! in some tree. Each node in the vector has the index of an (optional)
+//! parent and (for convenience) its root (which may be itself). It also
+//! has a current state, described by `NodeState`. After each
+//! processing step, we compress the vector to remove completed and error
+//! nodes, which aren't needed anymore.
 
 use fx::{FxHashMap, FxHashSet};
 
index d23d8b829c0c057c8746a8867c32725015cbfce7..142d60c8d00b290bc1222c2794af7a60e81849a6 100644 (file)
@@ -916,7 +916,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
         crate_loader,
         &resolver_arenas,
     );
-    syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote);
+    syntax_ext::register_builtins(&mut resolver, syntax_exts);
 
     // Expand all macros
     sess.profiler(|p| p.start_activity(ProfileCategory::Expansion));
index c8a5bbe8315b376f56a7b16a4c27b29d9f57f9a6..abcdf175ada996c73e3175480d36c20f38b78f41 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(box_syntax)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(nll)]
-#![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(set_stdio)]
index d1108304d11d9a02a600eb7b4b51cb317b5d8f42..d980c5a3d29c3e77f58bb8f0c72d198650c02587 100644 (file)
@@ -123,7 +123,8 @@ pub fn parse_pretty(sess: &Session,
                 sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \
                                      `expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
                                      `identified`, `expanded,identified`, `everybody_loops`, \
-                                     `hir`, `hir,identified`, `hir,typed`, or `mir`; got {}",
+                                     `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
+                                     `mir` or `mir-cfg`; got {}",
                                     name));
             } else {
                 sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \
index 7449b2b758302f4228024ee31072fd2a42d5376f..736cca6bd64af3b6399623e4b054e4b333bff7aa 100644 (file)
@@ -33,7 +33,11 @@ pub struct DiagnosticBuilder<'a> {
 /// it easy to declare such methods on the builder.
 macro_rules! forward {
     // Forward pattern for &self -> &Self
-    (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n(&self, $($name: $ty),*) -> &Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -42,7 +46,11 @@ pub fn $n(&self, $($name: $ty),*) -> &Self {
     };
 
     // Forward pattern for &mut self -> &mut Self
-    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -52,10 +60,15 @@ pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
 
     // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
     // type parameter. No obvious way to make this more generic.
-    (pub fn $n:ident<S: Into<MultiSpan>>(
-                    &mut self,
-                    $($name:ident: $ty:ty),*
-                    $(,)*) -> &mut Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident<S: Into<MultiSpan>>(
+            &mut self,
+            $($name:ident: $ty:ty),*
+            $(,)*
+        ) -> &mut Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -177,34 +190,43 @@ pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self
                                                   msg: &str,
                                                   ) -> &mut Self);
 
-    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
-    forward!(pub fn span_suggestion_short(
-                                      &mut self,
-                                      sp: Span,
-                                      msg: &str,
-                                      suggestion: String,
-                                      ) -> &mut Self);
-
-    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
-    forward!(pub fn multipart_suggestion(
-        &mut self,
-        msg: &str,
-        suggestion: Vec<(Span, String)>,
-    ) -> &mut Self);
-
-    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
-    forward!(pub fn span_suggestion(&mut self,
-                                    sp: Span,
-                                    msg: &str,
-                                    suggestion: String,
-                                    ) -> &mut Self);
-
-    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
-    forward!(pub fn span_suggestions(&mut self,
-                                     sp: Span,
-                                     msg: &str,
-                                     suggestions: Vec<String>,
-                                     ) -> &mut Self);
+    forward!(
+        #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+        pub fn span_suggestion_short(
+            &mut self,
+            sp: Span,
+            msg: &str,
+            suggestion: String,
+        ) -> &mut Self
+    );
+
+    forward!(
+        #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
+        pub fn multipart_suggestion(
+            &mut self,
+            msg: &str,
+            suggestion: Vec<(Span, String)>,
+        ) -> &mut Self
+    );
+
+    forward!(
+        #[deprecated(note = "Use `span_suggestion_with_applicability`")]
+        pub fn span_suggestion(
+            &mut self,
+            sp: Span,
+            msg: &str,
+            suggestion: String,
+        ) -> &mut Self
+    );
+
+    forward!(
+        #[deprecated(note = "Use `span_suggestions_with_applicability`")]
+        pub fn span_suggestions(&mut self,
+            sp: Span,
+            msg: &str,
+            suggestions: Vec<String>,
+        ) -> &mut Self
+    );
 
     pub fn multipart_suggestion_with_applicability(&mut self,
                                               msg: &str,
index 0443b2228e5b4fcaef05407e95b7483bd6951d3b..25d09a33c154fad930b780a341540568bbb3ea97 100644 (file)
@@ -959,7 +959,7 @@ fn emit_message_default(&mut self,
             Style::MainHeaderMsg
         };
 
-        if msp.primary_spans().is_empty() && msp.span_labels().is_empty() && is_secondary
+        if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary
            && !self.short_message {
             // This is a secondary message with no span info
             for _ in 0..max_line_num_len {
index f895542e43adac2e8768ea9b3f996f8b6f9829c1..f6c381ff74cc9e42d7db24193bf8a31772d56df8 100644 (file)
@@ -1474,7 +1474,7 @@ fn check_tokens(&mut self, cx: &EarlyContext, tokens: TokenStream) {
                     _ => {},
                 }
                 TokenTree::Delimited(_, _, tts) => {
-                    self.check_tokens(cx, tts.stream())
+                    self.check_tokens(cx, tts)
                 },
             }
         }
index 71c859d8dbea71fb489d0ff3364c607d1b639f83..d3d17184a01815527f1dc632d4b193ca20d49cb5 100644 (file)
@@ -17,7 +17,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(nll)]
-#![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
index bc29020e79f2a380322734ce36e18e16f09b3c50..8a68f1bb9d085e8512ee9a38708ba1da70457376 100644 (file)
@@ -41,7 +41,7 @@ fn get_lints(&self) -> LintArray {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         let expr = match s.node {
-            hir::StmtKind::Semi(ref expr, _) => &**expr,
+            hir::StmtKind::Semi(ref expr) => &**expr,
             _ => return,
         };
 
@@ -205,7 +205,7 @@ fn get_lints(&self) -> LintArray {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
-        if let hir::StmtKind::Semi(ref expr, _) = s.node {
+        if let hir::StmtKind::Semi(ref expr) = s.node {
             if let hir::ExprKind::Path(_) = expr.node {
                 cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect");
             }
index dc8db5be5820ab4024778b5c224cc07ad3f49bfc..ad6296e1a3bd863d96b097e8e1c23f3f93e382f5 100644 (file)
@@ -418,6 +418,7 @@ fn to_def(&self, did: DefId) -> Option<Def> {
             EntryKind::Mod(_) => Def::Mod(did),
             EntryKind::Variant(_) => Def::Variant(did),
             EntryKind::Trait(_) => Def::Trait(did),
+            EntryKind::TraitAlias(_) => Def::TraitAlias(did),
             EntryKind::Enum(..) => Def::Enum(did),
             EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
             EntryKind::ForeignType => Def::ForeignTy(did),
@@ -520,17 +521,26 @@ pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
     }
 
     pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
-        let data = match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode((self, sess)),
-            _ => bug!(),
-        };
-
-        ty::TraitDef::new(self.local_def_id(item_id),
-                          data.unsafety,
-                          data.paren_sugar,
-                          data.has_auto_impl,
-                          data.is_marker,
-                          self.def_path_table.def_path_hash(item_id))
+        match self.entry(item_id).kind {
+            EntryKind::Trait(data) => {
+                let data = data.decode((self, sess));
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  data.unsafety,
+                                  data.paren_sugar,
+                                  data.has_auto_impl,
+                                  data.is_marker,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            EntryKind::TraitAlias(_) => {
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  hir::Unsafety::Normal,
+                                  false,
+                                  false,
+                                  false,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        }
     }
 
     fn get_variant(&self,
@@ -615,10 +625,13 @@ pub fn get_super_predicates(&self,
                                 item_id: DefIndex,
                                 tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                 -> ty::GenericPredicates<'tcx> {
-        match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
-            _ => bug!(),
-        }
+        let super_predicates = match self.entry(item_id).kind {
+            EntryKind::Trait(data) => data.decode(self).super_predicates,
+            EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        };
+
+        super_predicates.decode((self, tcx))
     }
 
     pub fn get_generics(&self,
@@ -880,6 +893,9 @@ pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
             EntryKind::AssociatedType(container) => {
                 (ty::AssociatedKind::Type, container, false)
             }
+            EntryKind::AssociatedExistential(container) => {
+                (ty::AssociatedKind::Existential, container, false)
+            }
             _ => bug!("cannot get associated-item of `{:?}`", def_key)
         };
 
@@ -1014,7 +1030,8 @@ pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
         }
         def_key.parent.and_then(|parent_index| {
             match self.entry(parent_index).kind {
-                EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
+                EntryKind::Trait(_) |
+                EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
                 _ => None,
             }
         })
index 2de1637fb0d9d11e24e47757a8305d6f3d975af8..afb0218501d1877481f3a0e1b0e51a7c646b2e16 100644 (file)
@@ -1128,8 +1128,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
 
                 EntryKind::Impl(self.lazy(&data))
             }
-            hir::ItemKind::Trait(..) |
-            hir::ItemKind::TraitAlias(..) => {
+            hir::ItemKind::Trait(..) => {
                 let trait_def = tcx.trait_def(def_id);
                 let data = TraitData {
                     unsafety: trait_def.unsafety,
@@ -1141,6 +1140,13 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
 
                 EntryKind::Trait(self.lazy(&data))
             }
+            hir::ItemKind::TraitAlias(..) => {
+                let data = TraitAliasData {
+                    super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
+                };
+
+                EntryKind::TraitAlias(self.lazy(&data))
+            }
             hir::ItemKind::ExternCrate(_) |
             hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
         };
@@ -1214,6 +1220,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemKind::Impl(..) |
                 hir::ItemKind::Existential(..) |
                 hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)),
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)),
                 _ => None,
             },
             predicates: match item.node {
@@ -1226,7 +1233,8 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemKind::Union(..) |
                 hir::ItemKind::Impl(..) |
                 hir::ItemKind::Existential(..) |
-                hir::ItemKind::Trait(..) => Some(self.encode_predicates(def_id)),
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)),
                 _ => None,
             },
 
@@ -1236,7 +1244,8 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             // hack. (No reason not to expand it in the future if
             // necessary.)
             predicates_defined_on: match item.node {
-                hir::ItemKind::Trait(..) => Some(self.encode_predicates_defined_on(def_id)),
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)),
                 _ => None, // not *wrong* for other kinds of items, but not needed
             },
 
index d38562c93f804df0ea25925c7a818fa0f91a0756..1a6614212407d4b5ffd7e3441832a0048623f484 100644 (file)
@@ -7,7 +7,6 @@
 #![feature(nll)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
-#![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(crate_visibility_modifier)]
index 25f499bc319844af00df70fb9e40655175f248db..f3ff9747625f5b68724701049c5f6a660f347869 100644 (file)
@@ -316,6 +316,7 @@ pub enum EntryKind<'tcx> {
     AssociatedType(AssociatedContainer),
     AssociatedExistential(AssociatedContainer),
     AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
+    TraitAlias(Lazy<TraitAliasData<'tcx>>),
 }
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
@@ -370,6 +371,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             EntryKind::Trait(ref trait_data) => {
                 trait_data.hash_stable(hcx, hasher);
             }
+            EntryKind::TraitAlias(ref trait_alias_data) => {
+                trait_alias_data.hash_stable(hcx, hasher);
+            }
             EntryKind::Impl(ref impl_data) => {
                 impl_data.hash_stable(hcx, hasher);
             }
@@ -474,6 +478,15 @@ pub struct TraitData<'tcx> {
     super_predicates
 });
 
+#[derive(RustcEncodable, RustcDecodable)]
+pub struct TraitAliasData<'tcx> {
+    pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
+}
+
+impl_stable_hash_for!(struct TraitAliasData<'tcx> {
+    super_predicates
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
index 233db12b03001967b728223f2759258cf51d80c9..56b87feb82b2c34f2ce9bf93e14fe72489960f47 100644 (file)
@@ -198,19 +198,38 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 let place = &self.move_data.move_paths[mpi].place;
 
                 let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
-                let note_msg = match self.describe_place_with_options(
-                    place,
-                    IncludingDowncast(true),
-                ) {
-                    Some(name) => format!("`{}`", name),
+                let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
+                let note_msg = match opt_name {
+                    Some(ref name) => format!("`{}`", name),
                     None => "value".to_owned(),
                 };
-
-                err.note(&format!(
-                    "move occurs because {} has type `{}`, \
-                     which does not implement the `Copy` trait",
-                    note_msg, ty
-                ));
+                if let ty::TyKind::Param(param_ty) = ty.sty {
+                    let tcx = self.infcx.tcx;
+                    let generics = tcx.generics_of(self.mir_def_id);
+                    let def_id = generics.type_param(&param_ty, tcx).def_id;
+                    if let Some(sp) = tcx.hir().span_if_local(def_id) {
+                        err.span_label(
+                            sp,
+                            "consider adding a `Copy` constraint to this type argument",
+                        );
+                    }
+                }
+                if let Place::Local(local) = place {
+                    let decl = &self.mir.local_decls[*local];
+                    err.span_label(
+                        decl.source_info.span,
+                        format!(
+                            "move occurs because {} has type `{}`, \
+                                which does not implement the `Copy` trait",
+                            note_msg, ty,
+                    ));
+                } else {
+                    err.note(&format!(
+                        "move occurs because {} has type `{}`, \
+                         which does not implement the `Copy` trait",
+                        note_msg, ty
+                    ));
+                }
             }
 
             if let Some((_, mut old_err)) = self.move_error_reported
index 45632245b61de3f6f0d981a5fe7aae82d83d4c7f..9d49814c35a348056eee8f1e0aedc6bccc8ff688 100644 (file)
@@ -163,10 +163,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
 
-    let locals_are_invalidated_at_exit = match tcx.hir().body_owner_kind(id) {
-            hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
-            hir::BodyOwnerKind::Fn => true,
-    };
+    let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
     let borrow_set = Rc::new(BorrowSet::build(
             tcx, mir, locals_are_invalidated_at_exit, &mdpe.move_data));
 
index c63d45ce1d272798634030b4b9cadde51ecf726d..0a214e60bdd78a8f8d6641266c26acc688936c24 100644 (file)
@@ -476,6 +476,7 @@ fn defining_ty(&self) -> DefiningTy<'tcx> {
         let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
 
         match tcx.hir().body_owner_kind(self.mir_node_id) {
+            BodyOwnerKind::Closure |
             BodyOwnerKind::Fn => {
                 let defining_ty = if self.mir_def_id == closure_base_def_id {
                     tcx.type_of(closure_base_def_id)
index 2bf2824d835cc83564d9b65e54143ccb403faa6d..420ae113ad33026036c151c99fec21524a9fd6ed 100644 (file)
@@ -75,7 +75,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
         let cx = Cx::new(&infcx, id);
         let mut mir = if cx.tables().tainted_by_errors {
             build::construct_error(cx, body_id)
-        } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind {
+        } else if cx.body_owner_kind.is_fn_or_closure() {
             // fetch the fully liberated fn signature (that is, all bound
             // types/lifetimes replaced)
             let fn_hir_id = tcx.hir().node_to_hir_id(id);
index b44c2cc9c166ac5d2b1801f1807eb45203810cbb..78abba5f885b2e94882cd8f3f2785d0a7781e445 100644 (file)
@@ -613,6 +613,7 @@ pub fn local_scope(&self) -> Option<region::Scope> {
             hir::BodyOwnerKind::Static(_) =>
                 // No need to free storage in this context.
                 None,
+            hir::BodyOwnerKind::Closure |
             hir::BodyOwnerKind::Fn =>
                 Some(self.topmost_scope()),
         }
index f5f40481679385eae8372f11e161f48ae8132ccb..45c6c1b42496a052038d0758575bb509b2365c5c 100644 (file)
 use rustc::hir::def::Def;
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
 use rustc::mir;
-use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
+use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
 use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
 use rustc::ty::subst::Subst;
 use rustc::traits::Reveal;
-use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
 use rustc::util::common::ErrorReported;
 
 /// Should be a power of two for performance reasons.
 const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
 
-/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
-/// The `EvalContext` is only meant to be used to query values from constants and statics.
-///
-/// This function is used during const propagation. We cannot use `mk_eval_cx`, because copy
-/// propagation happens *during* the computation of the MIR of the current function. So if we
-/// tried to call the `optimized_mir` query, we'd get a cycle error because we are (transitively)
-/// inside the `optimized_mir` query of the `Instance` given.
-///
-/// Since we are looking at the MIR of the function in an abstract manner, we don't have a
-/// `ParamEnv` available to us. This function creates a `ParamEnv` for the given instance.
-pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
-    span: Span,
-) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
-    debug!("mk_borrowck_eval_cx: {:?}", instance);
-    let param_env = tcx.param_env(instance.def_id());
-    mk_eval_cx_inner(tcx, instance, mir, span, param_env)
-}
-
-/// This is just a helper function to reduce code duplication between `mk_borrowck_eval_cx` and
-/// `mk_eval_cx`. Do not call this function directly.
-fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
-    span: Span,
-    param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
-    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
-    // Insert a stack frame so any queries have the correct substs.
-    // We also avoid all the extra work performed by push_stack_frame,
-    // like initializing local variables
-    ecx.stack.push(interpret::Frame {
-        block: mir::START_BLOCK,
-        locals: IndexVec::new(),
-        instance,
-        span,
-        mir,
-        return_place: None,
-        return_to_block: StackPopCleanup::Goto(None), // never pop
-        stmt: 0,
-        extra: (),
-    });
-    Ok(ecx)
-}
-
-/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
 /// The `EvalContext` is only meant to be used to do field and index projections into constants for
 /// `simd_shuffle` and const patterns in match arms.
 ///
@@ -91,15 +41,13 @@ fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
 /// that inform us about the generic bounds of the constant. E.g. using an associated constant
 /// of a function's generic parameter will require knowledge about the bounds on the generic
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
-fn mk_eval_cx<'a, 'tcx>(
+pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
+    span: Span,
     param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
-    debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
-    let span = tcx.def_span(instance.def_id());
-    let mir = tcx.optimized_mir(instance.def.def_id());
-    mk_eval_cx_inner(tcx, instance, mir, span, param_env)
+) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
+    debug!("mk_eval_cx: {:?}", param_env);
+    EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
 }
 
 pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
@@ -108,7 +56,8 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
-    let mut ecx = mk_borrowck_eval_cx(tcx, cid.instance, mir, DUMMY_SP).unwrap();
+    let span = tcx.def_span(cid.instance.def_id());
+    let mut ecx = mk_eval_cx(tcx, span, param_env);
     eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
 }
 
@@ -529,13 +478,12 @@ fn stack_pop(
 pub fn const_field<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    instance: ty::Instance<'tcx>,
     variant: Option<VariantIdx>,
     field: mir::Field,
     value: ty::Const<'tcx>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
-    trace!("const_field: {:?}, {:?}, {:?}", instance, field, value);
-    let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    trace!("const_field: {:?}, {:?}", field, value);
+    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
     let result = (|| {
         // get the operand again
         let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?;
@@ -560,11 +508,10 @@ pub fn const_field<'a, 'tcx>(
 pub fn const_variant_index<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    instance: ty::Instance<'tcx>,
     val: ty::Const<'tcx>,
 ) -> EvalResult<'tcx, VariantIdx> {
-    trace!("const_variant_index: {:?}, {:?}", instance, val);
-    let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    trace!("const_variant_index: {:?}", val);
+    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
     let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?;
     Ok(ecx.read_discriminant(op)?.1)
 }
@@ -584,7 +531,7 @@ fn validate_and_turn_into_const<'a, 'tcx>(
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
     let cid = key.value;
-    let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
+    let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env);
     let val = (|| {
         let op = ecx.raw_const_to_mplace(constant)?.into();
         // FIXME: Once the visitor infrastructure landed, change validation to
index 37d741d2606d52630542cbd26703df1240634eb2..f63c3e2ff61420a4eba75b24a8fa2ae8c1266e42 100644 (file)
             let id = tcx.allocate_bytes(s.as_bytes());
             ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
         },
+        LitKind::Err(ref s) => {
+            let s = s.as_str();
+            let id = tcx.allocate_bytes(s.as_bytes());
+            return Ok(ty::Const {
+                val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx),
+                ty: tcx.types.err,
+            });
+        },
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_bytes(data);
             ConstValue::Scalar(Scalar::Ptr(id.into()))
index ea8b2826732b455c54e8dcd6023645641a080888..c50d9ddcb152e95a228817ef5fc7bfe54f4e7c96 100644 (file)
@@ -46,12 +46,12 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 -> Vec<StmtRef<'tcx>> {
     let mut result = vec![];
     for (index, stmt) in stmts.iter().enumerate() {
-        let hir_id = cx.tcx.hir().node_to_hir_id(stmt.node.id());
+        let hir_id = cx.tcx.hir().node_to_hir_id(stmt.id);
         let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
-        let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.node.id()));
+        let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.id));
         match stmt.node {
-            hir::StmtKind::Expr(ref expr, _) |
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Expr(ref expr) |
+            hir::StmtKind::Semi(ref expr) => {
                 result.push(StmtRef::Mirror(Box::new(Stmt {
                     kind: StmtKind::Expr {
                         scope: region::Scope {
@@ -64,52 +64,48 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     span: stmt_span,
                 })))
             }
-            hir::StmtKind::Decl(ref decl, _) => {
-                match decl.node {
-                    hir::DeclKind::Item(..) => {
-                        // ignore for purposes of the MIR
-                    }
-                    hir::DeclKind::Local(ref local) => {
-                        let remainder_scope = region::Scope {
-                            id: block_id,
-                            data: region::ScopeData::Remainder(
-                                region::FirstStatementIndex::new(index)),
-                        };
-
-                        let mut pattern = cx.pattern_from_hir(&local.pat);
+            hir::StmtKind::Item(..) => {
+                // ignore for purposes of the MIR
+            }
+            hir::StmtKind::Local(ref local) => {
+                let remainder_scope = region::Scope {
+                    id: block_id,
+                    data: region::ScopeData::Remainder(
+                        region::FirstStatementIndex::new(index)),
+                };
 
-                        if let Some(ty) = &local.ty {
-                            if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
-                                debug!("mirror_stmts: user_ty={:?}", user_ty);
-                                pattern = Pattern {
-                                    ty: pattern.ty,
-                                    span: pattern.span,
-                                    kind: Box::new(PatternKind::AscribeUserType {
-                                        user_ty: PatternTypeProjection::from_user_type(user_ty),
-                                        user_ty_span: ty.span,
-                                        subpattern: pattern,
-                                        variance: ty::Variance::Covariant,
-                                    })
-                                };
-                            }
-                        }
+                let mut pattern = cx.pattern_from_hir(&local.pat);
 
-                        result.push(StmtRef::Mirror(Box::new(Stmt {
-                            kind: StmtKind::Let {
-                                remainder_scope: remainder_scope,
-                                init_scope: region::Scope {
-                                    id: hir_id.local_id,
-                                    data: region::ScopeData::Node
-                                },
-                                pattern,
-                                initializer: local.init.to_ref(),
-                                lint_level: cx.lint_level_of(local.id),
-                            },
-                            opt_destruction_scope: opt_dxn_ext,
-                            span: stmt_span,
-                        })));
+                if let Some(ty) = &local.ty {
+                    if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
+                        debug!("mirror_stmts: user_ty={:?}", user_ty);
+                        pattern = Pattern {
+                            ty: pattern.ty,
+                            span: pattern.span,
+                            kind: Box::new(PatternKind::AscribeUserType {
+                                user_ty: PatternTypeProjection::from_user_type(user_ty),
+                                user_ty_span: ty.span,
+                                subpattern: pattern,
+                                variance: ty::Variance::Covariant,
+                            })
+                        };
                     }
                 }
+
+                result.push(StmtRef::Mirror(Box::new(Stmt {
+                    kind: StmtKind::Let {
+                        remainder_scope: remainder_scope,
+                        init_scope: region::Scope {
+                            id: hir_id.local_id,
+                            data: region::ScopeData::Node
+                        },
+                        pattern,
+                        initializer: local.init.to_ref(),
+                        lint_level: cx.lint_level_of(local.id),
+                    },
+                    opt_destruction_scope: opt_dxn_ext,
+                    span: stmt_span,
+                })));
             }
         }
     }
index 6113d88e09591a07c4cb4442f7e2d59347d94680..f514cac6326be317b2a2de11cede84ea73091003 100644 (file)
@@ -61,6 +61,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         let constness = match body_owner_kind {
             hir::BodyOwnerKind::Const |
             hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
+            hir::BodyOwnerKind::Closure |
             hir::BodyOwnerKind::Fn => hir::Constness::NotConst,
         };
 
index 188a1120442983dfba44c786cb5a4b6047a04590..9cc5c93de41d8e3f9c4f1091ccdfed769a6a6b5c 100644 (file)
@@ -427,13 +427,24 @@ pub enum Constructor<'tcx> {
 }
 
 impl<'tcx> Constructor<'tcx> {
-    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
+    fn variant_index_for_adt<'a>(
+        &self,
+        cx: &MatchCheckCtxt<'a, 'tcx>,
+        adt: &'tcx ty::AdtDef,
+    ) -> VariantIdx {
         match self {
             &Variant(vid) => adt.variant_index_with_id(vid),
             &Single => {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
             }
+            &ConstantValue(c) => {
+                ::const_eval::const_variant_index(
+                    cx.tcx,
+                    cx.param_env,
+                    c,
+                ).unwrap()
+            },
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt)
         }
     }
@@ -567,7 +578,7 @@ fn apply_constructor<'a>(
                             PatternKind::Variant {
                                 adt_def: adt,
                                 substs,
-                                variant_index: ctor.variant_index_for_adt(adt),
+                                variant_index: ctor.variant_index_for_adt(cx, adt),
                                 subpatterns: pats
                             }
                         } else {
@@ -1329,7 +1340,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
 ///
 /// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
 /// A struct pattern's arity is the number of fields it contains, etc.
-fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
+fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> u64 {
     debug!("constructor_arity({:#?}, {:?})", ctor, ty);
     match ty.sty {
         ty::Tuple(ref fs) => fs.len() as u64,
@@ -1340,7 +1351,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
         },
         ty::Ref(..) => 1,
         ty::Adt(adt, _) => {
-            adt.variants[ctor.variant_index_for_adt(adt)].fields.len() as u64
+            adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.len() as u64
         }
         _ => 0
     }
@@ -1351,7 +1362,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
 ///
 /// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char].
 fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
-                                             ctor: &Constructor,
+                                             ctor: &Constructor<'tcx>,
                                              ty: Ty<'tcx>) -> Vec<Ty<'tcx>>
 {
     debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
@@ -1368,7 +1379,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                 // Use T as the sub pattern type of Box<T>.
                 vec![substs.type_at(0)]
             } else {
-                adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
+                adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
                         || field.vis.is_accessible_from(cx.module, cx.tcx);
                     if is_visible {
index 9dcccba1a06b596aa8aca1c8f9f9760df7091bbb..06a50f35be1cf428280e52f5841dbf208a9d8646 100644 (file)
@@ -888,7 +888,7 @@ fn const_to_pat(
         let adt_subpattern = |i, variant_opt| {
             let field = Field::new(i);
             let val = const_field(
-                self.tcx, self.param_env, instance,
+                self.tcx, self.param_env,
                 variant_opt, field, cv,
             ).expect("field access failed");
             self.const_to_pat(instance, val, id, span)
@@ -931,7 +931,7 @@ fn const_to_pat(
             },
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
                 let variant_index = const_variant_index(
-                    self.tcx, self.param_env, instance, cv
+                    self.tcx, self.param_env, cv
                 ).expect("const_variant_index failed");
                 let subpatterns = adt_subpatterns(
                     adt_def.variants[variant_index].fields.len(),
index 190a381cf52a5e0d5d20fb7b4adf7b87d0fa5859..c3b71be8354daabcb1c6c1b6c0ce952876f740cd 100644 (file)
@@ -109,11 +109,7 @@ pub fn cast(
                 // The src operand does not matter, just its type
                 match src.layout.ty.sty {
                     ty::Closure(def_id, substs) => {
-                        let substs = self.tcx.subst_and_normalize_erasing_regions(
-                            self.substs(),
-                            ty::ParamEnv::reveal_all(),
-                            &substs,
-                        );
+                        let substs = self.subst_and_normalize_erasing_regions(substs)?;
                         let instance = ty::Instance::resolve_closure(
                             *self.tcx,
                             def_id,
index 19362b6cfdb1c4af21052d343674fde60cdb9b05..132b753eb9a62dc92595556e7d95224b0ed9663e 100644 (file)
@@ -1,3 +1,4 @@
+use std::cell::Cell;
 use std::fmt::Write;
 use std::mem;
 
@@ -76,6 +77,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
     /// `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<Tag>>,
+    pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -214,11 +216,21 @@ pub(super) fn mir(&self) -> &'mir mir::Mir<'tcx> {
         self.frame().mir
     }
 
-    pub fn substs(&self) -> &'tcx Substs<'tcx> {
-        if let Some(frame) = self.stack.last() {
-            frame.instance.substs
-        } else {
-            Substs::empty()
+    pub(super) fn subst_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
+        &self,
+        substs: T,
+    ) -> EvalResult<'tcx, T> {
+        match self.stack.last() {
+            Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions(
+                frame.instance.substs,
+                self.param_env,
+                &substs,
+            )),
+            None => if substs.needs_subst() {
+                err!(TooGeneric).into()
+            } else {
+                Ok(substs)
+            },
         }
     }
 
@@ -228,13 +240,9 @@ pub(super) fn resolve(
         substs: &'tcx Substs<'tcx>
     ) -> EvalResult<'tcx, ty::Instance<'tcx>> {
         trace!("resolve: {:?}, {:#?}", def_id, substs);
-        trace!("substs: {:#?}", self.substs());
         trace!("param_env: {:#?}", self.param_env);
-        let substs = self.tcx.subst_and_normalize_erasing_regions(
-            self.substs(),
-            self.param_env,
-            &substs,
-        );
+        let substs = self.subst_and_normalize_erasing_regions(substs)?;
+        trace!("substs: {:#?}", substs);
         ty::Instance::resolve(
             *self.tcx,
             self.param_env,
@@ -274,7 +282,21 @@ pub fn load_mir(
         }
     }
 
-    pub fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
+    pub(super) fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
+        &self,
+        t: T,
+    ) -> EvalResult<'tcx, T> {
+        match self.stack.last() {
+            Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)),
+            None => if t.needs_subst() {
+                err!(TooGeneric).into()
+            } else {
+                Ok(t)
+            },
+        }
+    }
+
+    fn monomorphize_with_substs<T: TypeFoldable<'tcx> + Subst<'tcx>>(
         &self,
         t: T,
         substs: &'tcx Substs<'tcx>
@@ -290,9 +312,15 @@ pub fn layout_of_local(
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local
     ) -> EvalResult<'tcx, TyLayout<'tcx>> {
-        let local_ty = frame.mir.local_decls[local].ty;
-        let local_ty = self.monomorphize(local_ty, frame.instance.substs);
-        self.layout_of(local_ty)
+        let cell = &frame.local_layouts[local];
+        if cell.get().is_none() {
+            let local_ty = frame.mir.local_decls[local].ty;
+            let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
+            let layout = self.layout_of(local_ty)?;
+            cell.set(Some(layout));
+        }
+
+        Ok(cell.get().unwrap())
     }
 
     pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
@@ -426,6 +454,7 @@ pub fn push_stack_frame(
             // empty local array, we fill it in below, after we are inside the stack frame and
             // all methods actually know about the frame
             locals: IndexVec::new(),
+            local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
             span,
             instance,
             stmt: 0,
@@ -464,11 +493,11 @@ pub fn push_stack_frame(
                 },
             }
             // Finally, properly initialize all those that still have the dummy value
-            for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
+            for (idx, local) in locals.iter_enumerated_mut() {
                 match *local {
                     LocalValue::Live(_) => {
                         // This needs to be peoperly initialized.
-                        let layout = self.layout_of(self.monomorphize(decl.ty, instance.substs))?;
+                        let layout = self.layout_of_local(self.frame(), idx)?;
                         *local = LocalValue::Live(self.uninit_operand(layout)?);
                     }
                     LocalValue::Dead => {
index 04e0955ad617263f3dcbbaf3c4ead5dcfbbed905..8741571342f83aff5e01e3700d028791d9d92a4e 100644 (file)
@@ -457,36 +457,30 @@ pub fn operand_projection(
     }
 
     /// This is used by [priroda](https://github.com/oli-obk/priroda) to get an OpTy from a local
-    ///
-    /// When you know the layout of the local in advance, you can pass it as last argument
-    pub fn access_local(
+    fn access_local(
         &self,
         frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local,
-        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         assert_ne!(local, mir::RETURN_PLACE);
         let op = *frame.locals[local].access()?;
-        let layout = from_known_layout(layout,
-                    || self.layout_of_local(frame, local))?;
+        let layout = self.layout_of_local(frame, local)?;
         Ok(OpTy { op, layout })
     }
 
     // Evaluate a place with the goal of reading from it.  This lets us sometimes
-    // avoid allocations.  If you already know the layout, you can pass it in
-    // to avoid looking it up again.
+    // avoid allocations.
     fn eval_place_to_op(
         &self,
         mir_place: &mir::Place<'tcx>,
-        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let op = match *mir_place {
             Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
-            Local(local) => self.access_local(self.frame(), local, layout)?,
+            Local(local) => self.access_local(self.frame(), local)?,
 
             Projection(ref proj) => {
-                let op = self.eval_place_to_op(&proj.base, None)?;
+                let op = self.eval_place_to_op(&proj.base)?;
                 self.operand_projection(op, &proj.elem)?
             }
 
@@ -510,11 +504,11 @@ pub fn eval_operand(
             // FIXME: do some more logic on `move` to invalidate the old location
             Copy(ref place) |
             Move(ref place) =>
-                self.eval_place_to_op(place, layout)?,
+                self.eval_place_to_op(place)?,
 
             Constant(ref constant) => {
                 let layout = from_known_layout(layout, || {
-                    let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
+                    let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx))?;
                     self.layout_of(ty)
                 })?;
                 let op = self.const_value_to_op(*constant.literal)?;
index 962e0b7a7420109d9a7c9e776be4137673eb6f89..f3a948a6ca3e70dbff560c86e5fa5db5f5a6a19f 100644 (file)
@@ -9,6 +9,7 @@
 use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
+use rustc::ty::TypeFoldable;
 
 use super::{
     GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
@@ -583,8 +584,8 @@ pub(super) fn eval_place_to_mplace(
             }
 
             Static(ref static_) => {
-                let ty = self.monomorphize(static_.ty, self.substs());
-                let layout = self.layout_of(ty)?;
+                assert!(!static_.ty.needs_subst());
+                let layout = self.layout_of(static_.ty)?;
                 let instance = ty::Instance::mono(*self.tcx, static_.def_id);
                 let cid = GlobalId {
                     instance,
index f9ce7b4319fac9d30231f07f0a93e41ddf6d0930..53105266b39284372354d84860652e4d2adf97ac 100644 (file)
@@ -314,13 +314,14 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
     stmt: usize,
 }
 
-impl_stable_hash_for!(impl<'tcx, 'mir: 'tcx> for struct Frame<'mir, 'tcx> {
+impl_stable_hash_for!(impl<'mir, 'tcx: 'mir> for struct Frame<'mir, 'tcx> {
     mir,
     instance,
     span,
     return_to_block,
     return_place -> (return_place.as_ref().map(|r| &**r)),
     locals,
+    local_layouts -> _,
     block,
     stmt,
     extra,
@@ -339,6 +340,7 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
             return_to_block,
             return_place,
             locals,
+            local_layouts: _,
             block,
             stmt,
             extra: _,
index 2de8b3c1afdf3579d95ff2959c21f4d886b9e941..25f3e4c1f771d80879409f9c6c0e9fe939659c0e 100644 (file)
@@ -248,7 +248,7 @@ fn eval_rvalue_into_place(
             }
 
             NullaryOp(mir::NullOp::SizeOf, ty) => {
-                let ty = self.monomorphize(ty, self.substs());
+                let ty = self.monomorphize(ty)?;
                 let layout = self.layout_of(ty)?;
                 assert!(!layout.is_unsized(),
                         "SizeOf nullary MIR operator called for unsized type");
@@ -260,7 +260,7 @@ fn eval_rvalue_into_place(
             }
 
             Cast(kind, ref operand, cast_ty) => {
-                debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
+                debug_assert_eq!(self.monomorphize(cast_ty)?, dest.layout.ty);
                 let src = self.eval_operand(operand, None)?;
                 self.cast(src, kind, dest)?;
             }
index a5fb44587400a1323e412e3a061967f19189fcdb..8f5a5bf8ee312d77dcbf27c6ebc9527aa484c340 100644 (file)
@@ -449,8 +449,13 @@ fn visit_scalar(
         }
         // At least one value is excluded. Get the bits.
         let value = try_validation!(value.not_undef(),
-            value, self.path,
-            format!("something in the range {:?}", layout.valid_range));
+            value,
+            self.path,
+            format!(
+                "something {}",
+                wrapping_range_format(&layout.valid_range, max_hi),
+            )
+        );
         let bits = match value {
             Scalar::Ptr(ptr) => {
                 if lo == 1 && hi == max_hi {
index eb49547e9bf529b38b4a430b47e41e8e9441bec6..bc63f8b6ac854a460261d99fd5e53061c4cdd86f 100644 (file)
@@ -355,7 +355,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // We've been here already, no need to search again.
         return;
     }
-    debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx));
+    debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx, true));
 
     let mut neighbors = Vec::new();
     let recursion_depth_reset;
@@ -409,7 +409,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         recursion_depths.insert(def_id, depth);
     }
 
-    debug!("END collect_items_rec({})", starting_point.to_string(tcx));
+    debug!("END collect_items_rec({})", starting_point.to_string(tcx, true));
 }
 
 fn record_accesses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
index c831cbd98299c3ae49be2894c0a091f7017d7a56..431cc0d52b4c8b4d6aa629ae761c5ba1cce4c26b 100644 (file)
@@ -159,14 +159,14 @@ fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
         tcx.substitute_normalize_and_test_predicates((def_id, &substs))
     }
 
-    fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
+    fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, debug: bool) -> String {
         return match *self.as_mono_item() {
             MonoItem::Fn(instance) => {
-                to_string_internal(tcx, "fn ", instance)
+                to_string_internal(tcx, "fn ", instance, debug)
             },
             MonoItem::Static(def_id) => {
                 let instance = Instance::new(def_id, tcx.intern_substs(&[]));
-                to_string_internal(tcx, "static ", instance)
+                to_string_internal(tcx, "static ", instance, debug)
             },
             MonoItem::GlobalAsm(..) => {
                 "global_asm".to_string()
@@ -175,12 +175,13 @@ fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
 
         fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         prefix: &str,
-                                        instance: Instance<'tcx>)
+                                        instance: Instance<'tcx>,
+                                        debug: bool)
                                         -> String {
             let mut result = String::with_capacity(32);
             result.push_str(prefix);
             let printer = DefPathBasedNames::new(tcx, false, false);
-            printer.push_instance_as_string(instance, &mut result);
+            printer.push_instance_as_string(instance, &mut result, debug);
             result
         }
     }
@@ -238,7 +239,13 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
+    // Pushes the type name of the specified type to the provided string.
+    // If 'debug' is true, printing normally unprintable types is allowed
+    // (e.g. ty::GeneratorWitness). This parameter should only be set when
+    // this method is being used for logging purposes (e.g. with debug! or info!)
+    // When being used for codegen purposes, 'debug' should be set to 'false'
+    // in order to catch unexpected types that should never end up in a type name
+    pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
         match t.sty {
             ty::Bool              => output.push_str("bool"),
             ty::Char              => output.push_str("char"),
@@ -260,12 +267,12 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
             ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
             ty::Adt(adt_def, substs) => {
                 self.push_def_path(adt_def.did, output);
-                self.push_type_params(substs, iter::empty(), output);
+                self.push_type_params(substs, iter::empty(), output, debug);
             },
             ty::Tuple(component_types) => {
                 output.push('(');
                 for &component_type in component_types {
-                    self.push_type_name(component_type, output);
+                    self.push_type_name(component_type, output, debug);
                     output.push_str(", ");
                 }
                 if !component_types.is_empty() {
@@ -281,7 +288,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                     hir::MutMutable => output.push_str("mut "),
                 }
 
-                self.push_type_name(inner_type, output);
+                self.push_type_name(inner_type, output, debug);
             },
             ty::Ref(_, inner_type, mutbl) => {
                 output.push('&');
@@ -289,17 +296,17 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                     output.push_str("mut ");
                 }
 
-                self.push_type_name(inner_type, output);
+                self.push_type_name(inner_type, output, debug);
             },
             ty::Array(inner_type, len) => {
                 output.push('[');
-                self.push_type_name(inner_type, output);
+                self.push_type_name(inner_type, output, debug);
                 write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
                 output.push(']');
             },
             ty::Slice(inner_type) => {
                 output.push('[');
-                self.push_type_name(inner_type, output);
+                self.push_type_name(inner_type, output, debug);
                 output.push(']');
             },
             ty::Dynamic(ref trait_data, ..) => {
@@ -309,6 +316,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                         principal.skip_binder().substs,
                         trait_data.projection_bounds(),
                         output,
+                        debug
                     );
                 } else {
                     output.push_str("dyn '_");
@@ -338,7 +346,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
 
                 if !sig.inputs().is_empty() {
                     for &parameter_type in sig.inputs() {
-                        self.push_type_name(parameter_type, output);
+                        self.push_type_name(parameter_type, output, debug);
                         output.push_str(", ");
                     }
                     output.pop();
@@ -357,7 +365,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
 
                 if !sig.output().is_unit() {
                     output.push_str(" -> ");
-                    self.push_type_name(sig.output(), output);
+                    self.push_type_name(sig.output(), output, debug);
                 }
             },
             ty::Generator(def_id, GeneratorSubsts { ref substs }, _) |
@@ -365,7 +373,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 self.push_def_path(def_id, output);
                 let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
                 let substs = substs.truncate_to(self.tcx, generics);
-                self.push_type_params(substs, iter::empty(), output);
+                self.push_type_params(substs, iter::empty(), output, debug);
             }
             ty::Error |
             ty::Bound(..) |
@@ -376,8 +384,12 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
             ty::Param(_) |
             ty::GeneratorWitness(_) |
             ty::Opaque(..) => {
-                bug!("DefPathBasedNames: Trying to create type name for \
+                if debug {
+                    output.push_str(&format!("`{:?}`", t));
+                } else {
+                    bug!("DefPathBasedNames: Trying to create type name for \
                                          unexpected type: {:?}", t);
+                }
             }
         }
     }
@@ -412,7 +424,8 @@ pub fn push_def_path(&self,
     fn push_type_params<I>(&self,
                             substs: &Substs<'tcx>,
                             projections: I,
-                            output: &mut String)
+                            output: &mut String,
+                            debug: bool)
         where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>>
     {
         let mut projections = projections.peekable();
@@ -423,7 +436,7 @@ fn push_type_params<I>(&self,
         output.push('<');
 
         for type_parameter in substs.types() {
-            self.push_type_name(type_parameter, output);
+            self.push_type_name(type_parameter, output, debug);
             output.push_str(", ");
         }
 
@@ -432,7 +445,7 @@ fn push_type_params<I>(&self,
             let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str();
             output.push_str(name);
             output.push_str("=");
-            self.push_type_name(projection.ty, output);
+            self.push_type_name(projection.ty, output, debug);
             output.push_str(", ");
         }
 
@@ -444,8 +457,9 @@ fn push_type_params<I>(&self,
 
     pub fn push_instance_as_string(&self,
                                    instance: Instance<'tcx>,
-                                   output: &mut String) {
+                                   output: &mut String,
+                                   debug: bool) {
         self.push_def_path(instance.def_id(), output);
-        self.push_type_params(instance.substs, iter::empty(), output);
+        self.push_type_params(instance.substs, iter::empty(), output, debug);
     }
 }
index c3613fbf04c1b3781f4c9ae83ca007a2d6f33370..569e4c828f6014ef845b3a4fd1a3910a07805b0a 100644 (file)
@@ -879,7 +879,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                    .unwrap_or("<no hash>");
 
                 debug!(" - {} [{:?}] [{}]",
-                       mono_item.to_string(tcx),
+                       mono_item.to_string(tcx, true),
                        linkage,
                        symbol_hash);
             }
@@ -971,7 +971,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
         let mut item_keys: Vec<_> = items
             .iter()
             .map(|i| {
-                let mut output = i.to_string(tcx);
+                let mut output = i.to_string(tcx, false);
                 output.push_str(" @@");
                 let mut empty = Vec::new();
                 let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
index eb151b56bed65f8d63dd585cc842873a5656996f..ab8da2f352c1c1c8ae3b6628d2ba977f3f9e12dd 100644 (file)
@@ -4,6 +4,7 @@
 
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::cast::CastTy;
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
@@ -20,6 +21,7 @@
 
 pub struct UnsafetyChecker<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
+    const_context: bool,
     min_const_fn: bool,
     source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
     violations: Vec<UnsafetyViolation>,
@@ -33,14 +35,20 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> {
 
 impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn new(
+        const_context: bool,
         min_const_fn: bool,
         mir: &'a Mir<'tcx>,
         source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
+        // sanity check
+        if min_const_fn {
+            assert!(const_context);
+        }
         Self {
             mir,
+            const_context,
             min_const_fn,
             source_scope_local_data,
             violations: vec![],
@@ -124,29 +132,70 @@ fn visit_rvalue(&mut self,
                     rvalue: &Rvalue<'tcx>,
                     location: Location)
     {
-        if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue {
-            match aggregate {
-                &AggregateKind::Array(..) |
-                &AggregateKind::Tuple => {}
-                &AggregateKind::Adt(ref def, ..) => {
-                    match self.tcx.layout_scalar_valid_range(def.did) {
-                        (Bound::Unbounded, Bound::Unbounded) => {},
-                        _ => self.require_unsafe(
-                            "initializing type with `rustc_layout_scalar_valid_range` attr",
-                            "initializing a layout restricted type's field with a value outside \
-                            the valid range is undefined behavior",
-                            UnsafetyViolationKind::GeneralAndConstFn,
-                        ),
+        match rvalue {
+            Rvalue::Aggregate(box ref aggregate, _) => {
+                match aggregate {
+                    &AggregateKind::Array(..) |
+                    &AggregateKind::Tuple => {}
+                    &AggregateKind::Adt(ref def, ..) => {
+                        match self.tcx.layout_scalar_valid_range(def.did) {
+                            (Bound::Unbounded, Bound::Unbounded) => {},
+                            _ => self.require_unsafe(
+                                "initializing type with `rustc_layout_scalar_valid_range` attr",
+                                "initializing a layout restricted type's field with a value \
+                                outside the valid range is undefined behavior",
+                                UnsafetyViolationKind::GeneralAndConstFn,
+                            ),
+                        }
+                    }
+                    &AggregateKind::Closure(def_id, _) |
+                    &AggregateKind::Generator(def_id, _, _) => {
+                        let UnsafetyCheckResult {
+                            violations, unsafe_blocks
+                        } = self.tcx.unsafety_check_result(def_id);
+                        self.register_violations(&violations, &unsafe_blocks);
                     }
                 }
-                &AggregateKind::Closure(def_id, _) |
-                &AggregateKind::Generator(def_id, _, _) => {
-                    let UnsafetyCheckResult {
-                        violations, unsafe_blocks
-                    } = self.tcx.unsafety_check_result(def_id);
-                    self.register_violations(&violations, &unsafe_blocks);
+            },
+            // casting pointers to ints is unsafe in const fn because the const evaluator cannot
+            // possibly know what the result of various operations like `address / 2` would be
+            // pointers during const evaluation have no integral address, only an abstract one
+            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty)
+            if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast => {
+                let operand_ty = operand.ty(self.mir, self.tcx);
+                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
+                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+                match (cast_in, cast_out) {
+                    (CastTy::Ptr(_), CastTy::Int(_)) |
+                    (CastTy::FnPtr, CastTy::Int(_)) => {
+                        self.register_violations(&[UnsafetyViolation {
+                            source_info: self.source_info,
+                            description: Symbol::intern("cast of pointer to int").as_interned_str(),
+                            details: Symbol::intern("casting pointers to integers in constants")
+                                     .as_interned_str(),
+                            kind: UnsafetyViolationKind::General,
+                        }], &[]);
+                    },
+                    _ => {},
                 }
             }
+            // raw pointer and fn pointer operations are unsafe as it is not clear whether one
+            // pointer would be "less" or "equal" to another, because we cannot know where llvm
+            // or the linker will place various statics in memory. Without this information the
+            // result of a comparison of addresses would differ between runtime and compile-time.
+            Rvalue::BinaryOp(_, ref lhs, _)
+            if self.const_context && self.tcx.features().const_compare_raw_pointers => {
+                if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty {
+                    self.register_violations(&[UnsafetyViolation {
+                        source_info: self.source_info,
+                        description: Symbol::intern("pointer operation").as_interned_str(),
+                        details: Symbol::intern("operations on pointers in constants")
+                                 .as_interned_str(),
+                        kind: UnsafetyViolationKind::General,
+                    }], &[]);
+                }
+            }
+            _ => {},
         }
         self.super_rvalue(rvalue, location);
     }
@@ -484,8 +533,16 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     };
 
     let param_env = tcx.param_env(def_id);
+
+    let id = tcx.hir().as_local_node_id(def_id).unwrap();
+    let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
+        hir::BodyOwnerKind::Closure => (false, false),
+        hir::BodyOwnerKind::Fn => (tcx.is_const_fn(def_id), tcx.is_min_const_fn(def_id)),
+        hir::BodyOwnerKind::Const |
+        hir::BodyOwnerKind::Static(_) => (true, false),
+    };
     let mut checker = UnsafetyChecker::new(
-        tcx.is_min_const_fn(def_id),
+        const_context, min_const_fn,
         mir, source_scope_local_data, tcx, param_env);
     checker.visit_mir(mir);
 
index 03d6d3868c9f0440c31cb42a15ece29a20cf7a6b..dc556a15cd8550fe0891bba8995997519f50d915 100644 (file)
@@ -20,7 +20,7 @@
 
 use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind};
 use const_eval::{
-    CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx,
+    CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
     lazy_const_to_op,
 };
 use transform::{MirPass, MirSource};
@@ -110,9 +110,7 @@ fn new(
         source: MirSource,
     ) -> ConstPropagator<'a, 'mir, 'tcx> {
         let param_env = tcx.param_env(source.def_id);
-        let substs = Substs::identity_for_item(tcx, source.def_id);
-        let instance = Instance::new(source.def_id, substs);
-        let ecx = mk_borrowck_eval_cx(tcx, instance, mir, DUMMY_SP).unwrap();
+        let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id), param_env);
         ConstPropagator {
             ecx,
             mir,
index 8b970c1408e378565e159932fc64351834b75c7c..9f0907adc989279935bf6278746b1e31ae9d49f3 100644 (file)
@@ -1,6 +1,5 @@
 //! Inlining pass for MIR functions
 
-use rustc::hir;
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::DefId;
 
@@ -74,15 +73,12 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
 
         // Only do inlining into fn bodies.
         let id = self.tcx.hir().as_local_node_id(self.source.def_id).unwrap();
-        let body_owner_kind = self.tcx.hir().body_owner_kind(id);
-
-        if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) {
-
+        if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() {
             for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
                 if let Some(callsite) = self.get_valid_function_call(bb,
-                                                                     bb_data,
-                                                                     caller_mir,
-                                                                     param_env) {
+                                                                    bb_data,
+                                                                    caller_mir,
+                                                                    param_env) {
                     callsites.push_back(callsite);
                 }
             }
index 78cf7153500c9d19251e74e34fd964bcd1413f5e..2d941902debc33807793869efe09bd660ab862ec 100644 (file)
@@ -1152,6 +1152,7 @@ fn run_pass<'a, 'tcx>(&self,
         let id = tcx.hir().as_local_node_id(def_id).unwrap();
         let mut const_promoted_temps = None;
         let mode = match tcx.hir().body_owner_kind(id) {
+            hir::BodyOwnerKind::Closure => Mode::Fn,
             hir::BodyOwnerKind::Fn => {
                 if tcx.is_const_fn(def_id) {
                     Mode::ConstFn
index 059b88a4d702ae923cff4541b5ba0aa5c5b4a703..85bf1e70ebf423c6261c1d1145536864e953d0d4 100644 (file)
@@ -21,6 +21,7 @@ pub fn is_min_const_fn(
                 | Predicate::RegionOutlives(_)
                 | Predicate::TypeOutlives(_)
                 | Predicate::WellFormed(_)
+                | Predicate::Projection(_)
                 | Predicate::ConstEvaluatable(..) => continue,
                 | Predicate::ObjectSafe(_) => {
                     bug!("object safe predicate on function: {:#?}", predicate)
@@ -29,13 +30,6 @@ pub fn is_min_const_fn(
                     bug!("closure kind predicate on function: {:#?}", predicate)
                 }
                 Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
-                Predicate::Projection(_) => {
-                    let span = tcx.def_span(current);
-                    // we'll hit a `Predicate::Trait` later which will report an error
-                    tcx.sess
-                        .delay_span_bug(span, "projection without trait bound");
-                    continue;
-                }
                 Predicate::Trait(pred) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
index e99f2da73385df0839e90edc2fa35f5950bc47bb..3a15356806a9767b13e6fdb4d1b2b211ffac547d 100644 (file)
@@ -573,6 +573,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> i
     let body_owner_kind = tcx.hir().body_owner_kind(id);
     match (body_owner_kind, src.promoted) {
         (_, Some(i)) => write!(w, "{:?} in", i)?,
+        (hir::BodyOwnerKind::Closure, _) |
         (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?,
         (hir::BodyOwnerKind::Const, _) => write!(w, "const")?,
         (hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?,
@@ -585,6 +586,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> i
     })?;
 
     match (body_owner_kind, src.promoted) {
+        (hir::BodyOwnerKind::Closure, None) |
         (hir::BodyOwnerKind::Fn, None) => {
             write!(w, "(")?;
 
index 3d0e46d998622e2791e6f8ba093b2843b3bc91de..d1a3d7c1f81e038343f2249c821764b10a7abe59 100644 (file)
@@ -6,6 +6,7 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
+use std::mem;
 use rustc::lint;
 use rustc::session::Session;
 use syntax::ast::*;
 
 struct AstValidator<'a> {
     session: &'a Session,
+
+    // Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
+    // Nested `impl Trait` _is_ allowed in associated type position,
+    // e.g `impl Iterator<Item=impl Debug>`
+    outer_impl_trait: Option<Span>,
+
+    // Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
+    // or `Foo::Bar<impl Trait>`
+    is_impl_trait_banned: bool,
 }
 
 impl<'a> AstValidator<'a> {
+    fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.is_impl_trait_banned, true);
+        f(self);
+        self.is_impl_trait_banned = old;
+    }
+
+    fn with_impl_trait(&mut self, outer_impl_trait: Option<Span>, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.outer_impl_trait, outer_impl_trait);
+        f(self);
+        self.outer_impl_trait = old;
+    }
+
+    // Mirrors visit::walk_ty, but tracks relevant state
+    fn walk_ty(&mut self, t: &'a Ty) {
+        match t.node {
+            TyKind::ImplTrait(..) => {
+                self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
+            }
+            TyKind::Path(ref qself, ref path) => {
+                // We allow these:
+                //  - `Option<impl Trait>`
+                //  - `option::Option<impl Trait>`
+                //  - `option::Option<T>::Foo<impl Trait>
+                //
+                // But not these:
+                //  - `<impl Trait>::Foo`
+                //  - `option::Option<impl Trait>::Foo`.
+                //
+                // To implement this, we disallow `impl Trait` from `qself`
+                // (for cases like `<impl Trait>::Foo>`)
+                // but we allow `impl Trait` in `GenericArgs`
+                // iff there are no more PathSegments.
+                if let Some(ref qself) = *qself {
+                    // `impl Trait` in `qself` is always illegal
+                    self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
+                }
+
+                // Note that there should be a call to visit_path here,
+                // so if any logic is added to process `Path`s a call to it should be
+                // added both in visit_path and here. This code mirrors visit::walk_path.
+                for (i, segment) in path.segments.iter().enumerate() {
+                    // Allow `impl Trait` iff we're on the final path segment
+                    if i == path.segments.len() - 1 {
+                        self.visit_path_segment(path.span, segment);
+                    } else {
+                        self.with_banned_impl_trait(|this| {
+                            this.visit_path_segment(path.span, segment)
+                        });
+                    }
+                }
+            }
+            _ => visit::walk_ty(self, t),
+        }
+    }
+
     fn err_handler(&self) -> &errors::Handler {
         &self.session.diagnostic()
     }
@@ -267,6 +332,19 @@ fn visit_ty(&mut self, ty: &'a Ty) {
                 self.no_questions_in_bounds(bounds, "trait object types", false);
             }
             TyKind::ImplTrait(_, ref bounds) => {
+                if self.is_impl_trait_banned {
+                    struct_span_err!(self.session, ty.span, E0667,
+                        "`impl Trait` is not allowed in path parameters").emit();
+                }
+
+                if let Some(outer_impl_trait) = self.outer_impl_trait {
+                    struct_span_err!(self.session, ty.span, E0666,
+                                    "nested `impl Trait` is not allowed")
+                        .span_label(outer_impl_trait, "outer `impl Trait`")
+                        .span_label(ty.span, "nested `impl Trait` here")
+                        .emit();
+
+                }
                 if !bounds.iter()
                           .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
                     self.err_handler().span_err(ty.span, "at least one trait must be specified");
@@ -275,7 +353,7 @@ fn visit_ty(&mut self, ty: &'a Ty) {
             _ => {}
         }
 
-        visit::walk_ty(self, ty)
+        self.walk_ty(ty)
     }
 
     fn visit_label(&mut self, label: &'a Label) {
@@ -414,6 +492,28 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         visit::walk_foreign_item(self, fi)
     }
 
+    // Mirrors visit::walk_generic_args, but tracks relevant state
+    fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
+        match *generic_args {
+            GenericArgs::AngleBracketed(ref data) => {
+                walk_list!(self, visit_generic_arg, &data.args);
+                // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
+                // are allowed to contain nested `impl Trait`.
+                self.with_impl_trait(None, |this| {
+                    walk_list!(this, visit_assoc_type_binding, &data.bindings);
+                });
+            }
+            GenericArgs::Parenthesized(ref data) => {
+                walk_list!(self, visit_ty, &data.inputs);
+                if let Some(ref type_) = data.output {
+                    // `-> Foo` syntax is essentially an associated type binding,
+                    // so it is also allowed to contain nested `impl Trait`.
+                    self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
+                }
+            }
+        }
+    }
+
     fn visit_generics(&mut self, generics: &'a Generics) {
         let mut seen_non_lifetime_param = false;
         let mut seen_default = None;
@@ -490,148 +590,10 @@ fn visit_mac(&mut self, mac: &Spanned<Mac_>) {
     }
 }
 
-// Bans nested `impl Trait`, e.g., `impl Into<impl Debug>`.
-// Nested `impl Trait` _is_ allowed in associated type position,
-// e.g `impl Iterator<Item=impl Debug>`
-struct NestedImplTraitVisitor<'a> {
-    session: &'a Session,
-    outer_impl_trait: Option<Span>,
-}
-
-impl<'a> NestedImplTraitVisitor<'a> {
-    fn with_impl_trait<F>(&mut self, outer_impl_trait: Option<Span>, f: F)
-        where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
-    {
-        let old_outer_impl_trait = self.outer_impl_trait;
-        self.outer_impl_trait = outer_impl_trait;
-        f(self);
-        self.outer_impl_trait = old_outer_impl_trait;
-    }
-}
-
-
-impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
-    fn visit_ty(&mut self, t: &'a Ty) {
-        if let TyKind::ImplTrait(..) = t.node {
-            if let Some(outer_impl_trait) = self.outer_impl_trait {
-                struct_span_err!(self.session, t.span, E0666,
-                                 "nested `impl Trait` is not allowed")
-                    .span_label(outer_impl_trait, "outer `impl Trait`")
-                    .span_label(t.span, "nested `impl Trait` here")
-                    .emit();
-
-            }
-            self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t));
-        } else {
-            visit::walk_ty(self, t);
-        }
-    }
-    fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
-        match *generic_args {
-            GenericArgs::AngleBracketed(ref data) => {
-                for arg in &data.args {
-                    self.visit_generic_arg(arg)
-                }
-                for type_binding in &data.bindings {
-                    // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
-                    // are allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty));
-                }
-            }
-            GenericArgs::Parenthesized(ref data) => {
-                for type_ in &data.inputs {
-                    self.visit_ty(type_);
-                }
-                if let Some(ref type_) = data.output {
-                    // `-> Foo` syntax is essentially an associated type binding,
-                    // so it is also allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
-                }
-            }
-        }
-    }
-
-    fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
-        // covered in AstValidator
-    }
-}
-
-// Bans `impl Trait` in path projections like `<impl Iterator>::Item` or `Foo::Bar<impl Trait>`.
-struct ImplTraitProjectionVisitor<'a> {
-    session: &'a Session,
-    is_banned: bool,
-}
-
-impl<'a> ImplTraitProjectionVisitor<'a> {
-    fn with_ban<F>(&mut self, f: F)
-        where F: FnOnce(&mut ImplTraitProjectionVisitor<'a>)
-    {
-        let old_is_banned = self.is_banned;
-        self.is_banned = true;
-        f(self);
-        self.is_banned = old_is_banned;
-    }
-}
-
-impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
-    fn visit_ty(&mut self, t: &'a Ty) {
-        match t.node {
-            TyKind::ImplTrait(..) => {
-                if self.is_banned {
-                    struct_span_err!(self.session, t.span, E0667,
-                        "`impl Trait` is not allowed in path parameters").emit();
-                }
-            }
-            TyKind::Path(ref qself, ref path) => {
-                // We allow these:
-                //  - `Option<impl Trait>`
-                //  - `option::Option<impl Trait>`
-                //  - `option::Option<T>::Foo<impl Trait>
-                //
-                // But not these:
-                //  - `<impl Trait>::Foo`
-                //  - `option::Option<impl Trait>::Foo`.
-                //
-                // To implement this, we disallow `impl Trait` from `qself`
-                // (for cases like `<impl Trait>::Foo>`)
-                // but we allow `impl Trait` in `GenericArgs`
-                // iff there are no more PathSegments.
-                if let Some(ref qself) = *qself {
-                    // `impl Trait` in `qself` is always illegal
-                    self.with_ban(|this| this.visit_ty(&qself.ty));
-                }
-
-                for (i, segment) in path.segments.iter().enumerate() {
-                    // Allow `impl Trait` iff we're on the final path segment
-                    if i == path.segments.len() - 1 {
-                        visit::walk_path_segment(self, path.span, segment);
-                    } else {
-                        self.with_ban(|this|
-                            visit::walk_path_segment(this, path.span, segment));
-                    }
-                }
-            }
-            _ => visit::walk_ty(self, t),
-        }
-    }
-
-    fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
-        // covered in AstValidator
-    }
-}
-
 pub fn check_crate(session: &Session, krate: &Crate) {
-    visit::walk_crate(
-        &mut NestedImplTraitVisitor {
-            session,
-            outer_impl_trait: None,
-        }, krate);
-
-    visit::walk_crate(
-        &mut ImplTraitProjectionVisitor {
-            session,
-            is_banned: false,
-        }, krate);
-
-    visit::walk_crate(&mut AstValidator { session }, krate)
+    visit::walk_crate(&mut AstValidator {
+        session,
+        outer_impl_trait: None,
+        is_impl_trait_banned: false,
+    }, krate)
 }
index 604b31e7167a971dd6b13fe7b10e1860c0c70fa5..74d6d75a7f528ad9ef403b8406af5676aa05cebf 100644 (file)
@@ -144,7 +144,7 @@ fn visit_block(&mut self, b: &'v hir::Block) {
     }
 
     fn visit_stmt(&mut self, s: &'v hir::Stmt) {
-        self.record("Stmt", Id::Node(s.node.id()), s);
+        self.record("Stmt", Id::Node(s.id), s);
         hir_visit::walk_stmt(self, s)
     }
 
@@ -158,11 +158,6 @@ fn visit_pat(&mut self, p: &'v hir::Pat) {
         hir_visit::walk_pat(self, p)
     }
 
-    fn visit_decl(&mut self, d: &'v hir::Decl) {
-        self.record("Decl", Id::None, d);
-        hir_visit::walk_decl(self, d)
-    }
-
     fn visit_expr(&mut self, ex: &'v hir::Expr) {
         self.record("Expr", Id::Node(ex.id), ex);
         hir_visit::walk_expr(self, ex)
index f0b559f80a28ce0c87d8d51f6fe6aba01011729e..c11b1af97766d80d651c8b50cbb0fa67eab8c662 100644 (file)
@@ -191,6 +191,7 @@ fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability {
         self.in_static = false;
 
         match self.tcx.hir().body_owner_kind(item_id) {
+            hir::BodyOwnerKind::Closure |
             hir::BodyOwnerKind::Fn => self.in_fn = true,
             hir::BodyOwnerKind::Static(_) => self.in_static = true,
             _ => {}
@@ -220,26 +221,22 @@ fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability {
 
     fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability {
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _node_id) => {
-                match &decl.node {
-                    hir::DeclKind::Local(local) => {
-                        if self.remove_mut_rvalue_borrow(&local.pat) {
-                            if let Some(init) = &local.init {
-                                self.mut_rvalue_borrows.insert(init.id);
-                            }
-                        }
-
-                        if let Some(ref expr) = local.init {
-                            let _ = self.check_expr(&expr);
-                        }
-                        NotPromotable
+            hir::StmtKind::Local(ref local) => {
+                if self.remove_mut_rvalue_borrow(&local.pat) {
+                    if let Some(init) = &local.init {
+                        self.mut_rvalue_borrows.insert(init.id);
                     }
-                    // Item statements are allowed
-                    hir::DeclKind::Item(_) => Promotable
                 }
+
+                if let Some(ref expr) = local.init {
+                    let _ = self.check_expr(&expr);
+                }
+                NotPromotable
             }
-            hir::StmtKind::Expr(ref box_expr, _node_id) |
-            hir::StmtKind::Semi(ref box_expr, _node_id) => {
+            // Item statements are allowed
+            hir::StmtKind::Item(..) => Promotable,
+            hir::StmtKind::Expr(ref box_expr) |
+            hir::StmtKind::Semi(ref box_expr) => {
                 let _ = self.check_expr(box_expr);
                 NotPromotable
             }
index 698037e237101e8c50ced784cbd808873cdcfb06..dcbb9ff4a757628580a0495e6bc22a6e89a8a6bb 100644 (file)
@@ -13,7 +13,7 @@
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
-use rustc::hir::{self, Node, PatKind};
+use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -548,7 +548,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                         let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
                         reach.generics().predicates();
 
-                        if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                        if trait_item_ref.kind == AssociatedItemKind::Type &&
                            !trait_item_ref.defaultness.has_value() {
                             // No type to visit.
                         } else {
@@ -1343,11 +1343,11 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                         if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
-                                hir::AssociatedItemKind::Const => {
+                                AssociatedItemKind::Const => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
-                                hir::AssociatedItemKind::Method { has_self: false } => {
+                                AssociatedItemKind::Method { has_self: false } => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
@@ -1568,6 +1568,24 @@ fn check(&self, item_id: ast::NodeId, required_visibility: ty::Visibility)
             in_assoc_ty: false,
         }
     }
+
+    fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
+                                defaultness: hir::Defaultness, vis: ty::Visibility) {
+        let mut check = self.check(node_id, vis);
+
+        let (check_ty, is_assoc_ty) = match assoc_item_kind {
+            AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
+            AssociatedItemKind::Type => (defaultness.has_value(), true),
+            // `ty()` for existential types is the underlying type,
+            // it's not a part of interface, so we skip it.
+            AssociatedItemKind::Existential => (false, true),
+        };
+        check.in_assoc_ty = is_assoc_ty;
+        check.generics().predicates();
+        if check_ty {
+            check.ty();
+        }
+    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1602,16 +1620,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 self.check(item.id, item_visibility).generics().predicates();
 
                 for trait_item_ref in trait_item_refs {
-                    let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
-                    check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
-                    check.generics().predicates();
-
-                    if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
-                       !trait_item_ref.defaultness.has_value() {
-                        // No type to visit.
-                    } else {
-                        check.ty();
-                    }
+                    self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
+                                                  trait_item_ref.defaultness, item_visibility);
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
@@ -1657,9 +1667,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     } else {
                         impl_vis
                     };
-                    let mut check = self.check(impl_item.id, impl_item_vis);
-                    check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
-                    check.generics().predicates().ty();
+                    self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
+                                                  impl_item_ref.defaultness, impl_item_vis);
                 }
             }
         }
index a452bbf0c9d5409f53da9c508f9b7d536c4aa9ff..3db73800d640a207df802a55ad05adde84a53a88 100644 (file)
@@ -21,6 +21,8 @@
 use std::ptr;
 use rustc_data_structures::sync::Lrc;
 
+use errors::Applicability;
+
 use syntax::ast::{Name, Ident};
 use syntax::attr;
 
@@ -345,7 +347,12 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
                 let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() {
                     self.session
                         .struct_span_err(item.span, "`extern crate self;` requires renaming")
-                        .span_suggestion(item.span, "try", "extern crate self as name;".into())
+                        .span_suggestion_with_applicability(
+                            item.span,
+                            "try",
+                            "extern crate self as name;".into(),
+                            Applicability::HasPlaceholders,
+                        )
                         .emit();
                     return;
                 } else if orig_name == Some(keywords::SelfLower.name()) {
@@ -673,6 +680,10 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
                 }
                 module.populated.set(true);
             }
+            Def::Existential(..) |
+            Def::TraitAlias(..) => {
+                self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
+            }
             Def::Struct(..) | Def::Union(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
 
index a58d63e1ca28b271f2915a14a62ad3d08f1daec1..4c9347afa611d442d27a1f49e69e847bce421c64 100644 (file)
@@ -4866,8 +4866,13 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                 } else if ident.span.rust_2018() {
                     let msg = "relative paths are not supported in visibilities on 2018 edition";
                     self.session.struct_span_err(ident.span, msg)
-                                .span_suggestion(path.span, "try", format!("crate::{}", path))
-                                .emit();
+                        .span_suggestion_with_applicability(
+                            path.span,
+                            "try",
+                            format!("crate::{}", path),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
                     return ty::Visibility::Public;
                 } else {
                     let ctxt = ident.span.ctxt();
@@ -5008,11 +5013,7 @@ fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError) {
                 ))
             }
 
-            if b.span.is_dummy() {
-                err.note(&note_msg);
-            } else {
-                err.span_note(b.span, &note_msg);
-            }
+            err.span_note(b.span, &note_msg);
             for (i, help_msg) in help_msgs.iter().enumerate() {
                 let or = if i == 0 { "" } else { "or " };
                 err.help(&format!("{}{}", or, help_msg));
@@ -5127,10 +5128,10 @@ fn report_conflict<'b>(&mut self,
                           container));
 
         err.span_label(span, format!("`{}` re{} here", name, new_participle));
-        if !old_binding.span.is_dummy() {
-            err.span_label(self.session.source_map().def_span(old_binding.span),
-                           format!("previous {} of the {} `{}` here", old_noun, old_kind, name));
-        }
+        err.span_label(
+            self.session.source_map().def_span(old_binding.span),
+            format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
+        );
 
         // See https://github.com/rust-lang/rust/issues/32354
         if old_binding.is_import() || new_binding.is_import() {
index 3a21ca19b176b789a7328bd19ef922f2c79dc1e2..e47da3cff95b695e2545a8b28bcc5f20724cfab9 100644 (file)
@@ -367,6 +367,7 @@ fn $module() {
 
     ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
     ("i686-unknown-freebsd", i686_unknown_freebsd),
+    ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
 
     ("i686-unknown-dragonfly", i686_unknown_dragonfly),
diff --git a/src/librustc_target/spec/powerpc64_unknown_freebsd.rs b/src/librustc_target/spec/powerpc64_unknown_freebsd.rs
new file mode 100644 (file)
index 0000000..cc7b87b
--- /dev/null
@@ -0,0 +1,22 @@
+use spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::freebsd_base::opts();
+    base.cpu = "ppc64".to_string();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.max_atomic_width = Some(64);
+
+    Ok(Target {
+        llvm_target: "powerpc64-unknown-freebsd".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64".to_string(),
+        arch: "powerpc64".to_string(),
+        target_os: "freebsd".to_string(),
+        target_env: String::new(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
index 5502a1d186eeef2c3bd1776921cc86d7f1b5df08..9bdef3051e58934403ec63e0be1712fff71fdda2 100644 (file)
@@ -158,7 +158,8 @@ fn into_well_formed_goal(self) -> DomainGoal<'tcx> {
     def_id: DefId,
 ) -> Clauses<'tcx> {
     match tcx.def_key(def_id).disambiguated_data.data {
-        DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+        DefPathData::Trait(_) |
+        DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id),
         DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
         DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
         DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
index 534279e981d624cd465e31b4b78a30b6388b4020..e89506aaf99f9232bc0a103c0339f63fb99f84d3 100644 (file)
@@ -2,7 +2,7 @@
 //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
 //! instance of `AstConv`.
 
-use errors::{Applicability, FatalError, DiagnosticId};
+use errors::{Applicability, DiagnosticId};
 use hir::{self, GenericArg, GenericArgs};
 use hir::def::Def;
 use hir::def_id::DefId;
@@ -690,27 +690,13 @@ pub fn instantiate_mono_trait_ref(&self,
     {
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
 
-        let trait_def_id = self.trait_def_id(trait_ref);
         self.ast_path_to_mono_trait_ref(trait_ref.path.span,
-                                        trait_def_id,
+                                        trait_ref.trait_def_id(),
                                         self_ty,
                                         trait_ref.path.segments.last().unwrap())
     }
 
-    /// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
-    fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
-        let path = &trait_ref.path;
-        match path.def {
-            Def::Trait(trait_def_id) => trait_def_id,
-            Def::TraitAlias(alias_def_id) => alias_def_id,
-            Def::Err => {
-                FatalError.raise();
-            }
-            _ => unreachable!(),
-        }
-    }
-
-    /// The given trait ref must actually be a trait.
+    /// The given trait-ref must actually be a trait.
     pub(super) fn instantiate_poly_trait_ref_inner(&self,
         trait_ref: &hir::TraitRef,
         self_ty: Ty<'tcx>,
@@ -718,7 +704,7 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
         speculative: bool)
         -> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
     {
-        let trait_def_id = self.trait_def_id(trait_ref);
+        let trait_def_id = trait_ref.trait_def_id();
 
         debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
 
index 1767af4870d3b27eca2564d33b461a746e2f54d4..47f258e1aea7478d77cb28b8004bfbbf34225ced 100644 (file)
@@ -1,5 +1,6 @@
 use check::{FnCtxt, Expectation, Diverges, Needs};
 use check::coercion::CoerceMany;
+use errors::Applicability;
 use rustc::hir::{self, PatKind};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -989,7 +990,13 @@ fn check_struct_pat_fields(&self,
                     let suggested_name =
                         find_best_match_for_name(input, &ident.as_str(), None);
                     if let Some(suggested_name) = suggested_name {
-                        err.span_suggestion(*span, "did you mean", suggested_name.to_string());
+                        err.span_suggestion_with_applicability(
+                            *span,
+                            "did you mean",
+                            suggested_name.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+
                         // we don't want to throw `E0027` in case we have thrown `E0026` for them
                         unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
                     }
index a82a0d3ce52329827e1fb756b9c9471ce1d24f4d..d1dfe9469fb774753afedee85e4c200ec058c8f5 100644 (file)
@@ -1199,7 +1199,6 @@ fn coerce_inner<'a>(&mut self,
                     (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                 };
 
-                let reason_label = "expected because of this statement";
                 let mut db;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
@@ -1209,34 +1208,23 @@ fn coerce_inner<'a>(&mut self,
                         db.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id) => {
-                        db = fcx.report_mismatched_types(cause, expected, found, err);
-
-                        let expr = expression.unwrap_or_else(|| {
-                            span_bug!(cause.span,
-                                      "supposed to be part of a block tail expression, but the \
-                                       expression is empty");
-                        });
-                        fcx.suggest_mismatched_types_on_tail(
-                            &mut db,
-                            expr,
+                        let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
+                        db = self.report_return_mismatched_types(
+                            cause,
                             expected,
                             found,
-                            cause.span,
-                            blk_id,
+                            err,
+                            fcx,
+                            parent_id,
+                            expression.map(|expr| (expr, blk_id)),
                         );
-                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
-                            if !sp.overlaps(cause.span) {
-                                db.span_label(*sp, reason_label);
-                            }
-                        }
+                    }
+                    ObligationCauseCode::ReturnType(id) => {
+                        db = self.report_return_mismatched_types(
+                            cause, expected, found, err, fcx, id, None);
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
-                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
-                            if !sp.overlaps(cause.span) {
-                                db.span_label(*sp, reason_label);
-                            }
-                        }
                     }
                 }
 
@@ -1251,6 +1239,59 @@ fn coerce_inner<'a>(&mut self,
         }
     }
 
+    fn report_return_mismatched_types<'a>(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+        err: TypeError<'tcx>,
+        fcx: &FnCtxt<'a, 'gcx, 'tcx>,
+        id: syntax::ast::NodeId,
+        expression: Option<(&'gcx hir::Expr, syntax::ast::NodeId)>,
+    ) -> DiagnosticBuilder<'a> {
+        let mut db = fcx.report_mismatched_types(cause, expected, found, err);
+
+        let mut pointing_at_return_type = false;
+        let mut return_sp = None;
+
+        // Verify that this is a tail expression of a function, otherwise the
+        // label pointing out the cause for the type coercion will be wrong
+        // as prior return coercions would not be relevant (#57664).
+        let parent_id = fcx.tcx.hir().get_parent_node(id);
+        let fn_decl = if let Some((expr, blk_id)) = expression {
+            pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
+                &mut db,
+                expr,
+                expected,
+                found,
+                cause.span,
+                blk_id,
+            );
+            let parent = fcx.tcx.hir().get(parent_id);
+            fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
+        } else {
+            fcx.get_fn_decl(parent_id)
+        };
+
+        if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) {
+            if expression.is_none() {
+                pointing_at_return_type |= fcx.suggest_missing_return_type(
+                    &mut db, &fn_decl, expected, found, can_suggest);
+            }
+            if !pointing_at_return_type {
+                return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
+            }
+        }
+        if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
+            db.span_label(return_sp, "expected because this return type...");
+            db.span_label( *sp, format!(
+                "...is found to be `{}` here",
+                fcx.resolve_type_vars_with_obligations(expected),
+            ));
+        }
+        db
+    }
+
     pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         if let Some(final_ty) = self.final_ty {
             final_ty
index c0cedd77440d9898e47352a5fb717cc918a51512..d985bdae491d09d6d2dd40f47a648b632cce65cb 100644 (file)
@@ -454,12 +454,13 @@ fn is_range_literal(&self, expr: &hir::Expr) -> bool {
         false
     }
 
-    pub fn check_for_cast(&self,
-                      err: &mut DiagnosticBuilder<'tcx>,
-                      expr: &hir::Expr,
-                      checked_ty: Ty<'tcx>,
-                      expected_ty: Ty<'tcx>)
-                      -> bool {
+    pub fn check_for_cast(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        expr: &hir::Expr,
+        checked_ty: Ty<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) -> bool {
         let parent_id = self.tcx.hir().get_parent_node(expr.id);
         if let Some(parent) = self.tcx.hir().find(parent_id) {
             // Shouldn't suggest `.into()` on `const`s.
@@ -487,17 +488,40 @@ pub fn check_for_cast(&self,
         // For now, don't suggest casting with `as`.
         let can_cast = false;
 
+        let mut prefix = String::new();
+        if let Some(hir::Node::Expr(hir::Expr {
+            node: hir::ExprKind::Struct(_, fields, _),
+            ..
+        })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) {
+            // `expr` is a literal field for a struct, only suggest if appropriate
+            for field in fields {
+                if field.expr.id == expr.id && field.is_shorthand {
+                    // This is a field literal
+                    prefix = format!("{}: ", field.ident);
+                    break;
+                }
+            }
+            if &prefix == "" {
+                // Likely a field was meant, but this field wasn't found. Do not suggest anything.
+                return false;
+            }
+        }
+
         let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8);
 
         if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
             let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
-            let cast_suggestion = format!("{}{}{} as {}",
-                                          if needs_paren { "(" } else { "" },
-                                          src,
-                                          if needs_paren { ")" } else { "" },
-                                          expected_ty);
+            let cast_suggestion = format!(
+                "{}{}{}{} as {}",
+                prefix,
+                if needs_paren { "(" } else { "" },
+                src,
+                if needs_paren { ")" } else { "" },
+                expected_ty,
+            );
             let into_suggestion = format!(
-                "{}{}{}.into()",
+                "{}{}{}{}.into()",
+                prefix,
                 if needs_paren { "(" } else { "" },
                 src,
                 if needs_paren { ")" } else { "" },
index 143715dff813bb99aa436b7892f62cef706b44a4..96e271f0cde10b6e146cc92ce6c03af213a9d58c 100644 (file)
@@ -430,6 +430,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
         "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
         "simd_cast" => (2, vec![param(0)], param(1)),
+        "simd_bitmask" => (2, vec![param(0)], param(1)),
         "simd_select" |
         "simd_select_bitmask" => (2, vec![param(0), param(1), param(1)], param(1)),
         "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool),
index 9a828ce01775c0df574f734aea316ff4761f1f43..b849be52a9223fe7f4e210f3ad25177583c96e2e 100644 (file)
@@ -506,15 +506,13 @@ fn assemble_probe(&mut self, self_ty: &Canonical<'gcx, QueryResponse<'gcx, Ty<'g
         match self_ty.value.value.sty {
             ty::Dynamic(ref data, ..) => {
                 if let Some(p) = data.principal() {
-                    self.fcx.probe(|_| {
-                        let InferOk { value: self_ty, obligations: _ } =
-                            self.fcx.probe_instantiate_query_response(
-                                self.span, &self.orig_steps_var_values, self_ty)
-                            .unwrap_or_else(|_| {
-                                span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty)
-                            });
-                        self.assemble_inherent_candidates_from_object(self_ty);
-                    });
+                    let InferOk { value: instantiated_self_ty, obligations: _ } =
+                        self.fcx.probe_instantiate_query_response(
+                            self.span, &self.orig_steps_var_values, self_ty)
+                        .unwrap_or_else(|_| {
+                            span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty)
+                        });
+                    self.assemble_inherent_candidates_from_object(instantiated_self_ty);
                     self.assemble_inherent_impl_candidates_for_type(p.def_id());
                 }
             }
index 23bcd88d6afb5548ccc94557115a1be069fd5d62..f71a163cee26156b813ee12dbb0126837c5dcdeb 100644 (file)
@@ -304,7 +304,12 @@ pub fn report_method_error<'b>(&self,
                         );
                         if let Some(suggestion) = suggestion {
                             // enum variant
-                            err.help(&format!("did you mean `{}`?", suggestion));
+                            err.span_suggestion_with_applicability(
+                                item_name.span,
+                                "did you mean",
+                                suggestion.to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                         err
                     }
@@ -440,7 +445,12 @@ macro_rules! report_function {
                 }
 
                 if let Some(lev_candidate) = lev_candidate {
-                    err.help(&format!("did you mean `{}`?", lev_candidate.ident));
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "did you mean",
+                        lev_candidate.ident.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
                 err.emit();
             }
index 19e3d6bcaab587729b827d491db744f60de29fb8..240db801fb2f22c4ffd6d91ff6bd27e97263ed10 100644 (file)
@@ -3122,7 +3122,8 @@ fn check_lit(&self,
                 opt_ty.unwrap_or_else(
                     || tcx.mk_float_var(self.next_float_var_id()))
             }
-            ast::LitKind::Bool(_) => tcx.types.bool
+            ast::LitKind::Bool(_) => tcx.types.bool,
+            ast::LitKind::Err(_) => tcx.types.err,
         }
     }
 
@@ -4348,11 +4349,15 @@ fn check_expr_kind(
                     struct_span_err!(self.tcx.sess, expr.span, E0572,
                                      "return statement outside of function body").emit();
                 } else if let Some(ref e) = *expr_opt {
-                    *self.ret_coercion_span.borrow_mut() = Some(e.span);
+                    if self.ret_coercion_span.borrow().is_none() {
+                        *self.ret_coercion_span.borrow_mut() = Some(e.span);
+                    }
                     self.check_return_expr(e);
                 } else {
                     let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
-                    *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+                    if self.ret_coercion_span.borrow().is_none() {
+                        *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+                    }
                     let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
                     if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
                         coercion.coerce_forced_unit(
@@ -4841,15 +4846,11 @@ pub fn check_decl_local(&self, local: &'gcx hir::Local) {
     pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
         // Don't do all the complex logic below for `DeclItem`.
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                if let hir::DeclKind::Item(_) = decl.node {
-                    return
-                }
-            }
-            hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
+            hir::StmtKind::Item(..) => return,
+            hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
         }
 
-        self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement");
+        self.warn_if_unreachable(stmt.id, stmt.span, "statement");
 
         // Hide the outer diverging and `has_errors` flags.
         let old_diverges = self.diverges.get();
@@ -4858,20 +4859,16 @@ pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
         self.has_errors.set(false);
 
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                match decl.node {
-                    hir::DeclKind::Local(ref l) => {
-                        self.check_decl_local(&l);
-                    }
-                    // Ignore for now.
-                    hir::DeclKind::Item(_) => ()
-                }
+            hir::StmtKind::Local(ref l) => {
+                self.check_decl_local(&l);
             }
-            hir::StmtKind::Expr(ref expr, _) => {
+            // Ignore for now.
+            hir::StmtKind::Item(_) => {}
+            hir::StmtKind::Expr(ref expr) => {
                 // Check with expected type of `()`.
                 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());
             }
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Semi(ref expr) => {
                 self.check_expr(&expr);
             }
         }
@@ -5090,12 +5087,15 @@ pub fn suggest_mismatched_types_on_tail(
         found: Ty<'tcx>,
         cause_span: Span,
         blk_id: ast::NodeId,
-    ) {
+    ) -> bool {
         self.suggest_missing_semicolon(err, expression, expected, cause_span);
+        let mut pointing_at_return_type = false;
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
-            self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
+            pointing_at_return_type = self.suggest_missing_return_type(
+                err, &fn_decl, expected, found, can_suggest);
         }
         self.suggest_ref_or_into(err, expression, expected, found);
+        pointing_at_return_type
     }
 
     pub fn suggest_ref_or_into(
@@ -5194,12 +5194,14 @@ fn suggest_missing_semicolon(&self,
     /// This routine checks if the return type is left as default, the method is not part of an
     /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
     /// type.
-    fn suggest_missing_return_type(&self,
-                                   err: &mut DiagnosticBuilder<'tcx>,
-                                   fn_decl: &hir::FnDecl,
-                                   expected: Ty<'tcx>,
-                                   found: Ty<'tcx>,
-                                   can_suggest: bool) {
+    fn suggest_missing_return_type(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        fn_decl: &hir::FnDecl,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+        can_suggest: bool,
+    ) -> bool {
         // Only suggest changing the return type for methods that
         // haven't set a return type at all (and aren't `fn main()` or an impl).
         match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
@@ -5209,16 +5211,19 @@ fn suggest_missing_return_type(&self,
                     "try adding a return type",
                     format!("-> {} ", self.resolve_type_vars_with_obligations(found)),
                     Applicability::MachineApplicable);
+                true
             }
             (&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => {
                 err.span_label(span, "possibly return type missing here?");
+                true
             }
             (&hir::FunctionRetTy::DefaultReturn(span), _, false, true) => {
                 // `fn main()` must return `()`, do not suggest changing return type
                 err.span_label(span, "expected `()` because of default return type");
+                true
             }
             // expectation was caused by something else, not the default return
-            (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => {}
+            (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => false,
             (&hir::FunctionRetTy::Return(ref ty), _, _, _) => {
                 // Only point to return type if the expected type is the return type, as if they
                 // are not, the expectation must have been caused by something else.
@@ -5230,7 +5235,9 @@ fn suggest_missing_return_type(&self,
                 if ty.sty == expected.sty {
                     err.span_label(sp, format!("expected `{}` because of return type",
                                                expected));
+                    return true;
                 }
+                false
             }
         }
     }
@@ -5274,7 +5281,7 @@ fn could_remove_semicolon(
             None => return None,
         };
         let last_expr = match last_stmt.node {
-            hir::StmtKind::Semi(ref e, _) => e,
+            hir::StmtKind::Semi(ref e) => e,
             _ => return None,
         };
         let last_expr_ty = self.node_ty(last_expr.hir_id);
index 53e44d53e6a9bb1c6d86dcaf3c6d5955ec5da6a8..6cae8d6fc5b9434c943cc39b48e5ae563355f678 100644 (file)
@@ -608,8 +608,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
             if let ty::Opaque(def_id, substs) = ty.sty {
                 trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
-                // only check named existential types
-                if generics.parent.is_none() {
+                // only check named existential types defined in this crate
+                if generics.parent.is_none() && def_id.is_local() {
                     let opaque_node_id = tcx.hir().as_local_node_id(def_id).unwrap();
                     if may_define_existential_type(tcx, fn_def_id, opaque_node_id) {
                         trace!("check_existential_types may define. Generics: {:#?}", generics);
index 3a546f84469e60343a4c0689b034db5e743cc3a5..93f14a2ea6f647b26ee4836b556c20cdad8eeb9b 100644 (file)
@@ -715,7 +715,7 @@ fn super_predicates_of<'a, 'tcx>(
     // In the case of trait aliases, however, we include all bounds in the where clause,
     // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
     // as one of its "superpredicates".
-    let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
+    let is_trait_alias = tcx.is_trait_alias(trait_def_id);
     let superbounds2 = icx.type_parameter_bounds_in_generics(
         generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
 
index 6c1c49bda4ce5d4f7062738f5c11e8eed5ac55b5..5149f460baca0a21ea24dbb3e9a52839cacc320b 100644 (file)
@@ -66,7 +66,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(exhaustive_patterns)]
 #![feature(nll)]
-#![feature(quote)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
index 87e979b93e9ef55240b537b2ed2be79ec36b233d..e43251b7d5f97126cfbf8ed901dced7818731be3 100644 (file)
@@ -25,40 +25,51 @@ pub fn render_with_highlighting(
     tooltip: Option<(&str, &str)>,
 ) -> String {
     debug!("highlighting: ================\n{}\n==============", src);
-    let sess = parse::ParseSess::new(FilePathMapping::empty());
-    let fm = sess.source_map().new_source_file(FileName::Custom("stdin".to_string()),
-                                               src.to_string());
-
     let mut out = Vec::new();
     if let Some((tooltip, class)) = tooltip {
         write!(out, "<div class='information'><div class='tooltip {}'>ⓘ<span \
                      class='tooltiptext'>{}</span></div></div>",
                class, tooltip).unwrap();
     }
-    write_header(class, &mut out).unwrap();
-
-    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 sess = parse::ParseSess::new(FilePathMapping::empty());
+    let fm = sess.source_map().new_source_file(
+        FileName::Custom(String::from("rustdoc-highlighting")),
+        src.to_owned(),
+    );
+    let highlight_result =
+        lexer::StringReader::new_or_buffered_errs(&sess, fm, None).and_then(|lexer| {
+            let mut classifier = Classifier::new(lexer, sess.source_map());
+
+            let mut highlighted_source = vec![];
+            if classifier.write_source(&mut highlighted_source).is_err() {
+                Err(classifier.lexer.buffer_fatal_errors())
+            } else {
+                Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
+            }
+        });
+
+    match highlight_result {
+        Ok(highlighted_source) => {
+            write_header(class, &mut out).unwrap();
+            write!(out, "{}", highlighted_source).unwrap();
+            if let Some(extension) = extension {
+                write!(out, "{}", extension).unwrap();
+            }
+            write_footer(&mut out).unwrap();
         }
-    };
-    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);
-    }
+        Err(errors) => {
+            // If errors are encountered while trying to highlight, cancel the errors and just emit
+            // the unhighlighted source. The errors will have already been reported in the
+            // `check-code-block-syntax` pass.
+            for mut error in errors {
+                error.cancel();
+            }
 
-    if let Some(extension) = extension {
-        write!(out, "{}", extension).unwrap();
+            write!(out, "<pre><code>{}</code></pre>", src).unwrap();
+        }
     }
-    write_footer(&mut out).unwrap();
+
     String::from_utf8_lossy(&out[..]).into_owned()
 }
 
@@ -151,6 +162,17 @@ fn exit_span(&mut self) -> io::Result<()> {
     }
 }
 
+enum HighlightError {
+    LexError,
+    IoError(io::Error),
+}
+
+impl From<io::Error> for HighlightError {
+    fn from(err: io::Error) -> Self {
+        HighlightError::IoError(err)
+    }
+}
+
 impl<'a> Classifier<'a> {
     fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> {
         Classifier {
@@ -162,17 +184,11 @@ fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<
         }
     }
 
-    /// Gets the next token out of the lexer, emitting fatal errors if lexing fails.
-    fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
+    /// Gets the next token out of the lexer.
+    fn try_next_token(&mut self) -> Result<TokenAndSpan, HighlightError> {
         match self.lexer.try_next_token() {
             Ok(tas) => Ok(tas),
-            Err(_) => {
-                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, ""))
-            }
+            Err(_) => Err(HighlightError::LexError),
         }
     }
 
@@ -185,7 +201,7 @@ fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
     /// source.
     fn write_source<W: Writer>(&mut self,
                                    out: &mut W)
-                                   -> io::Result<()> {
+                                   -> Result<(), HighlightError> {
         loop {
             let next = self.try_next_token()?;
             if next.tok == token::Eof {
@@ -202,7 +218,7 @@ fn write_source<W: Writer>(&mut self,
     fn write_token<W: Writer>(&mut self,
                               out: &mut W,
                               tas: TokenAndSpan)
-                              -> io::Result<()> {
+                              -> Result<(), HighlightError> {
         let klass = match tas.tok {
             token::Shebang(s) => {
                 out.string(Escape(&s.as_str()), Class::None)?;
@@ -296,7 +312,7 @@ fn write_token<W: Writer>(&mut self,
             token::Literal(lit, _suf) => {
                 match lit {
                     // Text literals.
-                    token::Byte(..) | token::Char(..) |
+                    token::Byte(..) | token::Char(..) | token::Err(..) |
                         token::ByteStr(..) | token::ByteStrRaw(..) |
                         token::Str_(..) | token::StrRaw(..) => Class::String,
 
@@ -341,7 +357,9 @@ fn write_token<W: Writer>(&mut self,
 
         // Anything that didn't return above is the simple case where we the
         // class just spans a single token, so we can use the `string` method.
-        out.string(Escape(&self.snip(tas.sp)), klass)
+        out.string(Escape(&self.snip(tas.sp)), klass)?;
+
+        Ok(())
     }
 
     // Helper function to get a snippet from the source_map.
index 987cec6fbfa962f9a106e543941154a8cd49b20e..c34dcbbb672e9b8753d784dbe9687171faed258f 100644 (file)
@@ -177,7 +177,10 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     root_path = page.root_path,
     css_class = page.css_class,
     logo      = if layout.logo.is_empty() {
-        String::new()
+        format!("<a href='{}{}/index.html'>\
+                 <img src='{static_root_path}rust-logo{suffix}.png' alt='logo' width='100'></a>",
+                static_root_path=static_root_path,
+                suffix=page.resource_suffix)
     } else {
         format!("<a href='{}{}/index.html'>\
                  <img src='{}' alt='logo' width='100'></a>",
@@ -188,7 +191,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     description = page.description,
     keywords = page.keywords,
     favicon   = if layout.favicon.is_empty() {
-        String::new()
+        format!(r#"<link rel="shortcut icon" href="{static_root_path}favicon{suffix}.ico">"#,
+                static_root_path=static_root_path,
+                suffix=page.resource_suffix)
     } else {
         format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
     },
index 05a9a2d1312ae445c87f3f431d36bccc21fa4e9d..6b7f54044ca1d23b533653713b61115e28361099 100644 (file)
@@ -919,6 +919,115 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
     links
 }
 
+#[derive(Debug)]
+crate struct RustCodeBlock {
+    /// The range in the markdown that the code block occupies. Note that this includes the fences
+    /// for fenced code blocks.
+    pub range: Range<usize>,
+    /// The range in the markdown that the code within the code block occupies.
+    pub code: Range<usize>,
+    pub is_fenced: bool,
+    pub syntax: Option<String>,
+}
+
+/// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
+/// untagged (and assumed to be rust).
+crate fn rust_code_blocks(md: &str) -> Vec<RustCodeBlock> {
+    let mut code_blocks = vec![];
+
+    if md.is_empty() {
+        return code_blocks;
+    }
+
+    let mut opts = Options::empty();
+    opts.insert(OPTION_ENABLE_TABLES);
+    opts.insert(OPTION_ENABLE_FOOTNOTES);
+    let mut p = Parser::new_ext(md, opts);
+
+    let mut code_block_start = 0;
+    let mut code_start = 0;
+    let mut is_fenced = false;
+    let mut previous_offset = 0;
+    let mut in_rust_code_block = false;
+    while let Some(event) = p.next() {
+        let offset = p.get_offset();
+
+        match event {
+            Event::Start(Tag::CodeBlock(syntax)) => {
+                let lang_string = if syntax.is_empty() {
+                    LangString::all_false()
+                } else {
+                    LangString::parse(&*syntax, ErrorCodes::Yes)
+                };
+
+                if lang_string.rust {
+                    in_rust_code_block = true;
+
+                    code_start = offset;
+                    code_block_start = match md[previous_offset..offset].find("```") {
+                        Some(fence_idx) => {
+                            is_fenced = true;
+                            previous_offset + fence_idx
+                        }
+                        None => offset,
+                    };
+                }
+            }
+            Event::End(Tag::CodeBlock(syntax)) if in_rust_code_block => {
+                in_rust_code_block = false;
+
+                let code_block_end = if is_fenced {
+                    let fence_str = &md[previous_offset..offset]
+                        .chars()
+                        .rev()
+                        .collect::<String>();
+                    fence_str
+                        .find("```")
+                        .map(|fence_idx| offset - fence_idx)
+                        .unwrap_or_else(|| offset)
+                } else if md
+                    .as_bytes()
+                    .get(offset)
+                    .map(|b| *b == b'\n')
+                    .unwrap_or_default()
+                {
+                    offset - 1
+                } else {
+                    offset
+                };
+
+                let code_end = if is_fenced {
+                    previous_offset
+                } else {
+                    code_block_end
+                };
+
+                code_blocks.push(RustCodeBlock {
+                    is_fenced,
+                    range: Range {
+                        start: code_block_start,
+                        end: code_block_end,
+                    },
+                    code: Range {
+                        start: code_start,
+                        end: code_end,
+                    },
+                    syntax: if !syntax.is_empty() {
+                        Some(syntax.into_owned())
+                    } else {
+                        None
+                    },
+                });
+            }
+            _ => (),
+        }
+
+        previous_offset = offset;
+    }
+
+    code_blocks
+}
+
 #[derive(Clone, Default, Debug)]
 pub struct IdMap {
     map: FxHashMap<String, usize>,
index ad1659be3460e00fd153281d3fede04a3b172dab..86fb51419c270a581d9bff2a6a5d931831d26075 100644 (file)
@@ -789,6 +789,14 @@ fn write_shared(
         themes.insert(theme.to_owned());
     }
 
+    if (*cx.shared).layout.logo.is_empty() {
+        write(cx.dst.join(&format!("rust-logo{}.png", cx.shared.resource_suffix)),
+              static_files::RUST_LOGO)?;
+    }
+    if (*cx.shared).layout.favicon.is_empty() {
+        write(cx.dst.join(&format!("favicon{}.ico", cx.shared.resource_suffix)),
+              static_files::RUST_FAVICON)?;
+    }
     write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
           static_files::BRUSH_SVG)?;
     write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
@@ -2068,8 +2076,6 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
         themes.push(PathBuf::from("settings.css"));
         let mut layout = self.shared.layout.clone();
         layout.krate = String::new();
-        layout.logo = String::new();
-        layout.favicon = String::new();
         try_err!(layout::render(&mut w, &layout,
                                 &page, &sidebar, &settings,
                                 self.shared.css_file_extension.is_some(),
diff --git a/src/librustdoc/html/static/favicon.ico b/src/librustdoc/html/static/favicon.ico
new file mode 100644 (file)
index 0000000..b8ad237
Binary files /dev/null and b/src/librustdoc/html/static/favicon.ico differ
diff --git a/src/librustdoc/html/static/rust-logo.png b/src/librustdoc/html/static/rust-logo.png
new file mode 100644 (file)
index 0000000..74b4bd6
Binary files /dev/null and b/src/librustdoc/html/static/rust-logo.png differ
index f340590e5fe33b4dc4bd149f14a44e1c6c24a04b..a1d8cfacc54ada112d34a7cb52037559b4c522bd 100644 (file)
 /// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
 pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
 
+/// The contents of `rust-logo.png`, the default icon of the documentation.
+pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png");
+/// The contents of `favicon.ico`, the default favicon of the documentation.
+pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico");
+
 /// The built-in themes given to every documentation site.
 pub mod themes {
     /// The "light" theme, selected by default when no setting is available. Used as the basis for
index 4bbc01d32de3a8e0d52a022eb96cf673490295f7..f4149b5f35736805ee2b1c40c4ba29f519cee160 100644 (file)
@@ -3,6 +3,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
+#![feature(bind_by_move_pattern_guards)]
 #![feature(rustc_private)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
new file mode 100644 (file)
index 0000000..a013cc3
--- /dev/null
@@ -0,0 +1,109 @@
+use errors::Applicability;
+use syntax::parse::lexer::{TokenAndSpan, StringReader as Lexer};
+use syntax::parse::{ParseSess, token};
+use syntax::source_map::FilePathMapping;
+use syntax_pos::FileName;
+
+use clean;
+use core::DocContext;
+use fold::DocFolder;
+use html::markdown::{self, RustCodeBlock};
+use passes::Pass;
+
+pub const CHECK_CODE_BLOCK_SYNTAX: Pass =
+    Pass::early("check-code-block-syntax", check_code_block_syntax,
+                "validates syntax inside Rust code blocks");
+
+pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext) -> clean::Crate {
+    SyntaxChecker { cx }.fold_crate(krate)
+}
+
+struct SyntaxChecker<'a, 'tcx: 'a, 'rcx: 'a> {
+    cx: &'a DocContext<'a, 'tcx, 'rcx>,
+}
+
+impl<'a, 'tcx, 'rcx> SyntaxChecker<'a, 'tcx, 'rcx> {
+    fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) {
+        let sess = ParseSess::new(FilePathMapping::empty());
+        let source_file = sess.source_map().new_source_file(
+            FileName::Custom(String::from("doctest")),
+            dox[code_block.code].to_owned(),
+        );
+
+        let errors = Lexer::new_or_buffered_errs(&sess, source_file, None).and_then(|mut lexer| {
+            while let Ok(TokenAndSpan { tok, .. }) = lexer.try_next_token() {
+                if tok == token::Eof {
+                    break;
+                }
+            }
+
+            let errors = lexer.buffer_fatal_errors();
+
+            if !errors.is_empty() {
+                Err(errors)
+            } else {
+                Ok(())
+            }
+        });
+
+        if let Err(errors) = errors {
+            let mut diag = if let Some(sp) =
+                super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
+            {
+                let mut diag = self
+                    .cx
+                    .sess()
+                    .struct_span_warn(sp, "could not parse code block as Rust code");
+
+                for mut err in errors {
+                    diag.note(&format!("error from rustc: {}", err.message()));
+                    err.cancel();
+                }
+
+                if code_block.syntax.is_none() && code_block.is_fenced {
+                    let sp = sp.from_inner_byte_pos(0, 3);
+                    diag.span_suggestion_with_applicability(
+                        sp,
+                        "mark blocks that do not contain Rust code as text",
+                        String::from("```text"),
+                        Applicability::MachineApplicable,
+                    );
+                }
+
+                diag
+            } else {
+                // We couldn't calculate the span of the markdown block that had the error, so our
+                // diagnostics are going to be a bit lacking.
+                let mut diag = self.cx.sess().struct_span_warn(
+                    super::span_of_attrs(&item.attrs),
+                    "doc comment contains an invalid Rust code block",
+                );
+
+                for mut err in errors {
+                    // Don't bother reporting the error, because we can't show where it happened.
+                    err.cancel();
+                }
+
+                if code_block.syntax.is_none() && code_block.is_fenced {
+                    diag.help("mark blocks that do not contain Rust code as text: ```text");
+                }
+
+                diag
+            };
+
+            diag.emit();
+        }
+    }
+}
+
+impl<'a, 'tcx, 'rcx> DocFolder for SyntaxChecker<'a, 'tcx, 'rcx> {
+    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+        if let Some(dox) = &item.attrs.collapsed_doc_value() {
+            for code_block in markdown::rust_code_blocks(&dox) {
+                self.check_rust_syntax(&item, &dox, code_block);
+            }
+        }
+
+        self.fold_item_recur(item)
+    }
+}
index fdc1c0616187a8ed61acb26ad09afd2241d67a42..13ad05101e4b66bfee470a363e3646b16a3c74f5 100644 (file)
@@ -6,7 +6,7 @@
 use syntax::ast::{self, Ident, NodeId};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::symbol::Symbol;
-use syntax_pos::{self, DUMMY_SP};
+use syntax_pos::DUMMY_SP;
 
 use std::ops::Range;
 
@@ -16,6 +16,7 @@
 
 use clean::*;
 use passes::{look_for_tests, Pass};
+use super::span_of_attrs;
 
 pub const COLLECT_INTRA_DOC_LINKS: Pass =
     Pass::early("collect-intra-doc-links", collect_intra_doc_links,
@@ -430,8 +431,12 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
     let parent_scope = resolver.dummy_parent_scope();
     if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang,
                                                          &parent_scope, false, false) {
-        if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
-            return Some(def);
+        if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
+            // skip proc-macro stubs, they'll cause `get_macro` to crash
+        } else {
+            if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
+                return Some(def);
+            }
         }
     }
     if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {
@@ -440,28 +445,11 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
     None
 }
 
-pub fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
-    if attrs.doc_strings.is_empty() {
-        return DUMMY_SP;
-    }
-    let start = attrs.doc_strings[0].span();
-    let end = attrs.doc_strings.last().expect("No doc strings provided").span();
-    start.to(end)
-}
-
 /// Reports a resolution failure diagnostic.
 ///
-/// Ideally we can report the diagnostic with the actual span in the source where the link failure
-/// occurred. However, there's a mismatch between the span in the source code and the span in the
-/// markdown, so we have to do a bit of work to figure out the correspondence.
-///
-/// It's not too hard to find the span for sugared doc comments (`///` and `/**`), because the
-/// source will match the markdown exactly, excluding the comment markers. However, it's much more
-/// difficult to calculate the spans for unsugared docs, because we have to deal with escaping and
-/// other source features. So, we attempt to find the exact source span of the resolution failure
-/// in sugared docs, but use the span of the documentation attributes themselves for unsugared
-/// docs. Because this span might be overly large, we display the markdown line containing the
-/// failure as a note.
+/// If we cannot find the exact source span of the resolution failure, we use the span of the
+/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
+/// line containing the failure as a note as well.
 fn resolution_failure(
     cx: &DocContext,
     attrs: &Attributes,
@@ -473,54 +461,7 @@ fn resolution_failure(
     let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
 
     let mut diag = if let Some(link_range) = link_range {
-        let src = cx.sess().source_map().span_to_snippet(sp);
-        let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
-            DocFragment::SugaredDoc(..) => true,
-            _ => false,
-        });
-
-        if let (Ok(src), true) = (src, is_all_sugared_doc) {
-            // The number of markdown lines up to and including the resolution failure.
-            let num_lines = dox[..link_range.start].lines().count();
-
-            // We use `split_terminator('\n')` instead of `lines()` when counting bytes to ensure
-            // that DOS-style line endings do not cause the spans to be calculated incorrectly.
-            let mut src_lines = src.split_terminator('\n');
-            let mut md_lines = dox.split_terminator('\n').take(num_lines).peekable();
-
-            // The number of bytes from the start of the source span to the resolution failure that
-            // are *not* part of the markdown, like comment markers.
-            let mut extra_src_bytes = 0;
-
-            while let Some(md_line) = md_lines.next() {
-                loop {
-                    let source_line = src_lines
-                        .next()
-                        .expect("could not find markdown line in source");
-
-                    match source_line.find(md_line) {
-                        Some(offset) => {
-                            extra_src_bytes += if md_lines.peek().is_some() {
-                                source_line.len() - md_line.len()
-                            } else {
-                                offset
-                            };
-                            break;
-                        }
-                        None => {
-                            // Since this is a source line that doesn't include a markdown line,
-                            // we have to count the newline that we split from earlier.
-                            extra_src_bytes += source_line.len() + 1;
-                        }
-                    }
-                }
-            }
-
-            let sp = sp.from_inner_byte_pos(
-                link_range.start + extra_src_bytes,
-                link_range.end + extra_src_bytes,
-            );
-
+        if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
             let mut diag = cx.tcx.struct_span_lint_node(
                 lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
                 NodeId::from_u32(0),
index e897b9a7de58e32ca26c3202c1489246a93cb658..c9a3a2c003fe05415f11ef20ca3b676bffa45385 100644 (file)
@@ -8,6 +8,8 @@
 use std::mem;
 use std::fmt;
 use syntax::ast::NodeId;
+use syntax_pos::{DUMMY_SP, Span};
+use std::ops::Range;
 
 use clean::{self, GetDefId, Item};
 use core::{DocContext, DocAccessLevels};
@@ -16,8 +18,6 @@
 
 use html::markdown::{find_testable_code, ErrorCodes, LangString};
 
-use self::collect_intra_doc_links::span_of_attrs;
-
 mod collapse_docs;
 pub use self::collapse_docs::COLLAPSE_DOCS;
 
@@ -45,6 +45,9 @@
 mod collect_trait_impls;
 pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
 
+mod check_code_block_syntax;
+pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
+
 /// Represents a single pass.
 #[derive(Copy, Clone)]
 pub enum Pass {
@@ -135,6 +138,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
     COLLECT_INTRA_DOC_LINKS,
+    CHECK_CODE_BLOCK_SYNTAX,
     COLLECT_TRAIT_IMPLS,
 ];
 
@@ -145,6 +149,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
     "strip-hidden",
     "strip-private",
     "collect-intra-doc-links",
+    "check-code-block-syntax",
     "collapse-docs",
     "unindent-comments",
     "propagate-doc-cfg",
@@ -156,6 +161,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
     "check-private-items-doc-tests",
     "strip-priv-imports",
     "collect-intra-doc-links",
+    "check-code-block-syntax",
     "collapse-docs",
     "unindent-comments",
     "propagate-doc-cfg",
@@ -396,3 +402,94 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
         }
     }
 }
+
+/// Return a span encompassing all the given attributes.
+crate fn span_of_attrs(attrs: &clean::Attributes) -> Span {
+    if attrs.doc_strings.is_empty() {
+        return DUMMY_SP;
+    }
+    let start = attrs.doc_strings[0].span();
+    let end = attrs.doc_strings.last().expect("No doc strings provided").span();
+    start.to(end)
+}
+
+/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
+///
+/// This method will return `None` if we cannot construct a span from the source map or if the
+/// attributes are not all sugared doc comments. It's difficult to calculate the correct span in
+/// that case due to escaping and other source features.
+crate fn source_span_for_markdown_range(
+    cx: &DocContext,
+    markdown: &str,
+    md_range: &Range<usize>,
+    attrs: &clean::Attributes,
+) -> Option<Span> {
+    let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
+        clean::DocFragment::SugaredDoc(..) => true,
+        _ => false,
+    });
+
+    if !is_all_sugared_doc {
+        return None;
+    }
+
+    let snippet = cx
+        .sess()
+        .source_map()
+        .span_to_snippet(span_of_attrs(attrs))
+        .ok()?;
+
+    let starting_line = markdown[..md_range.start].lines().count() - 1;
+    let ending_line = markdown[..md_range.end].lines().count() - 1;
+
+    // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only
+    // we can treat CRLF and LF line endings the same way.
+    let mut src_lines = snippet.split_terminator('\n');
+    let md_lines = markdown.split_terminator('\n');
+
+    // The number of bytes from the source span to the markdown span that are not part
+    // of the markdown, like comment markers.
+    let mut start_bytes = 0;
+    let mut end_bytes = 0;
+
+    'outer: for (line_no, md_line) in md_lines.enumerate() {
+        loop {
+            let source_line = src_lines.next().expect("could not find markdown in source");
+            match source_line.find(md_line) {
+                Some(offset) => {
+                    if line_no == starting_line {
+                        start_bytes += offset;
+
+                        if starting_line == ending_line {
+                            break 'outer;
+                        }
+                    } else if line_no == ending_line {
+                        end_bytes += offset;
+                        break 'outer;
+                    } else if line_no < starting_line {
+                        start_bytes += source_line.len() - md_line.len();
+                    } else {
+                        end_bytes += source_line.len() - md_line.len();
+                    }
+                    break;
+                }
+                None => {
+                    // Since this is a source line that doesn't include a markdown line,
+                    // we have to count the newline that we split from earlier.
+                    if line_no <= starting_line {
+                        start_bytes += source_line.len() + 1;
+                    } else {
+                        end_bytes += source_line.len() + 1;
+                    }
+                }
+            }
+        }
+    }
+
+    let sp = span_of_attrs(attrs).from_inner_byte_pos(
+        md_range.start + start_bytes,
+        md_range.end + start_bytes + end_bytes,
+    );
+
+    Some(sp)
+}
index a7b9895177fe55c097b5317ee4e569ce7fb29996..22900c3067b112470cd02075ce76bbd5e9681e90 100644 (file)
@@ -11,7 +11,7 @@
 #[doc(inline)]
 pub use core::future::*;
 
-/// Wrap a future in a generator.
+/// Wrap a generator in a future.
 ///
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
index 83db3f347a761ff1ea9cc9b28f17804254617e75..82f3463dba0fc32b77329674168e2146eef96811 100644 (file)
@@ -7,11 +7,9 @@
 //! primitives](#primitives), [standard macros](#macros), [I/O] and
 //! [multithreading], among [many other things][other].
 //!
-//! `std` is available to all Rust crates by default, just as if each one
-//! contained an `extern crate std;` import at the [crate root]. Therefore the
+//! `std` is available to all Rust crates by default. Therefore the
 //! standard library can be accessed in [`use`] statements through the path
-//! `std`, as in [`use std::env`], or in expressions through the absolute path
-//! `::std`, as in [`::std::env::args`].
+//! `std`, as in [`use std::env`].
 //!
 //! # How to read this documentation
 //!
 //! [TCP]: net/struct.TcpStream.html
 //! [The Rust Prelude]: prelude/index.html
 //! [UDP]: net/struct.UdpSocket.html
-//! [`::std::env::args`]: env/fn.args.html
 //! [`Arc`]: sync/struct.Arc.html
 //! [owned slice]: boxed/index.html
 //! [`Cell`]: cell/struct.Cell.html
 //! [`thread`]: thread/index.html
 //! [`use std::env`]: env/index.html
 //! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#the-use-keyword-to-bring-paths-into-a-scope
-//! [crate root]: ../book/ch07-01-packages-and-crates-for-making-libraries-and-executables.html
 //! [crates.io]: https://crates.io
 //! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
 //! [files]: fs/struct.File.html
index 47c7b5dcbe64a374a27afe0d4b6e7255462d7239..810965fc1b85af02892ba3126eb8db80ccaed161 100644 (file)
@@ -56,4 +56,4 @@ pub mod mem {
     pub use sys::abi::mem::*;
 }
 
-pub use sys::ext::{io, arch};
+pub use sys::ext::{io, arch, ffi};
diff --git a/src/libstd/sys/sgx/ext/ffi.rs b/src/libstd/sys/sgx/ext/ffi.rs
new file mode 100644 (file)
index 0000000..7b0ffea
--- /dev/null
@@ -0,0 +1,109 @@
+//! SGX-specific extension to the primitives in the `std::ffi` module
+
+#![unstable(feature = "sgx_platform", issue = "56975")]
+
+use ffi::{OsStr, OsString};
+use mem;
+use sys::os_str::Buf;
+use sys_common::{FromInner, IntoInner, AsInner};
+
+/// SGX-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait OsStringExt {
+    /// Creates an [`OsString`] from a byte vector.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::OsString;
+    /// use std::os::unix::ffi::OsStringExt;
+    ///
+    /// let bytes = b"foo".to_vec();
+    /// let os_string = OsString::from_vec(bytes);
+    /// assert_eq!(os_string.to_str(), Some("foo"));
+    /// ```
+    ///
+    /// [`OsString`]: ../../../ffi/struct.OsString.html
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    fn from_vec(vec: Vec<u8>) -> Self;
+
+    /// Yields the underlying byte vector of this [`OsString`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::OsString;
+    /// use std::os::unix::ffi::OsStringExt;
+    ///
+    /// let mut os_string = OsString::new();
+    /// os_string.push("foo");
+    /// let bytes = os_string.into_vec();
+    /// assert_eq!(bytes, b"foo");
+    /// ```
+    ///
+    /// [`OsString`]: ../../../ffi/struct.OsString.html
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    fn into_vec(self) -> Vec<u8>;
+}
+
+#[unstable(feature = "sgx_platform", issue = "56975")]
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
+    }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+/// SGX-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait OsStrExt {
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    /// Creates an [`OsStr`] from a byte slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::OsStr;
+    /// use std::os::unix::ffi::OsStrExt;
+    ///
+    /// let bytes = b"foo";
+    /// let os_str = OsStr::from_bytes(bytes);
+    /// assert_eq!(os_str.to_str(), Some("foo"));
+    /// ```
+    ///
+    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
+    fn from_bytes(slice: &[u8]) -> &Self;
+
+    /// Gets the underlying byte view of the [`OsStr`] slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::OsStr;
+    /// use std::os::unix::ffi::OsStrExt;
+    ///
+    /// let mut os_str = OsStr::new("foo");
+    /// let bytes = os_str.as_bytes();
+    /// assert_eq!(bytes, b"foo");
+    /// ```
+    ///
+    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    fn as_bytes(&self) -> &[u8];
+}
+
+#[unstable(feature = "sgx_platform", issue = "56975")]
+impl OsStrExt for OsStr {
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
index 5489f6f56946e8a37f48312a423e8302bd06f9bc..51b2659da83e369f7e3ec1aa19aa37c2e64b63df 100644 (file)
@@ -2,3 +2,4 @@
 
 pub mod arch;
 pub mod io;
+pub mod ffi;
index 47874158ed9dfad0275d86adfabe3281291a963b..43ceae7d33b8d88d8c2e904531730db606f3ee6a 100644 (file)
@@ -1,3 +1,4 @@
+use alloc::{self, Layout};
 use num::NonZeroUsize;
 use slice;
 use str;
@@ -147,6 +148,7 @@ pub unsafe fn write_unlock(&self) {
         self.__write_unlock(rguard, wguard);
     }
 
+    // only used by __rust_rwlock_unlock below
     #[inline]
     unsafe fn unlock(&self) {
         let rguard = self.readers.lock();
@@ -164,6 +166,7 @@ pub unsafe fn destroy(&self) {}
 
 const EINVAL: i32 = 22;
 
+// used by libunwind port
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -190,6 +193,8 @@ pub unsafe fn destroy(&self) {}
     return 0;
 }
 
+// the following functions are also used by the libunwind port. They're
+// included here to make sure parallel codegen and LTO don't mess things up.
 #[no_mangle]
 pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
     if s < 0 {
@@ -206,6 +211,16 @@ pub unsafe fn destroy(&self) {}
     ::sys::abort_internal();
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
+    alloc::alloc(Layout::from_size_align_unchecked(size, align))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
+    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+}
+
 #[cfg(test)]
 mod tests {
 
index d48d701dd50eab0eabbf7f0d5f7c8b96882f90bc..742ffd12b883dc89035c73c81aae9379a2a02bf7 100644 (file)
@@ -33,30 +33,57 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     register_dtor_fallback(t, dtor);
 }
 
-// macOS's analog of the above linux function is this _tlv_atexit function.
-// The disassembly of thread_local globals in C++ (at least produced by
-// clang) will have this show up in the output.
+// This implementation is very similar to register_dtor_fallback in
+// sys_common/thread_local.rs. The main difference is that we want to hook into
+// macOS's analog of the above linux function, _tlv_atexit. OSX will run the
+// registered dtors before any TLS slots get freed, and when the main thread
+// exits.
+//
+// Unfortunately, calling _tlv_atexit while tls dtors are running is UB. The
+// workaround below is to register, via _tlv_atexit, a custom DTOR list once per
+// thread. thread_local dtors are pushed to the DTOR list without calling
+// _tlv_atexit.
 #[cfg(target_os = "macos")]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+    use cell::Cell;
+    use ptr;
+
+    #[thread_local]
+    static REGISTERED: Cell<bool> = Cell::new(false);
+    if !REGISTERED.get() {
+        _tlv_atexit(run_dtors, ptr::null_mut());
+        REGISTERED.set(true);
+    }
+
+    type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
+
+    #[thread_local]
+    static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
+    if DTORS.get().is_null() {
+        let v: Box<List> = box Vec::new();
+        DTORS.set(Box::into_raw(v));
+    }
+
     extern {
         fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
                        arg: *mut u8);
     }
-    _tlv_atexit(dtor, t);
+
+    let list: &mut List = &mut *DTORS.get();
+    list.push((t, dtor));
+
+    unsafe extern fn run_dtors(_: *mut u8) {
+        let mut ptr = DTORS.replace(ptr::null_mut());
+        while !ptr.is_null() {
+            let list = Box::from_raw(ptr);
+            for (ptr, dtor) in list.into_iter() {
+                dtor(ptr);
+            }
+            ptr = DTORS.replace(ptr::null_mut());
+        }
+    }
 }
 
 pub fn requires_move_before_drop() -> bool {
-    // The macOS implementation of TLS apparently had an odd aspect to it
-    // where the pointer we have may be overwritten while this destructor
-    // is running. Specifically if a TLS destructor re-accesses TLS it may
-    // trigger a re-initialization of all TLS variables, paving over at
-    // least some destroyed ones with initial values.
-    //
-    // This means that if we drop a TLS value in place on macOS that we could
-    // revert the value to its original state halfway through the
-    // destructor, which would be bad!
-    //
-    // Hence, we use `ptr::read` on macOS (to move to a "safe" location)
-    // instead of drop_in_place.
-    cfg!(target_os = "macos")
+    false
 }
index 8e8e9195cf471913fe742bf173b6c21a52536b5f..8a8159af2f1a6ee2b5c4e8eecb8995296dc65726 100644 (file)
@@ -1,10 +1,7 @@
 use cmp::Ordering;
 use fmt;
 use mem;
-use sync::Once;
 use sys::c;
-use sys::cvt;
-use sys_common::mul_div_u64;
 use time::Duration;
 use convert::TryInto;
 use core::hash::{Hash, Hasher};
@@ -14,7 +11,9 @@
 
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
 pub struct Instant {
-    t: c::LARGE_INTEGER,
+    // This duration is relative to an arbitrary microsecond epoch
+    // from the winapi QueryPerformanceCounter function.
+    t: Duration,
 }
 
 #[derive(Copy, Clone)]
@@ -33,11 +32,12 @@ pub struct SystemTime {
 
 impl Instant {
     pub fn now() -> Instant {
-        let mut t = Instant { t: 0 };
-        cvt(unsafe {
-            c::QueryPerformanceCounter(&mut t.t)
-        }).unwrap();
-        t
+        // High precision timing on windows operates in "Performance Counter"
+        // units, as returned by the WINAPI QueryPerformanceCounter function.
+        // These relate to seconds by a factor of QueryPerformanceFrequency.
+        // In order to keep unit conversions out of normal interval math, we
+        // measure in QPC units and immediately convert to nanoseconds.
+        perf_counter::PerformanceCounterInstant::now().into()
     }
 
     pub fn actually_monotonic() -> bool {
@@ -45,47 +45,31 @@ pub fn actually_monotonic() -> bool {
     }
 
     pub const fn zero() -> Instant {
-        Instant { t: 0 }
+        Instant { t: Duration::from_secs(0) }
     }
 
     pub fn sub_instant(&self, other: &Instant) -> Duration {
-        // Values which are +- 1 need to be considered as basically the same
-        // units in time due to various measurement oddities, according to
-        // Windows [1]
-        //
-        // [1]:
-        // https://msdn.microsoft.com/en-us/library/windows/desktop
-        //                           /dn553408%28v=vs.85%29.aspx#guidance
-        if other.t > self.t && other.t - self.t == 1 {
+        // On windows there's a threshold below which we consider two timestamps
+        // equivalent due to measurement error. For more details + doc link,
+        // check the docs on epsilon.
+        let epsilon =
+            perf_counter::PerformanceCounterInstant::epsilon();
+        if other.t > self.t && other.t - self.t <= epsilon {
             return Duration::new(0, 0)
         }
-        let diff = (self.t as u64).checked_sub(other.t as u64)
-                                  .expect("specified instant was later than \
-                                           self");
-        let nanos = mul_div_u64(diff, NANOS_PER_SEC, frequency() as u64);
-        Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
+        self.t.checked_sub(other.t)
+              .expect("specified instant was later than self")
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
-        let freq = frequency() as u64;
-        let t = other.as_secs()
-            .checked_mul(freq)?
-            .checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))?
-            .checked_add(self.t as u64)?;
         Some(Instant {
-            t: t as c::LARGE_INTEGER,
+            t: self.t.checked_add(*other)?
         })
     }
 
     pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
-        let freq = frequency() as u64;
-        let t = other.as_secs().checked_mul(freq).and_then(|i| {
-            (self.t as u64).checked_sub(i)
-        }).and_then(|i| {
-            i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))
-        })?;
         Some(Instant {
-            t: t as c::LARGE_INTEGER,
+            t: self.t.checked_sub(*other)?
         })
     }
 }
@@ -186,14 +170,60 @@ fn intervals2dur(intervals: u64) -> Duration {
                   ((intervals % INTERVALS_PER_SEC) * 100) as u32)
 }
 
-fn frequency() -> c::LARGE_INTEGER {
-    static mut FREQUENCY: c::LARGE_INTEGER = 0;
-    static ONCE: Once = Once::new();
+mod perf_counter {
+    use super::{NANOS_PER_SEC};
+    use sync::Once;
+    use sys_common::mul_div_u64;
+    use sys::c;
+    use sys::cvt;
+    use time::Duration;
+
+    pub struct PerformanceCounterInstant {
+        ts: c::LARGE_INTEGER
+    }
+    impl PerformanceCounterInstant {
+        pub fn now() -> Self {
+            Self {
+                ts: query()
+            }
+        }
 
-    unsafe {
-        ONCE.call_once(|| {
-            cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
-        });
-        FREQUENCY
+        // Per microsoft docs, the margin of error for cross-thread time comparisons
+        // using QueryPerformanceCounter is 1 "tick" -- defined as 1/frequency().
+        // Reference: https://docs.microsoft.com/en-us/windows/desktop/SysInfo
+        //                   /acquiring-high-resolution-time-stamps
+        pub fn epsilon() -> Duration {
+            let epsilon = NANOS_PER_SEC / (frequency() as u64);
+            Duration::from_nanos(epsilon)
+        }
+    }
+    impl From<PerformanceCounterInstant> for super::Instant {
+        fn from(other: PerformanceCounterInstant) -> Self {
+            let freq = frequency() as u64;
+            let instant_nsec = mul_div_u64(other.ts as u64, NANOS_PER_SEC, freq);
+            Self {
+                t: Duration::from_nanos(instant_nsec)
+            }
+        }
+    }
+
+    fn frequency() -> c::LARGE_INTEGER {
+        static mut FREQUENCY: c::LARGE_INTEGER = 0;
+        static ONCE: Once = Once::new();
+
+        unsafe {
+            ONCE.call_once(|| {
+                cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
+            });
+            FREQUENCY
+        }
+    }
+
+    fn query() -> c::LARGE_INTEGER {
+        let mut qpc_value: c::LARGE_INTEGER = 0;
+        cvt(unsafe {
+            c::QueryPerformanceCounter(&mut qpc_value)
+        }).unwrap();
+        qpc_value
     }
 }
index efd231e0176790101d926514ee19085e342c2c79..5d2eb5f8e7320e09210a927efd3411ff3b0b9791 100644 (file)
@@ -69,9 +69,6 @@
 ///    destroyed, but not all platforms have this guard. Those platforms that do
 ///    not guard typically have a synthetic limit after which point no more
 ///    destructors are run.
-/// 3. On macOS, initializing TLS during destruction of other TLS slots can
-///    sometimes cancel *all* destructors for the current thread, whether or not
-///    the slots have already had their destructors run or not.
 ///
 /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
 /// [`thread_local!`]: ../../std/macro.thread_local.html
@@ -604,11 +601,8 @@ fn drop(&mut self) {
     }
 
     // Note that this test will deadlock if TLS destructors aren't run (this
-    // requires the destructor to be run to pass the test). macOS has a known bug
-    // where dtors-in-dtors may cancel other destructors, so we just ignore this
-    // test on macOS.
+    // requires the destructor to be run to pass the test).
     #[test]
-    #[cfg_attr(target_os = "macos", ignore)]
     fn dtors_in_dtors_in_dtors() {
         struct S1(Sender<()>);
         thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
index 507ea395c6c6c409d15b0be4ec40bb370f9d115b..23924559fcc248c447bb54fc268a115dc07d4da4 100644 (file)
@@ -610,6 +610,15 @@ fn instant_math() {
         assert_eq!(a + year, a.checked_add(year).unwrap());
     }
 
+    #[test]
+    fn instant_math_is_associative() {
+        let now = Instant::now();
+        let offset = Duration::from_millis(5);
+        // Changing the order of instant math shouldn't change the results,
+        // especially when the expression reduces to X + identity.
+        assert_eq!((now + offset) - now, (now - now) + offset);
+    }
+
     #[test]
     #[should_panic]
     fn instant_duration_panic() {
index 99ab9fbcf5fa029049ad9d156cc20a55a15c28db..af521848e9057f04beb511691186156bba4cbf6d 100644 (file)
@@ -15,7 +15,7 @@
 use source_map::{dummy_spanned, respan, Spanned};
 use symbol::{keywords, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
-use tokenstream::{ThinTokenStream, TokenStream};
+use tokenstream::TokenStream;
 use ThinVec;
 
 use rustc_data_structures::fx::FxHashSet;
@@ -136,10 +136,24 @@ pub enum GenericArgs {
     /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
     AngleBracketed(AngleBracketedArgs),
     /// The `(A,B)` and `C` in `Foo(A,B) -> C`
-    Parenthesized(ParenthesisedArgs),
+    Parenthesized(ParenthesizedArgs),
 }
 
 impl GenericArgs {
+    pub fn is_parenthesized(&self) -> bool {
+        match *self {
+            Parenthesized(..) => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_angle_bracketed(&self) -> bool {
+        match *self {
+            AngleBracketed(..) => true,
+            _ => false,
+        }
+    }
+
     pub fn span(&self) -> Span {
         match *self {
             AngleBracketed(ref data) => data.span,
@@ -173,7 +187,7 @@ fn into(self) -> Option<P<GenericArgs>> {
     }
 }
 
-impl Into<Option<P<GenericArgs>>> for ParenthesisedArgs {
+impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
     fn into(self) -> Option<P<GenericArgs>> {
         Some(P(GenericArgs::Parenthesized(self)))
     }
@@ -181,7 +195,7 @@ fn into(self) -> Option<P<GenericArgs>> {
 
 /// A path like `Foo(A,B) -> C`
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct ParenthesisedArgs {
+pub struct ParenthesizedArgs {
     /// Overall span
     pub span: Span,
 
@@ -192,6 +206,16 @@ pub struct ParenthesisedArgs {
     pub output: Option<P<Ty>>,
 }
 
+impl ParenthesizedArgs {
+    pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
+        AngleBracketedArgs {
+            span: self.span,
+            args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(),
+            bindings: vec![],
+        }
+    }
+}
+
 // hack to ensure that we don't try to access the private parts of `NodeId` in this module
 mod node_id_inner {
     use rustc_data_structures::indexed_vec::Idx;
@@ -1216,7 +1240,7 @@ pub enum Movability {
 pub struct Mac_ {
     pub path: Path,
     pub delim: MacDelimiter,
-    pub tts: ThinTokenStream,
+    pub tts: TokenStream,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
@@ -1228,13 +1252,13 @@ pub enum MacDelimiter {
 
 impl Mac_ {
     pub fn stream(&self) -> TokenStream {
-        self.tts.stream()
+        self.tts.clone()
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct MacroDef {
-    pub tokens: ThinTokenStream,
+    pub tokens: TokenStream,
     pub legacy: bool,
 }
 
@@ -1285,6 +1309,8 @@ pub enum LitKind {
     FloatUnsuffixed(Symbol),
     /// A boolean literal.
     Bool(bool),
+    /// A recovered character literal that contains mutliple `char`s, most likely a typo.
+    Err(Symbol),
 }
 
 impl LitKind {
@@ -1321,6 +1347,7 @@ pub fn is_unsuffixed(&self) -> bool {
             | LitKind::ByteStr(..)
             | LitKind::Byte(..)
             | LitKind::Char(..)
+            | LitKind::Err(..)
             | LitKind::Int(_, LitIntType::Unsuffixed)
             | LitKind::FloatUnsuffixed(..)
             | LitKind::Bool(..) => true,
index f83c1ec1455239e6bb973ee84fc1c15bc704421f..e5ce6a3f19a49f7ed40276b4cbcfa739f830ef38 100644 (file)
@@ -570,7 +570,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItemKind>
             }
             Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => {
                 tokens.next();
-                tts.stream()
+                tts.clone()
             }
             _ => return Some(MetaItemKind::Word),
         };
@@ -666,6 +666,7 @@ fn token(&self) -> Token {
             } else {
                 "false"
             })), false),
+            LitKind::Err(val) => Token::Literal(token::Lit::Err(val), None),
         }
     }
 
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
deleted file mode 100644 (file)
index c312414..0000000
+++ /dev/null
@@ -1,892 +0,0 @@
-use ast::{self, Arg, Arm, Block, Expr, Item, Pat, Stmt, Ty};
-use source_map::respan;
-use syntax_pos::{Span, DUMMY_SP};
-use ext::base::ExtCtxt;
-use ext::base;
-use ext::build::AstBuilder;
-use parse::parser::{Parser, PathStyle};
-use parse::token;
-use ptr::P;
-use tokenstream::{DelimSpan, TokenStream, TokenTree};
-
-/// Quasiquoting works via token trees.
-///
-/// This is registered as a set of expression syntax extension called quote!
-/// that lifts its argument token-tree to an AST representing the
-/// construction of the same token tree, with `token::SubstNt` interpreted
-/// as antiquotes (splices).
-
-pub mod rt {
-    use ast;
-    use source_map::Spanned;
-    use ext::base::ExtCtxt;
-    use parse::{self, classify};
-    use parse::token::{self, Token};
-    use ptr::P;
-    use symbol::Symbol;
-    use ThinVec;
-
-    use tokenstream::{DelimSpan, TokenTree, TokenStream};
-
-    pub use parse::new_parser_from_tts;
-    pub use syntax_pos::{BytePos, Span, DUMMY_SP, FileName};
-    pub use source_map::{dummy_spanned};
-
-    pub trait ToTokens {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
-    }
-
-    impl ToTokens for TokenTree {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![self.clone()]
-        }
-    }
-
-    impl<T: ToTokens> ToTokens for Vec<T> {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            self.iter().flat_map(|t| t.to_tokens(cx)).collect()
-        }
-    }
-
-    impl<T: ToTokens> ToTokens for Spanned<T> {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            // FIXME: use the span?
-            self.node.to_tokens(cx)
-        }
-    }
-
-    impl<T: ToTokens> ToTokens for Option<T> {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            match *self {
-                Some(ref t) => t.to_tokens(cx),
-                None => Vec::new(),
-            }
-        }
-    }
-
-    impl ToTokens for ast::Ident {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, Token::from_ast_ident(*self))]
-        }
-    }
-
-    impl ToTokens for ast::Path {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtPath(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Ty {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtTy(P(self.clone()));
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Block {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtBlock(P(self.clone()));
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Generics {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtGenerics(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::WhereClause {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtWhereClause(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for P<ast::Item> {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtItem(self.clone());
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::ImplItem {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtImplItem(self.clone());
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for P<ast::ImplItem> {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtImplItem((**self).clone());
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::TraitItem {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtTraitItem(self.clone());
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Stmt {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtStmt(self.clone());
-            let mut tts = vec![TokenTree::Token(self.span, Token::interpolated(nt))];
-
-            // Some statements require a trailing semicolon.
-            if classify::stmt_ends_with_semi(&self.node) {
-                tts.push(TokenTree::Token(self.span, token::Semi));
-            }
-
-            tts
-        }
-    }
-
-    impl ToTokens for P<ast::Expr> {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtExpr(self.clone());
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for P<ast::Pat> {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtPat(self.clone());
-            vec![TokenTree::Token(self.span, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Arm {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtArm(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Arg {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtArg(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for P<ast::Block> {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtBlock(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Lifetime {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.ident.span, token::Lifetime(self.ident))]
-        }
-    }
-
-    macro_rules! impl_to_tokens_slice {
-        ($t: ty, $sep: expr) => {
-            impl ToTokens for [$t] {
-                fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-                    let mut v = vec![];
-                    for (i, x) in self.iter().enumerate() {
-                        if i > 0 {
-                            v.extend_from_slice(&$sep);
-                        }
-                        v.extend(x.to_tokens(cx));
-                    }
-                    v
-                }
-            }
-        };
-    }
-
-    impl_to_tokens_slice! { ast::Ty, [TokenTree::Token(DUMMY_SP, token::Comma)] }
-    impl_to_tokens_slice! { P<ast::Item>, [] }
-    impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] }
-
-    impl ToTokens for ast::MetaItem {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let nt = token::NtMeta(self.clone());
-            vec![TokenTree::Token(DUMMY_SP, Token::interpolated(nt))]
-        }
-    }
-
-    impl ToTokens for ast::Attribute {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let mut r = vec![];
-            // FIXME: The spans could be better
-            r.push(TokenTree::Token(self.span, token::Pound));
-            if self.style == ast::AttrStyle::Inner {
-                r.push(TokenTree::Token(self.span, token::Not));
-            }
-            let mut inner = Vec::new();
-            for (i, segment) in self.path.segments.iter().enumerate() {
-                if i > 0 {
-                    inner.push(TokenTree::Token(self.span, token::Colon).into());
-                }
-                inner.push(TokenTree::Token(
-                    self.span, token::Token::from_ast_ident(segment.ident)
-                ).into());
-            }
-            self.tokens.clone().append_to_tree_and_joint_vec(&mut inner);
-
-            let delim_span = DelimSpan::from_single(self.span);
-            r.push(TokenTree::Delimited(
-                delim_span, token::Bracket, TokenStream::new(inner).into()
-            ));
-            r
-        }
-    }
-
-    impl ToTokens for str {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            let lit = ast::LitKind::Str(Symbol::intern(self), ast::StrStyle::Cooked);
-            dummy_spanned(lit).to_tokens(cx)
-        }
-    }
-
-    impl ToTokens for () {
-        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![
-                TokenTree::Delimited(DelimSpan::dummy(), token::Paren, TokenStream::empty().into())
-            ]
-        }
-    }
-
-    impl ToTokens for ast::Lit {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            // FIXME: This is wrong
-            P(ast::Expr {
-                id: ast::DUMMY_NODE_ID,
-                node: ast::ExprKind::Lit(self.clone()),
-                span: DUMMY_SP,
-                attrs: ThinVec::new(),
-            }).to_tokens(cx)
-        }
-    }
-
-    impl ToTokens for bool {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            dummy_spanned(ast::LitKind::Bool(*self)).to_tokens(cx)
-        }
-    }
-
-    impl ToTokens for char {
-        fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            dummy_spanned(ast::LitKind::Char(*self)).to_tokens(cx)
-        }
-    }
-
-    macro_rules! impl_to_tokens_int {
-        (signed, $t:ty, $tag:expr) => (
-            impl ToTokens for $t {
-                fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-                    let val = if *self < 0 {
-                        -self
-                    } else {
-                        *self
-                    };
-                    let lit = ast::LitKind::Int(val as u128, ast::LitIntType::Signed($tag));
-                    let lit = P(ast::Expr {
-                        id: ast::DUMMY_NODE_ID,
-                        node: ast::ExprKind::Lit(dummy_spanned(lit)),
-                        span: DUMMY_SP,
-                        attrs: ThinVec::new(),
-                    });
-                    if *self >= 0 {
-                        return lit.to_tokens(cx);
-                    }
-                    P(ast::Expr {
-                        id: ast::DUMMY_NODE_ID,
-                        node: ast::ExprKind::Unary(ast::UnOp::Neg, lit),
-                        span: DUMMY_SP,
-                        attrs: ThinVec::new(),
-                    }).to_tokens(cx)
-                }
-            }
-        );
-        (unsigned, $t:ty, $tag:expr) => (
-            impl ToTokens for $t {
-                fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-                    let lit = ast::LitKind::Int(*self as u128, ast::LitIntType::Unsigned($tag));
-                    dummy_spanned(lit).to_tokens(cx)
-                }
-            }
-        );
-    }
-
-    impl_to_tokens_int! { signed, isize, ast::IntTy::Isize }
-    impl_to_tokens_int! { signed, i8,  ast::IntTy::I8 }
-    impl_to_tokens_int! { signed, i16, ast::IntTy::I16 }
-    impl_to_tokens_int! { signed, i32, ast::IntTy::I32 }
-    impl_to_tokens_int! { signed, i64, ast::IntTy::I64 }
-
-    impl_to_tokens_int! { unsigned, usize, ast::UintTy::Usize }
-    impl_to_tokens_int! { unsigned, u8,   ast::UintTy::U8 }
-    impl_to_tokens_int! { unsigned, u16,  ast::UintTy::U16 }
-    impl_to_tokens_int! { unsigned, u32,  ast::UintTy::U32 }
-    impl_to_tokens_int! { unsigned, u64,  ast::UintTy::U64 }
-
-    pub trait ExtParseUtils {
-        fn parse_item(&self, s: String) -> P<ast::Item>;
-        fn parse_expr(&self, s: String) -> P<ast::Expr>;
-        fn parse_stmt(&self, s: String) -> ast::Stmt;
-        fn parse_tts(&self, s: String) -> Vec<TokenTree>;
-    }
-
-    impl<'a> ExtParseUtils for ExtCtxt<'a> {
-        fn parse_item(&self, s: String) -> P<ast::Item> {
-            panictry!(parse::parse_item_from_source_str(
-                FileName::quote_expansion_source_code(&s),
-                s,
-                self.parse_sess())).expect("parse error")
-        }
-
-        fn parse_stmt(&self, s: String) -> ast::Stmt {
-            panictry!(parse::parse_stmt_from_source_str(
-                FileName::quote_expansion_source_code(&s),
-                s,
-                self.parse_sess())).expect("parse error")
-        }
-
-        fn parse_expr(&self, s: String) -> P<ast::Expr> {
-            panictry!(parse::parse_expr_from_source_str(
-                FileName::quote_expansion_source_code(&s),
-                s,
-                self.parse_sess()))
-        }
-
-        fn parse_tts(&self, s: String) -> Vec<TokenTree> {
-            let source_name = FileName::quote_expansion_source_code(&s);
-            parse::parse_stream_from_source_str(source_name, s, self.parse_sess(), None)
-                .into_trees().collect()
-        }
-    }
-}
-
-// Replaces `Token::OpenDelim .. Token::CloseDelim` with `TokenTree::Delimited(..)`.
-pub fn unflatten(tts: Vec<TokenTree>) -> Vec<TokenTree> {
-    let mut results = Vec::new();
-    let mut result = Vec::new();
-    let mut open_span = DUMMY_SP;
-    for tree in tts {
-        match tree {
-            TokenTree::Token(span, token::OpenDelim(..)) => {
-                open_span = span;
-                results.push(::std::mem::replace(&mut result, Vec::new()));
-            }
-            TokenTree::Token(span, token::CloseDelim(delim)) => {
-                let delim_span = DelimSpan::from_pair(open_span, span);
-                let tree = TokenTree::Delimited(
-                    delim_span,
-                    delim,
-                    result.into_iter().map(TokenStream::from).collect::<TokenStream>().into(),
-                );
-                result = results.pop().unwrap();
-                result.push(tree);
-            }
-            tree => result.push(tree),
-        }
-    }
-    result
-}
-
-// These panicking parsing functions are used by the quote_*!() syntax extensions,
-// but shouldn't be used otherwise.
-pub fn parse_expr_panic(parser: &mut Parser) -> P<Expr> {
-    panictry!(parser.parse_expr())
-}
-
-pub fn parse_item_panic(parser: &mut Parser) -> Option<P<Item>> {
-    panictry!(parser.parse_item())
-}
-
-pub fn parse_pat_panic(parser: &mut Parser) -> P<Pat> {
-    panictry!(parser.parse_pat(None))
-}
-
-pub fn parse_arm_panic(parser: &mut Parser) -> Arm {
-    panictry!(parser.parse_arm())
-}
-
-pub fn parse_ty_panic(parser: &mut Parser) -> P<Ty> {
-    panictry!(parser.parse_ty())
-}
-
-pub fn parse_stmt_panic(parser: &mut Parser) -> Option<Stmt> {
-    panictry!(parser.parse_stmt())
-}
-
-pub fn parse_attribute_panic(parser: &mut Parser, permit_inner: bool) -> ast::Attribute {
-    panictry!(parser.parse_attribute(permit_inner))
-}
-
-pub fn parse_arg_panic(parser: &mut Parser) -> Arg {
-    panictry!(parser.parse_arg())
-}
-
-pub fn parse_block_panic(parser: &mut Parser) -> P<Block> {
-    panictry!(parser.parse_block())
-}
-
-pub fn parse_meta_item_panic(parser: &mut Parser) -> ast::MetaItem {
-    panictry!(parser.parse_meta_item())
-}
-
-pub fn parse_path_panic(parser: &mut Parser, mode: PathStyle) -> ast::Path {
-    panictry!(parser.parse_path(mode))
-}
-
-pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt,
-                                sp: Span,
-                                tts: &[TokenTree])
-                                -> Box<dyn base::MacResult+'cx> {
-    let (cx_expr, expr) = expand_tts(cx, sp, tts);
-    let expanded = expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"]]);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt,
-                              sp: Span,
-                              tts: &[TokenTree])
-                              -> Box<dyn base::MacResult+'cx> {
-    let expanded = expand_parse_call(cx, sp, "parse_expr_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_item<'cx>(cx: &'cx mut ExtCtxt,
-                              sp: Span,
-                              tts: &[TokenTree])
-                              -> Box<dyn base::MacResult+'cx> {
-    let expanded = expand_parse_call(cx, sp, "parse_item_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_pat<'cx>(cx: &'cx mut ExtCtxt,
-                             sp: Span,
-                             tts: &[TokenTree])
-                             -> Box<dyn base::MacResult+'cx> {
-    let expanded = expand_parse_call(cx, sp, "parse_pat_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_arm(cx: &mut ExtCtxt,
-                        sp: Span,
-                        tts: &[TokenTree])
-                        -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_arm_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_ty(cx: &mut ExtCtxt,
-                       sp: Span,
-                       tts: &[TokenTree])
-                       -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_ty_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_stmt(cx: &mut ExtCtxt,
-                         sp: Span,
-                         tts: &[TokenTree])
-                         -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_stmt_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_attr(cx: &mut ExtCtxt,
-                         sp: Span,
-                         tts: &[TokenTree])
-                         -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_attribute_panic",
-                                    vec![cx.expr_bool(sp, true)], tts);
-
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_arg(cx: &mut ExtCtxt,
-                        sp: Span,
-                        tts: &[TokenTree])
-                        -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_arg_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_block(cx: &mut ExtCtxt,
-                        sp: Span,
-                        tts: &[TokenTree])
-                        -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_block_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_meta_item(cx: &mut ExtCtxt,
-                        sp: Span,
-                        tts: &[TokenTree])
-                        -> Box<dyn base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_meta_item_panic", vec![], tts);
-    base::MacEager::expr(expanded)
-}
-
-pub fn expand_quote_path(cx: &mut ExtCtxt,
-                        sp: Span,
-                        tts: &[TokenTree])
-                        -> Box<dyn base::MacResult+'static> {
-    let mode = mk_parser_path(cx, sp, &["PathStyle", "Type"]);
-    let expanded = expand_parse_call(cx, sp, "parse_path_panic", vec![mode], tts);
-    base::MacEager::expr(expanded)
-}
-
-fn ids_ext(strs: Vec<String>) -> Vec<ast::Ident> {
-    strs.iter().map(|s| ast::Ident::from_str(s)).collect()
-}
-
-fn id_ext(s: &str) -> ast::Ident {
-    ast::Ident::from_str(s)
-}
-
-// Lift an ident to the expr that evaluates to that ident.
-fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P<ast::Expr> {
-    let e_str = cx.expr_str(sp, ident.name);
-    cx.expr_method_call(sp,
-                        cx.expr_ident(sp, id_ext("ext_cx")),
-                        id_ext("ident_of"),
-                        vec![e_str])
-}
-
-// Lift a name to the expr that evaluates to that name
-fn mk_name(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P<ast::Expr> {
-    let e_str = cx.expr_str(sp, ident.name);
-    cx.expr_method_call(sp,
-                        cx.expr_ident(sp, id_ext("ext_cx")),
-                        id_ext("name_of"),
-                        vec![e_str])
-}
-
-fn mk_tt_path(cx: &ExtCtxt, sp: Span, name: &str) -> P<ast::Expr> {
-    let idents = vec![id_ext("syntax"), id_ext("tokenstream"), id_ext("TokenTree"), id_ext(name)];
-    cx.expr_path(cx.path_global(sp, idents))
-}
-
-fn mk_token_path(cx: &ExtCtxt, sp: Span, name: &str) -> P<ast::Expr> {
-    let idents = vec![id_ext("syntax"), id_ext("parse"), id_ext("token"), id_ext(name)];
-    cx.expr_path(cx.path_global(sp, idents))
-}
-
-fn mk_parser_path(cx: &ExtCtxt, sp: Span, names: &[&str]) -> P<ast::Expr> {
-    let mut idents = vec![id_ext("syntax"), id_ext("parse"), id_ext("parser")];
-    idents.extend(names.iter().cloned().map(id_ext));
-    cx.expr_path(cx.path_global(sp, idents))
-}
-
-fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOpToken) -> P<ast::Expr> {
-    let name = match bop {
-        token::Plus     => "Plus",
-        token::Minus    => "Minus",
-        token::Star     => "Star",
-        token::Slash    => "Slash",
-        token::Percent  => "Percent",
-        token::Caret    => "Caret",
-        token::And      => "And",
-        token::Or       => "Or",
-        token::Shl      => "Shl",
-        token::Shr      => "Shr"
-    };
-    mk_token_path(cx, sp, name)
-}
-
-fn mk_delim(cx: &ExtCtxt, sp: Span, delim: token::DelimToken) -> P<ast::Expr> {
-    let name = match delim {
-        token::Paren   => "Paren",
-        token::Bracket => "Bracket",
-        token::Brace   => "Brace",
-        token::NoDelim => "NoDelim",
-    };
-    mk_token_path(cx, sp, name)
-}
-
-#[allow(non_upper_case_globals)]
-fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
-    macro_rules! mk_lit {
-        ($name: expr, $suffix: expr, $content: expr $(, $count: expr)*) => {{
-            let name = mk_name(cx, sp, ast::Ident::with_empty_ctxt($content));
-            let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![
-                name $(, cx.expr_u16(sp, $count))*
-            ]);
-            let suffix = match $suffix {
-                Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::with_empty_ctxt(name))),
-                None => cx.expr_none(sp)
-            };
-            cx.expr_call(sp, mk_token_path(cx, sp, "Literal"), vec![inner, suffix])
-        }}
-    }
-
-    let name = match *tok {
-        token::BinOp(binop) => {
-            return cx.expr_call(sp, mk_token_path(cx, sp, "BinOp"), vec![mk_binop(cx, sp, binop)]);
-        }
-        token::BinOpEq(binop) => {
-            return cx.expr_call(sp, mk_token_path(cx, sp, "BinOpEq"),
-                                vec![mk_binop(cx, sp, binop)]);
-        }
-
-        token::OpenDelim(delim) => {
-            return cx.expr_call(sp, mk_token_path(cx, sp, "OpenDelim"),
-                                vec![mk_delim(cx, sp, delim)]);
-        }
-        token::CloseDelim(delim) => {
-            return cx.expr_call(sp, mk_token_path(cx, sp, "CloseDelim"),
-                                vec![mk_delim(cx, sp, delim)]);
-        }
-
-        token::Literal(token::Byte(i), suf) => return mk_lit!("Byte", suf, i),
-        token::Literal(token::Char(i), suf) => return mk_lit!("Char", suf, i),
-        token::Literal(token::Integer(i), suf) => return mk_lit!("Integer", suf, i),
-        token::Literal(token::Float(i), suf) => return mk_lit!("Float", suf, i),
-        token::Literal(token::Str_(i), suf) => return mk_lit!("Str_", suf, i),
-        token::Literal(token::StrRaw(i, n), suf) => return mk_lit!("StrRaw", suf, i, n),
-        token::Literal(token::ByteStr(i), suf) => return mk_lit!("ByteStr", suf, i),
-        token::Literal(token::ByteStrRaw(i, n), suf) => return mk_lit!("ByteStrRaw", suf, i, n),
-
-        token::Ident(ident, is_raw) => {
-            return cx.expr_call(sp,
-                                mk_token_path(cx, sp, "Ident"),
-                                vec![mk_ident(cx, sp, ident), cx.expr_bool(sp, is_raw)]);
-        }
-
-        token::Lifetime(ident) => {
-            return cx.expr_call(sp,
-                                mk_token_path(cx, sp, "Lifetime"),
-                                vec![mk_ident(cx, sp, ident)]);
-        }
-
-        token::DocComment(ident) => {
-            return cx.expr_call(sp,
-                                mk_token_path(cx, sp, "DocComment"),
-                                vec![mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident))]);
-        }
-
-        token::Interpolated(_) => {
-            cx.span_err(sp, "quote! with interpolated token");
-            // Use dummy name.
-            "Interpolated"
-        }
-
-        token::Eq           => "Eq",
-        token::Lt           => "Lt",
-        token::Le           => "Le",
-        token::EqEq         => "EqEq",
-        token::Ne           => "Ne",
-        token::Ge           => "Ge",
-        token::Gt           => "Gt",
-        token::AndAnd       => "AndAnd",
-        token::OrOr         => "OrOr",
-        token::Not          => "Not",
-        token::Tilde        => "Tilde",
-        token::At           => "At",
-        token::Dot          => "Dot",
-        token::DotDot       => "DotDot",
-        token::DotDotDot    => "DotDotDot",
-        token::DotDotEq     => "DotDotEq",
-        token::Comma        => "Comma",
-        token::Semi         => "Semi",
-        token::Colon        => "Colon",
-        token::ModSep       => "ModSep",
-        token::RArrow       => "RArrow",
-        token::LArrow       => "LArrow",
-        token::FatArrow     => "FatArrow",
-        token::Pound        => "Pound",
-        token::Dollar       => "Dollar",
-        token::Question     => "Question",
-        token::SingleQuote  => "SingleQuote",
-        token::Eof          => "Eof",
-
-        token::Whitespace | token::Comment | token::Shebang(_) => {
-            panic!("unhandled token in quote!");
-        }
-    };
-    mk_token_path(cx, sp, name)
-}
-
-fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, quoted: bool) -> Vec<ast::Stmt> {
-    match *tt {
-        TokenTree::Token(sp, token::Ident(ident, _)) if quoted => {
-            // tt.extend($ident.to_tokens(ext_cx))
-
-            let e_to_toks =
-                cx.expr_method_call(sp,
-                                    cx.expr_ident(sp, ident),
-                                    id_ext("to_tokens"),
-                                    vec![cx.expr_ident(sp, id_ext("ext_cx"))]);
-            let e_to_toks =
-                cx.expr_method_call(sp, e_to_toks, id_ext("into_iter"), vec![]);
-
-            let e_push =
-                cx.expr_method_call(sp,
-                                    cx.expr_ident(sp, id_ext("tt")),
-                                    id_ext("extend"),
-                                    vec![e_to_toks]);
-
-            vec![cx.stmt_expr(e_push)]
-        }
-        TokenTree::Token(sp, ref tok) => {
-            let e_sp = cx.expr_ident(sp, id_ext("_sp"));
-            let e_tok = cx.expr_call(sp,
-                                     mk_tt_path(cx, sp, "Token"),
-                                     vec![e_sp, expr_mk_token(cx, sp, tok)]);
-            let e_push =
-                cx.expr_method_call(sp,
-                                    cx.expr_ident(sp, id_ext("tt")),
-                                    id_ext("push"),
-                                    vec![e_tok]);
-            vec![cx.stmt_expr(e_push)]
-        },
-        TokenTree::Delimited(span, delim, ref tts) => {
-            let mut stmts = statements_mk_tt(cx, &TokenTree::open_tt(span.open, delim), false);
-            stmts.extend(statements_mk_tts(cx, tts.stream()));
-            stmts.extend(statements_mk_tt(cx, &TokenTree::close_tt(span.close, delim), false));
-            stmts
-        }
-    }
-}
-
-fn parse_arguments_to_quote(cx: &ExtCtxt, tts: &[TokenTree])
-                            -> (P<ast::Expr>, Vec<TokenTree>) {
-    let mut p = cx.new_parser_from_tts(tts);
-
-    let cx_expr = panictry!(p.parse_expr());
-    if !p.eat(&token::Comma) {
-        let _ = p.diagnostic().fatal("expected token `,`");
-    }
-
-    let tts = panictry!(p.parse_all_token_trees());
-    p.abort_if_errors();
-
-    (cx_expr, tts)
-}
-
-fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec<ast::Stmt> {
-    // We also bind a single value, sp, to ext_cx.call_site()
-    //
-    // This causes every span in a token-tree quote to be attributed to the
-    // call site of the extension using the quote. We can't really do much
-    // better since the source of the quote may well be in a library that
-    // was not even parsed by this compilation run, that the user has no
-    // source code for (eg. in libsyntax, which they're just _using_).
-    //
-    // The old quasiquoter had an elaborate mechanism for denoting input
-    // file locations from which quotes originated; unfortunately this
-    // relied on feeding the source string of the quote back into the
-    // compiler (which we don't really want to do) and, in any case, only
-    // pushed the problem a very small step further back: an error
-    // resulting from a parse of the resulting quote is still attributed to
-    // the site the string literal occurred, which was in a source file
-    // _other_ than the one the user has control over. For example, an
-    // error in a quote from the protocol compiler, invoked in user code
-    // using macro_rules! for example, will be attributed to the macro_rules.rs
-    // file in libsyntax, which the user might not even have source to (unless
-    // they happen to have a compiler on hand). Over all, the phase distinction
-    // just makes quotes "hard to attribute". Possibly this could be fixed
-    // by recreating some of the original qq machinery in the tt regime
-    // (pushing fake SourceFiles onto the parser to account for original sites
-    // of quotes, for example) but at this point it seems not likely to be
-    // worth the hassle.
-
-    let e_sp = cx.expr_method_call(sp,
-                                   cx.expr_ident(sp, id_ext("ext_cx")),
-                                   id_ext("call_site"),
-                                   Vec::new());
-
-    let stmt_let_sp = cx.stmt_let(sp, false,
-                                  id_ext("_sp"),
-                                  e_sp);
-
-    let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp));
-
-    vec![stmt_let_sp, stmt_let_tt]
-}
-
-fn statements_mk_tts(cx: &ExtCtxt, tts: TokenStream) -> Vec<ast::Stmt> {
-    let mut ss = Vec::new();
-    let mut quoted = false;
-    for tt in tts.into_trees() {
-        quoted = match tt {
-            TokenTree::Token(_, token::Dollar) if !quoted => true,
-            _ => {
-                ss.extend(statements_mk_tt(cx, &tt, quoted));
-                false
-            }
-        }
-    }
-    ss
-}
-
-fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[TokenTree]) -> (P<ast::Expr>, P<ast::Expr>) {
-    let (cx_expr, tts) = parse_arguments_to_quote(cx, tts);
-
-    let mut vector = mk_stmts_let(cx, sp);
-    vector.extend(statements_mk_tts(cx, tts.iter().cloned().collect()));
-    vector.push(cx.stmt_expr(cx.expr_ident(sp, id_ext("tt"))));
-    let block = cx.expr_block(cx.block(sp, vector));
-    let unflatten = vec![id_ext("syntax"), id_ext("ext"), id_ext("quote"), id_ext("unflatten")];
-
-    (cx_expr, cx.expr_call_global(sp, unflatten, vec![block]))
-}
-
-fn expand_wrapper(cx: &ExtCtxt,
-                  sp: Span,
-                  cx_expr: P<ast::Expr>,
-                  expr: P<ast::Expr>,
-                  imports: &[&[&str]]) -> P<ast::Expr> {
-    // Explicitly borrow to avoid moving from the invoker (#16992)
-    let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr));
-    let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow);
-
-    let mut stmts = imports.iter().map(|path| {
-        // make item: `use ...;`
-        let path = path.iter().map(|s| s.to_string()).collect();
-        let use_item = cx.item_use_glob(
-            sp,
-            respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
-            ids_ext(path),
-        );
-        cx.stmt_item(sp, use_item)
-    }).chain(Some(stmt_let_ext_cx)).collect::<Vec<_>>();
-    stmts.push(cx.stmt_expr(expr));
-
-    cx.expr_block(cx.block(sp, stmts))
-}
-
-fn expand_parse_call(cx: &ExtCtxt,
-                     sp: Span,
-                     parse_method: &str,
-                     arg_exprs: Vec<P<ast::Expr>> ,
-                     tts: &[TokenTree]) -> P<ast::Expr> {
-    let (cx_expr, tts_expr) = expand_tts(cx, sp, tts);
-
-    let parse_sess_call = || cx.expr_method_call(
-        sp, cx.expr_ident(sp, id_ext("ext_cx")),
-        id_ext("parse_sess"), Vec::new());
-
-    let new_parser_call =
-        cx.expr_call(sp,
-                     cx.expr_ident(sp, id_ext("new_parser_from_tts")),
-                     vec![parse_sess_call(), tts_expr]);
-
-    let path = vec![id_ext("syntax"), id_ext("ext"), id_ext("quote"), id_ext(parse_method)];
-    let mut args = vec![cx.expr_mut_addr_of(sp, new_parser_call)];
-    args.extend(arg_exprs);
-    let expr = cx.expr_call_global(sp, path, args);
-
-    if parse_method == "parse_attribute" {
-        expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"],
-                                                &["syntax", "parse", "attr"]])
-    } else {
-        expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"]])
-    }
-}
index 9b54e8f9c1f2c33ccc0802e3e7372bb207ccbe3c..9e107fee5bad31549859cfed97b75fe1cec5665d 100644 (file)
@@ -124,7 +124,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     (active, link_llvm_intrinsics, "1.0.0", Some(29602), None),
     (active, linkage, "1.0.0", Some(29603), None),
-    (active, quote, "1.0.0", Some(29601), None),
 
     // rustc internal
     (active, rustc_diagnostic_macros, "1.0.0", None, None),
@@ -504,6 +503,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Paths of the form: `extern::foo::bar`
     (removed, extern_in_paths, "1.33.0", Some(55600), None,
      Some("subsumed by `::foo::bar` paths")),
+    (removed, quote, "1.0.0", Some(29601), None, None),
 );
 
 declare_features! (
index 8ac103856dcd17fe4b799789066cc993132f689a..fdcbbb939a6cf16167c86ecc7bb20725c7151470 100644 (file)
@@ -207,8 +207,8 @@ fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedArgs)
         noop_fold_angle_bracketed_parameter_data(p, self)
     }
 
-    fn fold_parenthesized_parameter_data(&mut self, p: ParenthesisedArgs)
-                                         -> ParenthesisedArgs
+    fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedArgs)
+                                         -> ParenthesizedArgs
     {
         noop_fold_parenthesized_parameter_data(p, self)
     }
@@ -504,12 +504,12 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedA
     }
 }
 
-pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesisedArgs,
+pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedArgs,
                                                          fld: &mut T)
-                                                         -> ParenthesisedArgs
+                                                         -> ParenthesizedArgs
 {
-    let ParenthesisedArgs { inputs, output, span } = data;
-    ParenthesisedArgs {
+    let ParenthesizedArgs { inputs, output, span } = data;
+    ParenthesizedArgs {
         inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
         output: output.map(|ty| fld.fold_ty(ty)),
         span: fld.new_span(span)
@@ -598,7 +598,7 @@ pub fn noop_fold_tt<T: Folder>(tt: TokenTree, fld: &mut T) -> TokenTree {
         TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
             DelimSpan::from_pair(fld.new_span(span.open), fld.new_span(span.close)),
             delim,
-            fld.fold_tts(tts.stream()).into(),
+            fld.fold_tts(tts).into(),
         ),
     }
 }
index df22dacce1a755ef4b399e4f1b62e25243cecb1b..b2a3ae7f9d9755bfe0115e76cd40695ca53a9378 100644 (file)
@@ -174,7 +174,6 @@ pub mod ext {
     pub mod derive;
     pub mod expand;
     pub mod placeholders;
-    pub mod quote;
     pub mod source_util;
 
     pub mod tt {
index 0e1c3b4b61f3a86f6793811abe6360da20855821..8827e04802c332edd6e748adb52141f18b3b917d 100644 (file)
@@ -238,19 +238,6 @@ 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 new_or_buffered_errs(sess: &'a ParseSess,
                                 source_file: Lrc<syntax_pos::SourceFile>,
                                 override_span: Option<Span>) -> Result<Self, Vec<Diagnostic>> {
@@ -1408,9 +1395,10 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     // lifetimes shouldn't end with a single quote
                     // if we find one, then this is an invalid character literal
                     if self.ch_is('\'') {
-                        self.fatal_span_verbose(start_with_quote, self.next_pos,
-                                String::from("character literal may only contain one codepoint"))
-                            .raise();
+                        self.err_span_(start_with_quote, self.next_pos,
+                                "character literal may only contain one codepoint");
+                        self.bump();
+                        return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
 
                     }
 
@@ -1445,7 +1433,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                                     format!("\"{}\"", &self.src[start..end]),
                                     Applicability::MachineApplicable
                                 ).emit();
-                            return Ok(token::Literal(token::Str_(Symbol::intern("??")), None))
+                            return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
                         }
                         if self.ch_is('\n') || self.is_eof() || self.ch_is('/') {
                             // Only attempt to infer single line string literals. If we encounter
index ea205530ca5ccb2dfdc8c35752203cd5e26cfcbb..c7330004d6ded280a1c443ffbd678873efae68b0 100644 (file)
@@ -8,7 +8,6 @@
 use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
 use feature_gate::UnstableFeatures;
 use parse::parser::Parser;
-use ptr::P;
 use symbol::Symbol;
 use tokenstream::{TokenStream, TokenTree};
 use diagnostics::plugin::ErrorMap;
@@ -135,25 +134,6 @@ pub fn parse_crate_attrs_from_source_str(name: FileName, source: String, sess: &
     new_parser_from_source_str(sess, name, source).parse_inner_attributes()
 }
 
-crate fn parse_expr_from_source_str(name: FileName, source: String, sess: &ParseSess)
-                                      -> PResult<P<ast::Expr>> {
-    new_parser_from_source_str(sess, name, source).parse_expr()
-}
-
-/// Parses an item.
-///
-/// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
-/// when a syntax error occurred.
-crate fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess)
-                                      -> PResult<Option<P<ast::Item>>> {
-    new_parser_from_source_str(sess, name, source).parse_item()
-}
-
-crate fn parse_stmt_from_source_str(name: FileName, source: String, sess: &ParseSess)
-                                      -> PResult<Option<ast::Stmt>> {
-    new_parser_from_source_str(sess, name, source).parse_stmt()
-}
-
 pub fn parse_stream_from_source_str(name: FileName, source: String, sess: &ParseSess,
                                     override_span: Option<Span>)
                                     -> TokenStream {
@@ -466,6 +446,7 @@ macro_rules! err {
     match lit {
        token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))),
        token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))),
+       token::Err(i) => (true, Some(LitKind::Err(i))),
 
         // There are some valid suffixes for integer and float literals,
         // so all the handling is done internally.
@@ -780,13 +761,22 @@ mod tests {
     use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION};
     use ast::{self, Ident, PatKind};
     use attr::first_attr_value_str_by_name;
-    use parse;
+    use ptr::P;
     use print::pprust::item_to_string;
     use tokenstream::{DelimSpan, TokenTree};
     use util::parser_testing::string_to_stream;
     use util::parser_testing::{string_to_expr, string_to_item};
     use with_globals;
 
+    /// Parses an item.
+    ///
+    /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
+    /// when a syntax error occurred.
+    fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess)
+                                        -> PResult<Option<P<ast::Item>>> {
+        new_parser_from_source_str(sess, name, source).parse_item()
+    }
+
     // produce a syntax_pos::span
     fn sp(a: u32, b: u32) -> Span {
         Span::new(BytePos(a), BytePos(b), NO_EXPANSION)
@@ -817,7 +807,7 @@ fn string_to_tts_macro () {
                 )
                 if name_macro_rules.name == "macro_rules"
                 && name_zip.name == "zip" => {
-                    let tts = &macro_tts.stream().trees().collect::<Vec<_>>();
+                    let tts = &macro_tts.trees().collect::<Vec<_>>();
                     match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
                         (
                             3,
@@ -826,7 +816,7 @@ fn string_to_tts_macro () {
                             Some(&TokenTree::Delimited(_, second_delim, ref second_tts)),
                         )
                         if macro_delim == token::Paren => {
-                            let tts = &first_tts.stream().trees().collect::<Vec<_>>();
+                            let tts = &first_tts.trees().collect::<Vec<_>>();
                             match (tts.len(), tts.get(0), tts.get(1)) {
                                 (
                                     2,
@@ -836,7 +826,7 @@ fn string_to_tts_macro () {
                                 if first_delim == token::Paren && ident.name == "a" => {},
                                 _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
                             }
-                            let tts = &second_tts.stream().trees().collect::<Vec<_>>();
+                            let tts = &second_tts.trees().collect::<Vec<_>>();
                             match (tts.len(), tts.get(0), tts.get(1)) {
                                 (
                                     2,
@@ -1015,9 +1005,15 @@ fn wb() -> c_int { O_WRONLY as c_int }
 
     #[test]
     fn ttdelim_span() {
+        fn parse_expr_from_source_str(
+            name: FileName, source: String, sess: &ParseSess
+        ) -> PResult<P<ast::Expr>> {
+            new_parser_from_source_str(sess, name, source).parse_expr()
+        }
+
         with_globals(|| {
             let sess = ParseSess::new(FilePathMapping::empty());
-            let expr = parse::parse_expr_from_source_str(PathBuf::from("foo").into(),
+            let expr = parse_expr_from_source_str(PathBuf::from("foo").into(),
                 "foo!( fn main() { body } )".to_string(), &sess).unwrap();
 
             let tts: Vec<_> = match expr.node {
index 5b430d13516b47f7ebd912263710ffc4c626e6b4..fb832afb74833296716e46f3cf4e59f5ffa9b057 100644 (file)
@@ -1,5 +1,5 @@
 use rustc_target::spec::abi::{self, Abi};
-use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
+use ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
 use ast::{GenericBound, TraitBoundModifier};
 use ast::Unsafety;
 use ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
@@ -46,7 +46,7 @@
 use ptr::P;
 use parse::PResult;
 use ThinVec;
-use tokenstream::{self, DelimSpan, ThinTokenStream, TokenTree, TokenStream};
+use tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
 use symbol::{Symbol, keywords};
 
 use std::borrow::Cow;
@@ -100,6 +100,7 @@ pub enum PathStyle {
 enum SemiColonMode {
     Break,
     Ignore,
+    Comma,
 }
 
 #[derive(Clone, Copy, PartialEq, Debug)]
@@ -280,17 +281,17 @@ struct TokenCursorFrame {
 /// on the parser.
 #[derive(Clone)]
 enum LastToken {
-    Collecting(Vec<TokenStream>),
-    Was(Option<TokenStream>),
+    Collecting(Vec<TreeAndJoint>),
+    Was(Option<TreeAndJoint>),
 }
 
 impl TokenCursorFrame {
-    fn new(sp: DelimSpan, delim: DelimToken, tts: &ThinTokenStream) -> Self {
+    fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
         TokenCursorFrame {
             delim: delim,
             span: sp,
             open_delim: delim == token::NoDelim,
-            tree_cursor: tts.stream().into_trees(),
+            tree_cursor: tts.clone().into_trees(),
             close_delim: delim == token::NoDelim,
             last_token: LastToken::Was(None),
         }
@@ -1285,9 +1286,6 @@ fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuild
     crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
         self.sess.span_diagnostic.span_bug(sp, m)
     }
-    crate fn abort_if_errors(&self) {
-        self.sess.span_diagnostic.abort_if_errors();
-    }
 
     fn cancel(&self, err: &mut DiagnosticBuilder) {
         self.sess.span_diagnostic.cancel(err)
@@ -1988,6 +1986,44 @@ fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
 
                 result.unwrap()
             }
+            token::Dot if self.look_ahead(1, |t| match t {
+                token::Literal(parse::token::Lit::Integer(_) , _) => true,
+                _ => false,
+            }) => { // recover from `let x = .4;`
+                let lo = self.span;
+                self.bump();
+                if let token::Literal(
+                    parse::token::Lit::Integer(val),
+                    suffix,
+                ) = self.token {
+                    let suffix = suffix.and_then(|s| {
+                        let s = s.as_str().get();
+                        if ["f32", "f64"].contains(&s) {
+                            Some(s)
+                        } else {
+                            None
+                        }
+                    }).unwrap_or("");
+                    self.bump();
+                    let sp = lo.to(self.prev_span);
+                    let mut err = self.diagnostic()
+                        .struct_span_err(sp, "float literals must have an integer part");
+                    err.span_suggestion_with_applicability(
+                        sp,
+                        "must have an integer part",
+                        format!("0.{}{}", val, suffix),
+                        Applicability::MachineApplicable,
+                    );
+                    err.emit();
+                    return Ok(match suffix {
+                        "f32" => ast::LitKind::Float(val, ast::FloatTy::F32),
+                        "f64" => ast::LitKind::Float(val, ast::FloatTy::F64),
+                        _ => ast::LitKind::FloatUnsuffixed(val),
+                    });
+                } else {
+                    unreachable!();
+                };
+            }
             _ => { return self.unexpected_last(&self.token); }
         };
 
@@ -2149,7 +2185,27 @@ fn parse_path_segments(&mut self,
                            enable_warning: bool)
                            -> PResult<'a, ()> {
         loop {
-            segments.push(self.parse_path_segment(style, enable_warning)?);
+            let segment = self.parse_path_segment(style, enable_warning)?;
+            if style == PathStyle::Expr {
+                // In order to check for trailing angle brackets, we must have finished
+                // recursing (`parse_path_segment` can indirectly call this function),
+                // that is, the next token must be the highlighted part of the below example:
+                //
+                // `Foo::<Bar as Baz<T>>::Qux`
+                //                      ^ here
+                //
+                // As opposed to the below highlight (if we had only finished the first
+                // recursion):
+                //
+                // `Foo::<Bar as Baz<T>>::Qux`
+                //                     ^ here
+                //
+                // `PathStyle::Expr` is only provided at the root invocation and never in
+                // `parse_path_segment` to recurse and therefore can be checked to maintain
+                // this invariant.
+                self.check_trailing_angle_brackets(&segment, token::ModSep);
+            }
+            segments.push(segment);
 
             if self.is_import_coupler() || !self.eat(&token::ModSep) {
                 return Ok(());
@@ -2176,11 +2232,11 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
               style != PathStyle::Mod && self.check(&token::ModSep)
                                       && self.look_ahead(1, |t| is_args_start(t)) {
             // Generic arguments are found - `<`, `(`, `::<` or `::(`.
-            let lo = self.span;
             if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
                 self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
                                  .span_label(self.prev_span, "try removing `::`").emit();
             }
+            let lo = self.span;
 
             let args = if self.eat_lt() {
                 // `<'a, T, A = U>`
@@ -2203,7 +2259,7 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
                 } else {
                     None
                 };
-                ParenthesisedArgs { inputs, output, span }.into()
+                ParenthesizedArgs { inputs, output, span }.into()
             };
 
             PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
@@ -2263,8 +2319,24 @@ fn parse_field(&mut self) -> PResult<'a, Field> {
         let lo = self.span;
 
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
-        let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
+        let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| {
+            t == &token::Colon || t == &token::Eq
+        }) {
             let fieldname = self.parse_field_name()?;
+
+            // Check for an equals token. This means the source incorrectly attempts to
+            // initialize a field with an eq rather than a colon.
+            if self.token == token::Eq {
+                self.diagnostic()
+                    .struct_span_err(self.span, "expected `:`, found `=`")
+                    .span_suggestion_with_applicability(
+                        fieldname.span.shrink_to_hi().to(self.span),
+                        "replace equals symbol with a colon",
+                        ":".to_string(),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
+            }
             self.bump(); // `:`
             (fieldname, self.parse_expr()?, false)
         } else {
@@ -2330,7 +2402,7 @@ pub fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) ->
         })
     }
 
-    fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinTokenStream)> {
+    fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
         let delim = match self.token {
             token::OpenDelim(delim) => delim,
             _ => {
@@ -2350,7 +2422,7 @@ fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinToke
             token::Brace => MacDelimiter::Brace,
             token::NoDelim => self.bug("unexpected no delimiter"),
         };
-        Ok((delim, tts.stream().into()))
+        Ok((delim, tts.into()))
     }
 
     /// At the bottom (top?) of the precedence hierarchy,
@@ -2656,8 +2728,24 @@ fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Att
                 break;
             }
 
+            let mut recovery_field = None;
+            if let token::Ident(ident, _) = self.token {
+                if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
+                    // Use in case of error after field-looking code: `S { foo: () with a }`
+                    let mut ident = ident.clone();
+                    ident.span = self.span;
+                    recovery_field = Some(ast::Field {
+                        ident,
+                        span: self.span,
+                        expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()),
+                        is_shorthand: false,
+                        attrs: ThinVec::new(),
+                    });
+                }
+            }
+            let mut parsed_field = None;
             match self.parse_field() {
-                Ok(f) => fields.push(f),
+                Ok(f) => parsed_field = Some(f),
                 Err(mut e) => {
                     e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
@@ -2666,19 +2754,28 @@ fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Att
                     // what comes next as additional fields, rather than
                     // bailing out until next `}`.
                     if self.token != token::Comma {
-                        self.recover_stmt();
-                        break;
+                        self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
+                        if self.token != token::Comma {
+                            break;
+                        }
                     }
                 }
             }
 
             match self.expect_one_of(&[token::Comma],
                                      &[token::CloseDelim(token::Brace)]) {
-                Ok(()) => {}
+                Ok(()) => if let Some(f) = parsed_field.or(recovery_field) {
+                    // only include the field if there's no parse error for the field name
+                    fields.push(f);
+                }
                 Err(mut e) => {
+                    if let Some(f) = recovery_field {
+                        fields.push(f);
+                    }
+                    e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
-                    self.recover_stmt();
-                    break;
+                    self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
+                    self.eat(&token::Comma);
                 }
             }
         }
@@ -2757,6 +2854,8 @@ fn parse_dot_or_call_expr_with(&mut self,
     // Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         let segment = self.parse_path_segment(PathStyle::Expr, true)?;
+        self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
+
         Ok(match self.token {
             token::OpenDelim(token::Paren) => {
                 // Method call `expr.f()`
@@ -2784,6 +2883,116 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
         })
     }
 
+    /// This function checks if there are trailing angle brackets and produces
+    /// a diagnostic to suggest removing them.
+    ///
+    /// ```ignore (diagnostic)
+    /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+    ///                                                        ^^ help: remove extra angle brackets
+    /// ```
+    fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) {
+        // This function is intended to be invoked after parsing a path segment where there are two
+        // cases:
+        //
+        // 1. A specific token is expected after the path segment.
+        //    eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
+        //        `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
+        // 2. No specific token is expected after the path segment.
+        //    eg. `x.foo` (field access)
+        //
+        // This function is called after parsing `.foo` and before parsing the token `end` (if
+        // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
+        // `Foo::<Bar>`.
+
+        // We only care about trailing angle brackets if we previously parsed angle bracket
+        // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
+        // removed in this case:
+        //
+        // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
+        //
+        // This case is particularly tricky as we won't notice it just looking at the tokens -
+        // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
+        // have already been parsed):
+        //
+        // `x.foo::<u32>>>(3)`
+        let parsed_angle_bracket_args = segment.args
+            .as_ref()
+            .map(|args| args.is_angle_bracketed())
+            .unwrap_or(false);
+
+        debug!(
+            "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
+            parsed_angle_bracket_args,
+        );
+        if !parsed_angle_bracket_args {
+            return;
+        }
+
+        // Keep the span at the start so we can highlight the sequence of `>` characters to be
+        // removed.
+        let lo = self.span;
+
+        // We need to look-ahead to see if we have `>` characters without moving the cursor forward
+        // (since we might have the field access case and the characters we're eating are
+        // actual operators and not trailing characters - ie `x.foo >> 3`).
+        let mut position = 0;
+
+        // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
+        // many of each (so we can correctly pluralize our error messages) and continue to
+        // advance.
+        let mut number_of_shr = 0;
+        let mut number_of_gt = 0;
+        while self.look_ahead(position, |t| {
+            trace!("check_trailing_angle_brackets: t={:?}", t);
+            if *t == token::BinOp(token::BinOpToken::Shr) {
+                number_of_shr += 1;
+                true
+            } else if *t == token::Gt {
+                number_of_gt += 1;
+                true
+            } else {
+                false
+            }
+        }) {
+            position += 1;
+        }
+
+        // If we didn't find any trailing `>` characters, then we have nothing to error about.
+        debug!(
+            "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
+            number_of_gt, number_of_shr,
+        );
+        if number_of_gt < 1 && number_of_shr < 1 {
+            return;
+        }
+
+        // Finally, double check that we have our end token as otherwise this is the
+        // second case.
+        if self.look_ahead(position, |t| {
+            trace!("check_trailing_angle_brackets: t={:?}", t);
+            *t == end
+        }) {
+            // Eat from where we started until the end token so that parsing can continue
+            // as if we didn't have those extra angle brackets.
+            self.eat_to_tokens(&[&end]);
+            let span = lo.until(self.span);
+
+            let plural = number_of_gt > 1 || number_of_shr >= 1;
+            self.diagnostic()
+                .struct_span_err(
+                    span,
+                    &format!("unmatched angle bracket{}", if plural { "s" } else { "" }),
+                )
+                .span_suggestion_with_applicability(
+                    span,
+                    &format!("remove extra angle bracket{}", if plural { "s" } else { "" }),
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+        }
+    }
+
     fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         let mut e = e0;
         let mut hi;
@@ -4063,12 +4272,13 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::Fiel
 
         if let Some(mut err) = delayed_err {
             if let Some(etc_span) = etc_span {
-                err.multipart_suggestion(
+                err.multipart_suggestion_with_applicability(
                     "move the `..` to the end of the field list",
                     vec![
                         (etc_span, String::new()),
                         (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
                     ],
+                    Applicability::MachineApplicable,
                 );
             }
             err.emit();
@@ -4482,13 +4692,17 @@ fn parse_name_and_ty(&mut self,
     }
 
     /// Emit an expected item after attributes error.
-    fn expected_item_err(&self, attrs: &[Attribute]) {
+    fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a,  ()> {
         let message = match attrs.last() {
             Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment",
             _ => "expected item after attributes",
         };
 
-        self.span_err(self.prev_span, message);
+        let mut err = self.diagnostic().struct_span_err(self.prev_span, message);
+        if attrs.last().unwrap().is_sugared_doc {
+            err.span_label(self.prev_span, "this doc comment doesn't document anything");
+        }
+        Err(err)
     }
 
     /// Parse a statement. This stops just before trailing semicolons on everything but items.
@@ -4537,13 +4751,13 @@ fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockM
                 token::CloseDelim(token::DelimToken::Brace) => {
                     if brace_depth == 0 {
                         debug!("recover_stmt_ return - close delim {:?}", self.token);
-                        return;
+                        break;
                     }
                     brace_depth -= 1;
                     self.bump();
                     if in_block && bracket_depth == 0 && brace_depth == 0 {
                         debug!("recover_stmt_ return - block end {:?}", self.token);
-                        return;
+                        break;
                     }
                 }
                 token::CloseDelim(token::DelimToken::Bracket) => {
@@ -4555,7 +4769,7 @@ fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockM
                 }
                 token::Eof => {
                     debug!("recover_stmt_ return - Eof");
-                    return;
+                    break;
                 }
                 token::Semi => {
                     self.bump();
@@ -4563,7 +4777,17 @@ fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockM
                        brace_depth == 0 &&
                        bracket_depth == 0 {
                         debug!("recover_stmt_ return - Semi");
-                        return;
+                        break;
+                    }
+                }
+                token::Comma => {
+                    if break_on_semi == SemiColonMode::Comma &&
+                       brace_depth == 0 &&
+                       bracket_depth == 0 {
+                        debug!("recover_stmt_ return - Semi");
+                        break;
+                    } else {
+                        self.bump();
                     }
                 }
                 _ => {
@@ -4641,7 +4865,7 @@ fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
                 let ident = self.parse_ident()?;
                 let tokens = if self.check(&token::OpenDelim(token::Brace)) {
                     match self.parse_token_tree() {
-                        TokenTree::Delimited(_, _, tts) => tts.stream(),
+                        TokenTree::Delimited(_, _, tts) => tts,
                         _ => unreachable!(),
                     }
                 } else if self.check(&token::OpenDelim(token::Paren)) {
@@ -6904,7 +7128,11 @@ fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> {
 
             let mut err = self.struct_span_err(fixed_name_sp, error_msg);
             err.span_label(fixed_name_sp, "dash-separated idents are not valid");
-            err.multipart_suggestion(suggestion_msg, replacement);
+            err.multipart_suggestion_with_applicability(
+                suggestion_msg,
+                replacement,
+                Applicability::MachineApplicable,
+            );
             err.emit();
         }
         Ok(ident)
@@ -7266,9 +7494,16 @@ fn parse_item_implementation(
             // CONST ITEM
             if self.eat_keyword(keywords::Mut) {
                 let prev_span = self.prev_span;
-                self.diagnostic().struct_span_err(prev_span, "const globals cannot be mutable")
-                                 .help("did you mean to declare a static?")
-                                 .emit();
+                let mut err = self.diagnostic()
+                    .struct_span_err(prev_span, "const globals cannot be mutable");
+                err.span_label(prev_span, "cannot be mutable");
+                err.span_suggestion_with_applicability(
+                    const_span,
+                    "you might want to declare a static instead",
+                    "static".to_owned(),
+                    Applicability::MaybeIncorrect,
+                );
+                err.emit();
             }
             let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
             let prev_span = self.prev_span;
@@ -7631,7 +7866,7 @@ fn parse_item_implementation(
             }
             None => {
                 if !attrs.is_empty()  {
-                    self.expected_item_err(&attrs);
+                    self.expected_item_err(&attrs)?;
                 }
 
                 self.unexpected()
@@ -7694,7 +7929,7 @@ fn parse_macro_use_or_failure(
         }
 
         if !attributes_allowed && !attrs.is_empty() {
-            self.expected_item_err(&attrs);
+            self.expected_item_err(&attrs)?;
         }
         Ok(None)
     }
@@ -7757,7 +7992,7 @@ fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
             &mut self.token_cursor.stack[prev].last_token
         };
 
-        // Pull our the toekns that we've collected from the call to `f` above
+        // Pull out the tokens that we've collected from the call to `f` above.
         let mut collected_tokens = match *last_token {
             LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
             LastToken::Was(_) => panic!("our vector went away?"),
@@ -7776,10 +8011,9 @@ fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
         // call. In that case we need to record all the tokens we collected in
         // our parent list as well. To do that we push a clone of our stream
         // onto the previous list.
-        let stream = collected_tokens.into_iter().collect::<TokenStream>();
         match prev_collecting {
             Some(mut list) => {
-                list.push(stream.clone());
+                list.extend(collected_tokens.iter().cloned());
                 list.extend(extra_token);
                 *last_token = LastToken::Collecting(list);
             }
@@ -7788,7 +8022,7 @@ fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
             }
         }
 
-        Ok((ret?, stream))
+        Ok((ret?, TokenStream::new(collected_tokens)))
     }
 
     pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
index 25a4da38c8c511863b557d97456ea0f92b97a676..f06e975a6d95acd436b6a9325d2442e48205379f 100644 (file)
@@ -60,6 +60,7 @@ pub fn is_empty(self) -> bool {
 pub enum Lit {
     Byte(ast::Name),
     Char(ast::Name),
+    Err(ast::Name),
     Integer(ast::Name),
     Float(ast::Name),
     Str_(ast::Name),
@@ -73,6 +74,7 @@ impl Lit {
         match *self {
             Byte(_) => "byte literal",
             Char(_) => "char literal",
+            Err(_) => "invalid literal",
             Integer(_) => "integer literal",
             Float(_) => "float literal",
             Str_(_) | StrRaw(..) => "string literal",
@@ -471,8 +473,7 @@ pub fn is_reserved_ident(&self) -> bool {
 
             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot |
             DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
-            Question | OpenDelim(..) | CloseDelim(..) => return None,
-
+            Question | OpenDelim(..) | CloseDelim(..) |
             Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
             Whitespace | Comment | Shebang(..) | Eof => return None,
         })
index 2ad3d3a6d648795d112c9cbd05e351d7249e88f1..7cecf4b9af73faf9f4f7497991e1b7b834de5104 100644 (file)
@@ -224,6 +224,7 @@ pub fn token_to_string(tok: &Token) -> String {
             let mut out = match lit {
                 token::Byte(b)           => format!("b'{}'", b),
                 token::Char(c)           => format!("'{}'", c),
+                token::Err(c)            => format!("'{}'", c),
                 token::Float(c)          |
                 token::Integer(c)        => c.to_string(),
                 token::Str_(s)           => format!("\"{}\"", s),
@@ -603,6 +604,14 @@ fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
         }
         match lit.node {
             ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
+            ast::LitKind::Err(st) => {
+                let st = st.as_str().escape_debug();
+                let mut res = String::with_capacity(st.len() + 2);
+                res.push('\'');
+                res.push_str(&st);
+                res.push('\'');
+                self.writer().word(res)
+            }
             ast::LitKind::Byte(byte) => {
                 let mut res = String::from("b'");
                 res.extend(ascii::escape_default(byte).map(|c| c as char));
@@ -807,7 +816,7 @@ fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> {
             TokenTree::Delimited(_, delim, tts) => {
                 self.writer().word(token_to_string(&token::OpenDelim(delim)))?;
                 self.writer().space()?;
-                self.print_tts(tts.stream())?;
+                self.print_tts(tts)?;
                 self.writer().space()?;
                 self.writer().word(token_to_string(&token::CloseDelim(delim)))
             },
index bb1744e2df169a2e21676abcb90c994947356831..3effe53cd29b05c821a7a7025eb21e5a1e55d85f 100644 (file)
@@ -101,6 +101,7 @@ pub fn filter_map<F>(mut self, f: F) -> Option<P<T>> where
                 // Recreate self from the raw pointer.
                 Some(P { ptr: Box::from_raw(p) })
             } else {
+                drop(Box::from_raw(p));
                 None
             }
         }
index fb72ef9c956ce5057041339d2645dbb56b31c1d8..f5d2d6f18ee87916f4a63d976fc3ebd2e533164c 100644 (file)
@@ -41,7 +41,7 @@ pub enum TokenTree {
     /// A single token
     Token(Span, token::Token),
     /// A delimited sequence of token trees
-    Delimited(DelimSpan, DelimToken, ThinTokenStream),
+    Delimited(DelimSpan, DelimToken, TokenStream),
 }
 
 impl TokenTree {
@@ -62,8 +62,7 @@ pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
             (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2,
             (&TokenTree::Delimited(_, delim, ref tts),
              &TokenTree::Delimited(_, delim2, ref tts2)) => {
-                delim == delim2 &&
-                tts.stream().eq_unspanned(&tts2.stream())
+                delim == delim2 && tts.eq_unspanned(&tts2)
             }
             (_, _) => false,
         }
@@ -81,8 +80,7 @@ pub fn probably_equal_for_proc_macro(&self, other: &TokenTree) -> bool {
             }
             (&TokenTree::Delimited(_, delim, ref tts),
              &TokenTree::Delimited(_, delim2, ref tts2)) => {
-                delim == delim2 &&
-                tts.stream().probably_equal_for_proc_macro(&tts2.stream())
+                delim == delim2 && tts.probably_equal_for_proc_macro(&tts2)
             }
             (_, _) => false,
         }
@@ -113,7 +111,7 @@ pub fn eq_token(&self, t: Token) -> bool {
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream::Tree(self, Joint)
+        TokenStream::new(vec![(self, Joint)])
     }
 
     /// Returns the opening delimiter as a token tree.
@@ -143,18 +141,19 @@ pub fn close_tt(span: Span, delim: DelimToken) -> TokenTree {
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
+///
+/// The use of `Option` is an optimization that avoids the need for an
+/// allocation when the stream is empty. However, it is not guaranteed that an
+/// empty stream is represented with `None`; it may be represented as a `Some`
+/// around an empty `Vec`.
 #[derive(Clone, Debug)]
-pub enum TokenStream {
-    Empty,
-    Tree(TokenTree, IsJoint),
-    Stream(Lrc<Vec<TreeAndJoint>>),
-}
+pub struct TokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
 
 pub type TreeAndJoint = (TokenTree, IsJoint);
 
 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
+static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 8);
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum IsJoint {
@@ -169,7 +168,7 @@ impl TokenStream {
     /// separating the two arguments with a comma for diagnostic suggestions.
     pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
         // Used to suggest if a user writes `foo!(a b);`
-        if let TokenStream::Stream(ref stream) = self {
+        if let Some(ref stream) = self.0 {
             let mut suggestion = None;
             let mut iter = stream.iter().enumerate().peekable();
             while let Some((pos, ts)) = iter.next() {
@@ -201,7 +200,7 @@ pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
 
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
-        TokenStream::Tree(tree, NonJoint)
+        TokenStream::new(vec![(tree, NonJoint)])
     }
 }
 
@@ -233,7 +232,7 @@ fn eq(&self, other: &TokenStream) -> bool {
 
 impl TokenStream {
     pub fn len(&self) -> usize {
-        if let TokenStream::Stream(ref slice) = self {
+        if let Some(ref slice) = self.0 {
             slice.len()
         } else {
             0
@@ -241,13 +240,13 @@ pub fn len(&self) -> usize {
     }
 
     pub fn empty() -> TokenStream {
-        TokenStream::Empty
+        TokenStream(None)
     }
 
     pub fn is_empty(&self) -> bool {
-        match self {
-            TokenStream::Empty => true,
-            _ => false,
+        match self.0 {
+            None => true,
+            Some(ref stream) => stream.is_empty(),
         }
     }
 
@@ -258,10 +257,9 @@ fn from_streams(mut streams: Vec<TokenStream>) -> TokenStream {
             _ => {
                 let mut vec = vec![];
                 for stream in streams {
-                    match stream {
-                        TokenStream::Empty => {},
-                        TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
-                        TokenStream::Stream(stream2) => vec.extend(stream2.iter().cloned()),
+                    match stream.0 {
+                        None => {},
+                        Some(stream2) => vec.extend(stream2.iter().cloned()),
                     }
                 }
                 TokenStream::new(vec)
@@ -269,22 +267,16 @@ fn from_streams(mut streams: Vec<TokenStream>) -> TokenStream {
         }
     }
 
-    pub fn new(mut streams: Vec<TreeAndJoint>) -> TokenStream {
+    pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
         match streams.len() {
-            0 => TokenStream::empty(),
-            1 => {
-                let (tree, is_joint) = streams.pop().unwrap();
-                TokenStream::Tree(tree, is_joint)
-            }
-            _ => TokenStream::Stream(Lrc::new(streams)),
+            0 => TokenStream(None),
+            _ => TokenStream(Some(Lrc::new(streams))),
         }
     }
 
     pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
-        match self {
-            TokenStream::Empty => {}
-            TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
-            TokenStream::Stream(stream) => vec.extend(stream.iter().cloned()),
+        if let Some(stream) = self.0 {
+            vec.extend(stream.iter().cloned());
         }
     }
 
@@ -349,51 +341,36 @@ fn semantic_tree(tree: &TokenTree) -> bool {
     }
 
     pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        match self {
-            TokenStream::Empty => TokenStream::Empty,
-            TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(0, tree), is_joint),
-            TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+        TokenStream(self.0.map(|stream| {
+            Lrc::new(
                 stream
                     .iter()
                     .enumerate()
                     .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
-                    .collect()
-            )),
-        }
+                    .collect())
+        }))
     }
 
     pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        match self {
-            TokenStream::Empty => TokenStream::Empty,
-            TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
-            TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+        TokenStream(self.0.map(|stream| {
+            Lrc::new(
                 stream
                     .iter()
                     .map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
-                    .collect()
-            )),
-        }
+                    .collect())
+        }))
     }
 
-    fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
-        match self {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)),
-            TokenStream::Stream(ref stream) => Some(stream.first().unwrap().clone())
-        }
+    fn first_tree_and_joint(&self) -> Option<TreeAndJoint> {
+        self.0.as_ref().map(|stream| {
+            stream.first().unwrap().clone()
+        })
     }
 
     fn last_tree_if_joint(&self) -> Option<TokenTree> {
-        match self {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, is_joint) => {
-                if *is_joint == Joint {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) => {
+        match self.0 {
+            None => None,
+            Some(ref stream) => {
                 if let (tree, Joint) = stream.last().unwrap() {
                     Some(tree.clone())
                 } else {
@@ -422,7 +399,7 @@ pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
                     self.push_all_but_last_tree(&last_stream);
                     let glued_span = last_span.to(span);
                     let glued_tt = TokenTree::Token(glued_span, glued_tok);
-                    let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint);
+                    let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]);
                     self.0.push(glued_tokenstream);
                     self.push_all_but_first_tree(&stream);
                     return
@@ -437,23 +414,21 @@ pub fn build(self) -> TokenStream {
     }
 
     fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
-        if let TokenStream::Stream(ref streams) = stream {
+        if let Some(ref streams) = stream.0 {
             let len = streams.len();
             match len {
                 1 => {}
-                2 => self.0.push(TokenStream::Tree(streams[0].0.clone(), streams[0].1)),
-                _ => self.0.push(TokenStream::Stream(Lrc::new(streams[0 .. len - 1].to_vec()))),
+                _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))),
             }
         }
     }
 
     fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
-        if let TokenStream::Stream(ref streams) = stream {
+        if let Some(ref streams) = stream.0 {
             let len = streams.len();
             match len {
                 1 => {}
-                2 => self.0.push(TokenStream::Tree(streams[1].0.clone(), streams[1].1)),
-                _ => self.0.push(TokenStream::Stream(Lrc::new(streams[1 .. len].to_vec()))),
+                _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))),
             }
         }
     }
@@ -479,17 +454,9 @@ fn new(stream: TokenStream) -> Self {
     }
 
     pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
-        match self.stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, ref is_joint) => {
-                if self.index == 0 {
-                    self.index = 1;
-                    Some((tree.clone(), *is_joint))
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) => {
+        match self.stream.0 {
+            None => None,
+            Some(ref stream) => {
                 if self.index < stream.len() {
                     self.index += 1;
                     Some(stream[self.index - 1].clone())
@@ -505,63 +472,19 @@ pub fn append(&mut self, new_stream: TokenStream) {
             return;
         }
         let index = self.index;
-        let stream = mem::replace(&mut self.stream, TokenStream::Empty);
+        let stream = mem::replace(&mut self.stream, TokenStream(None));
         *self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
         self.index = index;
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
-        match self.stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, _) => {
-                if n == 0 && self.index == 0 {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) =>
-                stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
+        match self.stream.0 {
+            None => None,
+            Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
         }
     }
 }
 
-/// The `TokenStream` type is large enough to represent a single `TokenTree` without allocation.
-/// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
-/// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
-#[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
-
-impl ThinTokenStream {
-    pub fn stream(&self) -> TokenStream {
-        self.clone().into()
-    }
-}
-
-impl From<TokenStream> for ThinTokenStream {
-    fn from(stream: TokenStream) -> ThinTokenStream {
-        ThinTokenStream(match stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(tree, is_joint) => Some(Lrc::new(vec![(tree, is_joint)])),
-            TokenStream::Stream(stream) => Some(stream),
-        })
-    }
-}
-
-impl From<ThinTokenStream> for TokenStream {
-    fn from(stream: ThinTokenStream) -> TokenStream {
-        stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty)
-    }
-}
-
-impl Eq for ThinTokenStream {}
-
-impl PartialEq<ThinTokenStream> for ThinTokenStream {
-    fn eq(&self, other: &ThinTokenStream) -> bool {
-        TokenStream::from(self.clone()) == TokenStream::from(other.clone())
-    }
-}
-
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&pprust::tokens_to_string(self.clone()))
@@ -580,18 +503,6 @@ fn decode<D: Decoder>(decoder: &mut D) -> Result<TokenStream, D::Error> {
     }
 }
 
-impl Encodable for ThinTokenStream {
-    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
-        TokenStream::from(self.clone()).encode(encoder)
-    }
-}
-
-impl Decodable for ThinTokenStream {
-    fn decode<D: Decoder>(decoder: &mut D) -> Result<ThinTokenStream, D::Error> {
-        TokenStream::decode(decoder).map(Into::into)
-    }
-}
-
 #[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub struct DelimSpan {
     pub open: Span,
index e407be6c1fe80d274fcaca440f430d922cf9148c..d0b3cd865ce6e211fb682c2f2f58ca549bdf258d 100644 (file)
@@ -25,7 +25,7 @@ fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T
 {
     let mut p = string_to_parser(&ps, s);
     let x = panictry!(f(&mut p));
-    p.abort_if_errors();
+    p.sess.span_diagnostic.abort_if_errors();
     x
 }
 
index 156546bbba94afb03eb677adeb5d449bc035a1c3..8cbd47ca70fded321d9eb95b2863d2e1327f6fdf 100644 (file)
@@ -832,7 +832,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute)
 pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
     match tt {
         TokenTree::Token(_, tok) => visitor.visit_token(tok),
-        TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()),
+        TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts),
     }
 }
 
index 807f190cb6a1afffcf31efe773625d5b45024011..f148f8e003df39eea6af5fd0574cca267292a24b 100644 (file)
@@ -23,6 +23,7 @@ pub fn expand_syntax_ext(
         match e.node {
             ast::ExprKind::Lit(ref lit) => match lit.node {
                 ast::LitKind::Str(ref s, _)
+                | ast::LitKind::Err(ref s)
                 | ast::LitKind::Float(ref s, _)
                 | ast::LitKind::FloatUnsuffixed(ref s) => {
                     accumulator.push_str(&s.as_str());
index 3e3bca7080fb6d4b9f77ce95272ffc6a68b5ee8b..215df4224c5f1ec7516ece1931eabbfea94d120c 100644 (file)
@@ -493,7 +493,10 @@ fn build_piece(&mut self,
 
                 let fill = arg.format.fill.unwrap_or(' ');
 
-                if *arg != simple_arg || fill != ' ' {
+                let pos_simple =
+                    arg.position.index() == simple_arg.position.index();
+
+                if !pos_simple || arg.format != simple_arg.format || fill != ' ' {
                     self.all_pieces_simple = false;
                 }
 
index 17996f23691611a9c3f6b0072b4a9e5746396935..5e767d237cc0ea7562e8c5479b66c1385cf090c8 100644 (file)
@@ -11,7 +11,6 @@
 #![feature(decl_macro)]
 #![feature(nll)]
 #![feature(str_escape)]
-#![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
@@ -58,8 +57,7 @@
 use syntax::symbol::Symbol;
 
 pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
-                         user_exts: Vec<NamedSyntaxExtension>,
-                         enable_quotes: bool) {
+                         user_exts: Vec<NamedSyntaxExtension>) {
     deriving::register_builtin_derives(resolver);
 
     let mut register = |name, ext| {
@@ -81,24 +79,6 @@ macro_rules! register {
         )* }
     }
 
-    if enable_quotes {
-        use syntax::ext::quote::*;
-        register! {
-            quote_tokens: expand_quote_tokens,
-            quote_expr: expand_quote_expr,
-            quote_ty: expand_quote_ty,
-            quote_item: expand_quote_item,
-            quote_pat: expand_quote_pat,
-            quote_arm: expand_quote_arm,
-            quote_stmt: expand_quote_stmt,
-            quote_attr: expand_quote_attr,
-            quote_arg: expand_quote_arg,
-            quote_block: expand_quote_block,
-            quote_meta_item: expand_quote_meta_item,
-            quote_path: expand_quote_path,
-        }
-    }
-
     use syntax::ext::source_util::*;
     register! {
         line: expand_line,
index 158cbc791ef504f30cf0d5ff6802f84769480874..7de9b9343a8faceb33609b220290e37dc5ca9b92 100644 (file)
@@ -269,7 +269,7 @@ fn to_internal(self) -> TokenStream {
         };
 
         let tree = tokenstream::TokenTree::Token(span, token);
-        TokenStream::Tree(tree, if joint { Joint } else { NonJoint })
+        TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
     }
 }
 
index 6a41a93f0b4fdd376a6e04c5c66a54cd20e498fc..d9d7f9b0cb4926fcfb9a392cbb6b177b99816538 100644 (file)
@@ -668,6 +668,11 @@ pub fn primary_spans(&self) -> &[Span] {
         &self.primary_spans
     }
 
+    /// Returns whether any of the primary spans is displayable.
+    pub fn has_primary_spans(&self) -> bool {
+        self.primary_spans.iter().any(|sp| !sp.is_dummy())
+    }
+
     /// Returns `true` if this contains only a dummy primary span with any hygienic context.
     pub fn is_dummy(&self) -> bool {
         let mut is_dummy = true;
@@ -726,6 +731,11 @@ pub fn span_labels(&self) -> Vec<SpanLabel> {
 
         span_labels
     }
+
+    /// Returns whether any of the span labels is displayable.
+    pub fn has_span_labels(&self) -> bool {
+        self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
+    }
 }
 
 impl From<Span> for MultiSpan {
diff --git a/src/test/codegen/simd-intrinsic-generic-bitmask.rs b/src/test/codegen/simd-intrinsic-generic-bitmask.rs
new file mode 100644 (file)
index 0000000..cd8130f
--- /dev/null
@@ -0,0 +1,57 @@
+// compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x2(u32, u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i32x2(i32, i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i8x16(
+    i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8,
+);
+
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+// CHECK-LABEL: @bitmask_int
+#[no_mangle]
+pub unsafe fn bitmask_int(x: i32x2) -> u8 {
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, <i32 31, i32 31>
+    // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
+    // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
+    // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
+    simd_bitmask(x)
+}
+
+// CHECK-LABEL: @bitmask_uint
+#[no_mangle]
+pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, <i32 31, i32 31>
+    // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
+    // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
+    // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
+    simd_bitmask(x)
+}
+
+// CHECK-LABEL: @bitmask_int16
+#[no_mangle]
+pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
+    // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{[0-9]+}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
+    // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
+    // CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
+    // CHECK-NOT: zext
+    simd_bitmask(x)
+}
diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs
deleted file mode 100644 (file)
index d0e0521..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// ignore-cross-compile
-
-// error-pattern:expected expression, found statement (`let`)
-
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-extern crate syntax_pos;
-
-use syntax::ast;
-use syntax::source_map;
-use syntax::print::pprust;
-use syntax::symbol::Symbol;
-use syntax_pos::DUMMY_SP;
-
-fn main() {
-    syntax::with_globals(|| run());
-}
-
-fn run() {
-    let ps = syntax::parse::ParseSess::new(source_map::FilePathMapping::empty());
-    let mut resolver = syntax::ext::base::DummyResolver;
-    let mut cx = syntax::ext::base::ExtCtxt::new(
-        &ps,
-        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()),
-        &mut resolver);
-    let cx = &mut cx;
-
-    println!("{}", pprust::expr_to_string(&*quote_expr!(&cx, 23)));
-    assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");
-
-    let expr = quote_expr!(&cx, let x isize = 20;);
-    println!("{}", pprust::expr_to_string(&*expr));
-    assert_eq!(pprust::expr_to_string(&*expr), "let x isize = 20;");
-}
diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-16723.rs b/src/test/run-pass-fulldeps/auxiliary/issue-16723.rs
deleted file mode 100644 (file)
index 76680f5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// force-host
-
-#![feature(plugin_registrar, quote, rustc_private)]
-#![crate_type = "dylib"]
-
-extern crate syntax;
-extern crate rustc;
-extern crate rustc_data_structures;
-extern crate rustc_plugin;
-#[macro_use] extern crate smallvec;
-extern crate syntax_pos;
-
-use smallvec::SmallVec;
-use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
-use syntax::tokenstream;
-use rustc_plugin::Registry;
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_macro("multiple_items", expand)
-}
-
-fn expand(cx: &mut ExtCtxt, _: syntax_pos::Span, _: &[tokenstream::TokenTree])
-          -> Box<MacResult+'static> {
-    MacEager::items(smallvec![
-        quote_item!(cx, struct Struct1;).unwrap(),
-        quote_item!(cx, struct Struct2;).unwrap()
-    ])
-}
index e31628782dc473586acbb797c33fa27e044b996b..a2b1d6976d0eb7e0db2c0ca96712b6fff5c4cfea 100644 (file)
 // force-host
+// no-prefer-dynamic
 
-#![feature(plugin_registrar, quote, rustc_private)]
+#![crate_type = "proc-macro"]
+#![feature(rustc_private)]
 
 extern crate syntax;
 extern crate rustc;
 extern crate rustc_plugin;
 extern crate syntax_pos;
-
-use syntax::ast::{self, Item, MetaItem, ItemKind};
-use syntax::source_map::DUMMY_SP;
-use syntax::ext::base::*;
-use syntax::ext::quote::rt::ToTokens;
-use syntax::parse::{self, token};
-use syntax::ptr::P;
-use syntax::symbol::Symbol;
-use syntax::tokenstream::TokenTree;
-use syntax_pos::Span;
-use rustc_plugin::Registry;
-
-#[macro_export]
-macro_rules! exported_macro { () => (2) }
-macro_rules! unexported_macro { () => (3) }
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_macro("make_a_1", expand_make_a_1);
-    reg.register_macro("identity", expand_identity);
-    reg.register_syntax_extension(
-        Symbol::intern("rustc_into_multi_foo"),
-        MultiModifier(Box::new(expand_into_foo_multi)));
-    reg.register_syntax_extension(
-        Symbol::intern("rustc_duplicate"),
-        MultiDecorator(Box::new(expand_duplicate)));
-    reg.register_syntax_extension(
-        Symbol::intern("rustc_caller"),
-        MultiDecorator(Box::new(expand_caller)));
-}
-
-fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
-    if !tts.is_empty() {
-        cx.span_fatal(sp, "make_a_1 takes no arguments");
-    }
-    MacEager::expr(quote_expr!(cx, 1))
-}
-
-// See Issue #15750
-fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
-    // Parse an expression and emit it unchanged.
-    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.to_vec());
-    let expr = parser.parse_expr().unwrap();
-    MacEager::expr(quote_expr!(&mut *cx, $expr))
-}
-
-fn expand_into_foo_multi(cx: &mut ExtCtxt,
-                         _sp: Span,
-                         _attr: &MetaItem,
-                         it: Annotatable)
-                         -> Vec<Annotatable> {
-    match it {
-        Annotatable::Item(it) => vec![
-            Annotatable::Item(P(Item {
-                attrs: it.attrs.clone(),
-                ..(*quote_item!(cx, enum Foo2 { Bar2, Baz2 }).unwrap()).clone()
-            })),
-            Annotatable::Item(quote_item!(cx, enum Foo3 { Bar }).unwrap()),
-            Annotatable::Item(quote_item!(cx, #[cfg(any())] fn foo2() {}).unwrap()),
-        ],
-        Annotatable::ImplItem(_it) => vec![
-            quote_item!(cx, impl X { fn foo(&self) -> i32 { 42 } }).unwrap().and_then(|i| {
-                match i.node {
-                    ItemKind::Impl(.., mut items) => {
-                        Annotatable::ImplItem(P(items.pop().expect("impl method not found")))
-                    }
-                    _ => unreachable!("impl parsed to something other than impl")
-                }
-            })
-        ],
-        Annotatable::TraitItem(_it) => vec![
-            quote_item!(cx, trait X { fn foo(&self) -> i32 { 0 } }).unwrap().and_then(|i| {
-                match i.node {
-                    ItemKind::Trait(.., mut items) => {
-                        Annotatable::TraitItem(P(items.pop().expect("trait method not found")))
-                    }
-                    _ => unreachable!("trait parsed to something other than trait")
-                }
-            })
-        ],
-        // covered in proc_macro/macros-in-extern.rs
-        Annotatable::ForeignItem(..) => unimplemented!(),
-        // covered in proc_macro/attr-stmt-expr.rs
-        Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item"),
-    }
+extern crate proc_macro;
+
+use proc_macro::{TokenTree, TokenStream};
+
+#[proc_macro_attribute]
+pub fn rustc_duplicate(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let mut new_name = Some(attr.into_iter().nth(0).unwrap());
+    let mut encountered_idents = 0;
+    let input = item.to_string();
+    let ret = item.into_iter().map(move |token| match token {
+        TokenTree::Ident(_) if encountered_idents == 1 => {
+            encountered_idents += 1;
+            new_name.take().unwrap()
+        }
+        TokenTree::Ident(_) => {
+            encountered_idents += 1;
+            token
+        }
+        _ => token
+    }).collect::<TokenStream>();
+    let mut input_again = input.parse::<TokenStream>().unwrap();
+    input_again.extend(ret);
+    input_again
 }
-
-// Create a duplicate of the annotatable, based on the MetaItem
-fn expand_duplicate(cx: &mut ExtCtxt,
-                    _sp: Span,
-                    mi: &MetaItem,
-                    it: &Annotatable,
-                    push: &mut FnMut(Annotatable)) {
-    let copy_name = match mi.node {
-        ast::MetaItemKind::List(ref xs) => {
-            if let Some(word) = xs[0].word() {
-                word.ident.segments.last().unwrap().ident
-            } else {
-                cx.span_err(mi.span, "Expected word");
-                return;
-            }
-        }
-        _ => {
-            cx.span_err(mi.span, "Expected list");
-            return;
-        }
-    };
-
-    // Duplicate the item but replace its ident by the MetaItem
-    match it.clone() {
-        Annotatable::Item(it) => {
-            let mut new_it = (*it).clone();
-            new_it.attrs.clear();
-            new_it.ident = copy_name;
-            push(Annotatable::Item(P(new_it)));
-        }
-        Annotatable::ImplItem(it) => {
-            let mut new_it = (*it).clone();
-            new_it.attrs.clear();
-            new_it.ident = copy_name;
-            push(Annotatable::ImplItem(P(new_it)));
-        }
-        Annotatable::TraitItem(tt) => {
-            let mut new_it = (*tt).clone();
-            new_it.attrs.clear();
-            new_it.ident = copy_name;
-            push(Annotatable::TraitItem(P(new_it)));
-        }
-        // covered in proc_macro/macros-in-extern.rs
-        Annotatable::ForeignItem(..) => unimplemented!(),
-        // covered in proc_macro/attr-stmt-expr.rs
-        Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
-    }
-}
-
-pub fn token_separate<T: ToTokens>(ecx: &ExtCtxt, things: &[T],
-                                   token: token::Token) -> Vec<TokenTree> {
-    let mut output: Vec<TokenTree> = vec![];
-    for (i, thing) in things.iter().enumerate() {
-        output.extend(thing.to_tokens(ecx));
-        if i < things.len() - 1 {
-            output.push(TokenTree::Token(DUMMY_SP, token.clone()));
-        }
-    }
-
-    output
-}
-
-fn expand_caller(cx: &mut ExtCtxt,
-                 sp: Span,
-                 mi: &MetaItem,
-                 it: &Annotatable,
-                 push: &mut FnMut(Annotatable)) {
-    let (orig_fn_name, ret_type) = match *it {
-        Annotatable::Item(ref item) => match item.node {
-            ItemKind::Fn(ref decl, ..) => {
-                (item.ident, &decl.output)
-            }
-            _ => cx.span_fatal(item.span, "Only functions with return types can be annotated.")
-        },
-        _ => cx.span_fatal(sp, "Only functions can be annotated.")
-    };
-
-    let (caller_name, arguments) = if let Some(list) = mi.meta_item_list() {
-        if list.len() < 2 {
-            cx.span_fatal(mi.span(), "Need a function name and at least one parameter.");
-        }
-
-        let fn_name = match list[0].name() {
-            Some(name) => ast::Ident::with_empty_ctxt(name),
-            None => cx.span_fatal(list[0].span(), "First parameter must be an ident.")
-        };
-
-        (fn_name, &list[1..])
-    } else {
-        cx.span_fatal(mi.span, "Expected list.");
-    };
-
-    let literals: Vec<ast::Lit> = arguments.iter().map(|arg| {
-        if let Some(lit) = arg.literal() {
-            lit.clone()
-        } else {
-            cx.span_fatal(arg.span(), "Expected literal.");
-        }
-    }).collect();
-
-    let arguments = token_separate(cx, literals.as_slice(), token::Comma);
-    if let ast::FunctionRetTy::Ty(ref rt) = *ret_type {
-        push(Annotatable::Item(quote_item!(cx,
-                                           fn $caller_name() -> $rt {
-                                               $orig_fn_name($arguments)
-                                           }).unwrap()))
-    } else {
-        push(Annotatable::Item(quote_item!(cx,
-                                           fn $caller_name() {
-                                               $orig_fn_name($arguments)
-                                           }).unwrap()))
-    }
-}
-
-pub fn foo() {}
diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_with_plugin_lib.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_with_plugin_lib.rs
deleted file mode 100644 (file)
index 320b77e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// force-host
-
-#![feature(plugin_registrar, rustc_private)]
-#![deny(plugin_as_library)] // should have no effect in a plugin crate
-
-extern crate macro_crate_test;
-extern crate rustc;
-extern crate rustc_plugin;
-
-use rustc_plugin::Registry;
-
-#[plugin_registrar]
-pub fn plugin_registrar(_: &mut Registry) { }
diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
deleted file mode 100644 (file)
index e2fa374..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// force-host
-
-#![crate_type="dylib"]
-#![feature(plugin_registrar, quote, rustc_private)]
-
-extern crate syntax;
-extern crate syntax_pos;
-extern crate rustc;
-extern crate rustc_plugin;
-
-use syntax::feature_gate::Features;
-use syntax::parse::token::{NtExpr, NtPat};
-use syntax::ast::{Ident, Pat, NodeId};
-use syntax::tokenstream::{TokenTree};
-use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
-use syntax::ext::build::AstBuilder;
-use syntax::ext::tt::quoted;
-use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
-use syntax::ext::tt::macro_parser::{Success, Failure, Error};
-use syntax::ext::tt::macro_parser::parse_failure_msg;
-use syntax::ptr::P;
-use syntax_pos::{Span, edition::Edition};
-use rustc_plugin::Registry;
-
-fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree])
-        -> Box<MacResult + 'static> {
-
-    let mbe_matcher = quote_tokens!(cx, $$matched:expr, $$($$pat:pat)|+);
-    let mbe_matcher = quoted::parse(mbe_matcher.into_iter().collect(),
-                                    true,
-                                    cx.parse_sess,
-                                    &Features::new(),
-                                    &[],
-                                    Edition::Edition2015,
-                                    // not used...
-                                    NodeId::from_u32(0));
-    let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) {
-        Success(map) => map,
-        Failure(_, tok, msg) => {
-            panic!("expected Success, but got Failure: {} - {}", parse_failure_msg(tok), msg);
-        }
-        Error(_, s) => {
-            panic!("expected Success, but got Error: {}", s);
-        }
-    };
-
-    let matched_nt = match *map[&Ident::from_str("matched")] {
-        MatchedNonterminal(ref nt) => nt.clone(),
-        _ => unreachable!(),
-    };
-
-    let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) {
-        (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => {
-            let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt| {
-                match *pat_nt {
-                    MatchedNonterminal(ref nt) => match **nt {
-                        NtPat(ref pat) => pat.clone(),
-                        _ => unreachable!(),
-                    },
-                    _ => unreachable!(),
-                }
-            }).collect();
-            let span = seq_sp.entire();
-            let arm = cx.arm(span, pats, cx.expr_bool(span, true));
-
-            quote_expr!(cx,
-                match $matched_expr {
-                    $arm
-                    _ => false
-                }
-            )
-        }
-        _ => unreachable!()
-    };
-
-    MacEager::expr(mac_expr)
-}
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_macro("matches", expand_mbe_matches);
-}
diff --git a/src/test/run-pass-fulldeps/auxiliary/syntax_extension_with_dll_deps_2.rs b/src/test/run-pass-fulldeps/auxiliary/syntax_extension_with_dll_deps_2.rs
deleted file mode 100644 (file)
index a356df5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// force-host
-
-#![crate_type = "dylib"]
-#![feature(plugin_registrar, quote, rustc_private)]
-
-extern crate syntax_extension_with_dll_deps_1 as other;
-extern crate syntax;
-extern crate syntax_pos;
-extern crate rustc;
-extern crate rustc_plugin;
-
-use syntax::ast::{Item, MetaItem};
-use syntax::ext::base::*;
-use syntax::tokenstream::TokenTree;
-use syntax_pos::Span;
-use rustc_plugin::Registry;
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_macro("foo", expand_foo);
-}
-
-fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
-              -> Box<MacResult+'static> {
-    let answer = other::the_answer();
-    MacEager::expr(quote_expr!(cx, $answer))
-}
diff --git a/src/test/run-pass-fulldeps/issue-16723.rs b/src/test/run-pass-fulldeps/issue-16723.rs
deleted file mode 100644 (file)
index a3965f9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// ignore-stage1
-// aux-build:issue-16723.rs
-#![feature(plugin)]
-#![plugin(issue_16723)]
-
-multiple_items!();
-
-impl Struct1 {
-    fn foo() {}
-}
-impl Struct2 {
-    fn foo() {}
-}
-
-fn main() {
-    Struct1::foo();
-    Struct2::foo();
-    println!("hallo");
-}
diff --git a/src/test/run-pass-fulldeps/issue-16992.rs b/src/test/run-pass-fulldeps/issue-16992.rs
deleted file mode 100644 (file)
index e5945b6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// ignore-cross-compile
-
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-
-use syntax::ext::base::ExtCtxt;
-
-#[allow(dead_code)]
-fn foobar(cx: &mut ExtCtxt) {
-    quote_expr!(cx, 1);
-    quote_expr!(cx, 2);
-}
-
-fn main() { }
diff --git a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs
deleted file mode 100644 (file)
index 9fa3d3d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#![allow(dead_code)]
-#![allow(unused_imports)]
-// ignore-cross-compile
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-
-use syntax::ext::base::ExtCtxt;
-
-fn syntax_extension(cx: &ExtCtxt) {
-    let _toks_1 = vec![quote_tokens!(cx, /** comment */ fn foo() {})];
-    let name = quote_tokens!(cx, bar);
-    let _toks_2 = vec![quote_item!(cx, static $name:isize = 2;)];
-    let _toks_4 = quote_tokens!(cx, $name:static $name:sizeof);
-    let _toks_3 = vec![quote_item!(cx,
-        /// comment
-        fn foo() { let $name:isize = 3; }
-    )];
-}
-
-fn main() {
-}
diff --git a/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs b/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs
deleted file mode 100644 (file)
index 3c251cc..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-
-// Issue #15750: a macro that internally parses its input and then
-// uses `quote_expr!` to rearrange it should be hygiene-preserving.
-
-#![feature(plugin)]
-#![plugin(macro_crate_test)]
-
-fn main() {
-    let x = 3;
-    assert_eq!(3, identity!(x));
-    assert_eq!(6, identity!(x+x));
-    let x = 4;
-    assert_eq!(4, identity!(x));
-}
diff --git a/src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs b/src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs
deleted file mode 100644 (file)
index eb7ab13..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#![allow(plugin_as_library)]
-#![allow(unused_imports)]
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-
-#![feature(plugin, rustc_attrs)]
-#![plugin(macro_crate_test)]
-
-#[macro_use]
-#[no_link]
-extern crate macro_crate_test;
-
-// The `caller(name, args...)` attribute emits a new nullary function named
-// `name` that calls the annotated function with `args`. As an example, consider
-// the following:
-//
-//     #[caller(simple, 1, "hello", 3.14)]
-//     fn f(num: isize, string: &'static str, float: f32) -> (isize, &'static str, float) {
-//         (num, string, float)
-//     }
-//
-// This results in a function named `simple` that calls `f(1, "hello", 3.14)`.
-// As a result, the expression `simple()` evaluates to `(1, "helllo", 3.14)`.
-
-#[rustc_caller(simple, 1, "hello", 3.14)]
-#[rustc_caller(simple1, 2, "bye", 6.28)]
-#[rustc_caller(simple2, 3, "hi", 1.01)]
-fn f(num: isize, string: &'static str, float: f32) -> (isize, &'static str, f32) {
-    (num, string, float)
-}
-
-#[rustc_caller(complex, true, 10)]
-#[rustc_caller(complex1, false, 15)]
-#[rustc_caller(complex2, true, 20)]
-fn g(emit: bool, num: i32) -> Option<i32> {
-    match emit {
-        true => Some(num),
-        false => None
-    }
-}
-
-fn main() {
-    assert_eq!(simple(), (1, "hello", 3.14));
-    assert_eq!(simple1(), (2, "bye", 6.28));
-    assert_eq!(simple2(), (3, "hi", 1.01));
-
-    assert_eq!(complex(), Some(10));
-    assert_eq!(complex1(), None);
-    assert_eq!(complex2(), Some(20));
-}
index ef28f233feaa19168464649b8ac7ed2ec04ec507..dcac160c4c9745df9a83e143c618749473f492d3 100644 (file)
@@ -5,11 +5,9 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
-#![feature(plugin, rustc_attrs)]
-#![plugin(macro_crate_test)]
+#![feature(rustc_attrs)]
 
 #[macro_use]
-#[no_link]
 extern crate macro_crate_test;
 
 // The duplicate macro will create a copy of the item with the given identifier.
diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs
deleted file mode 100644 (file)
index 62838c2..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#![allow(plugin_as_library)]
-#![allow(dead_code)]
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-
-#![feature(plugin, rustc_attrs)]
-#![plugin(macro_crate_test)]
-
-#[macro_use] #[no_link]
-extern crate macro_crate_test;
-
-#[rustc_into_multi_foo]
-#[derive(PartialEq, Clone, Debug)]
-fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
-
-// Check that the `#[into_multi_foo]`-generated `foo2` is configured away
-fn foo2() {}
-
-trait Qux {
-    #[rustc_into_multi_foo]
-    fn bar();
-}
-
-impl Qux for i32 {
-    #[rustc_into_multi_foo]
-    fn bar() {}
-}
-
-impl Qux for u8 {}
-
-pub fn main() {
-    assert_eq!(1, make_a_1!());
-    assert_eq!(2, exported_macro!());
-
-    assert_eq!(Foo2::Bar2, Foo2::Bar2);
-    test(None::<Foo2>);
-
-    let _ = Foo3::Bar;
-
-    let x = 10i32;
-    assert_eq!(x.foo(), 42);
-    let x = 10u8;
-    assert_eq!(x.foo(), 0);
-}
-
-fn test<T: PartialEq+Clone>(_: Option<T>) {}
diff --git a/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs b/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs
deleted file mode 100644 (file)
index c672081..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// aux-build:procedural_mbe_matching.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(procedural_mbe_matching)]
-
-pub fn main() {
-    assert_eq!(matches!(Some(123), None | Some(0)), false);
-    assert_eq!(matches!(Some(123), None | Some(123)), true);
-    assert_eq!(matches!(true, true), true);
-}
diff --git a/src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs b/src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs
deleted file mode 100644 (file)
index e9f234f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// aux-build:macro_crate_test.rs
-// aux-build:plugin_with_plugin_lib.rs
-// ignore-stage1
-// ignore-cross-compile
-//
-// macro_crate_test will not compile on a cross-compiled target because
-// libsyntax is not compiled for it.
-
-#![deny(plugin_as_library)]
-#![feature(plugin)]
-#![plugin(macro_crate_test)]
-#![plugin(plugin_with_plugin_lib)]
-
-fn main() {
-    assert_eq!(1, make_a_1!());
-}
diff --git a/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs b/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs
deleted file mode 100644 (file)
index e45a7f5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-// ignore-cross-compile
-//
-// macro_crate_test will not compile on a cross-compiled target because
-// libsyntax is not compiled for it.
-
-#![allow(plugin_as_library)]
-#![feature(plugin)]
-#![plugin(macro_crate_test)]
-
-extern crate macro_crate_test;
-
-fn main() {
-    assert_eq!(1, make_a_1!());
-    macro_crate_test::foo();
-}
diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs
deleted file mode 100644 (file)
index 33063fc..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-#![allow(unused_imports)]
-// ignore-cross-compile
-
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-extern crate syntax_pos;
-
-use syntax::source_map::FilePathMapping;
-use syntax::print::pprust::*;
-use syntax::symbol::Symbol;
-use syntax_pos::DUMMY_SP;
-
-fn main() {
-    syntax::with_globals(|| run());
-}
-
-fn run() {
-    let ps = syntax::parse::ParseSess::new(FilePathMapping::empty());
-    let mut resolver = syntax::ext::base::DummyResolver;
-    let mut cx = syntax::ext::base::ExtCtxt::new(
-        &ps,
-        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()),
-        &mut resolver);
-    let cx = &mut cx;
-
-    macro_rules! check {
-        ($f: ident, $($e: expr),+; $expect: expr) => ({
-            $(assert_eq!($f(&$e), $expect);)+
-        });
-    }
-
-    let abc = quote_expr!(cx, 23);
-    check!(expr_to_string, abc, *quote_expr!(cx, $abc); "23");
-
-    let ty = quote_ty!(cx, isize);
-    check!(ty_to_string, ty, *quote_ty!(cx, $ty); "isize");
-
-    let item = quote_item!(cx, static x: $ty = 10;).unwrap();
-    check!(item_to_string, item, quote_item!(cx, $item).unwrap(); "static x: isize = 10;");
-
-    let twenty: u16 = 20;
-    let stmt = quote_stmt!(cx, let x = $twenty;).unwrap();
-    check!(stmt_to_string, stmt, quote_stmt!(cx, $stmt).unwrap(); "let x = 20u16;");
-
-    let pat = quote_pat!(cx, Some(_));
-    check!(pat_to_string, pat, *quote_pat!(cx, $pat); "Some(_)");
-
-    let expr = quote_expr!(cx, (x, y));
-    let arm = quote_arm!(cx, (ref x, ref y) => $expr,);
-    check!(arm_to_string, arm, quote_arm!(cx, $arm); " (ref x, ref y) => (x, y),");
-
-    let attr = quote_attr!(cx, #![cfg(foo = "bar")]);
-    check!(attribute_to_string, attr, quote_attr!(cx, $attr); r#"#![cfg(foo = "bar")]"#);
-
-    // quote_arg!
-
-    let arg = quote_arg!(cx, foo: i32);
-    check!(arg_to_string, arg, quote_arg!(cx, $arg); "foo: i32");
-
-    let function = quote_item!(cx, fn f($arg) { }).unwrap();
-    check!(item_to_string, function; "fn f(foo: i32) { }");
-
-    let args = vec![arg, quote_arg!(cx, bar: u32)];
-    let args = &args[..];
-    let function = quote_item!(cx, fn f($args) { }).unwrap();
-    check!(item_to_string, function; "fn f(foo: i32, bar: u32) { }");
-
-    // quote_block!
-
-    let block = quote_block!(cx, { $stmt let y = 40u32; });
-    check!(block_to_string, block, *quote_block!(cx, $block); "{ let x = 20u16; let y = 40u32; }");
-
-    let function = quote_item!(cx, fn f() $block).unwrap();
-    check!(item_to_string, function; "fn f() { let x = 20u16; let y = 40u32; }");
-
-    // quote_path!
-
-    let path = quote_path!(cx, ::syntax::ptr::P<MetaItem>);
-    check!(path_to_string, path, quote_path!(cx, $path); "::syntax::ptr::P<MetaItem>");
-
-    let ty = quote_ty!(cx, $path);
-    check!(ty_to_string, ty; "::syntax::ptr::P<MetaItem>");
-
-    // quote_meta_item!
-
-    let meta = quote_meta_item!(cx, cfg(foo = "bar"));
-    check!(meta_item_to_string, meta, quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#);
-
-    let attr = quote_attr!(cx, #![$meta]);
-    check!(attribute_to_string, attr; r#"#![cfg(foo = "bar")]"#);
-}
diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs
deleted file mode 100644 (file)
index 04a4c44..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![allow(unused_imports)]
-// ignore-cross-compile
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-
-use syntax::ext::base::ExtCtxt;
-use syntax::ptr::P;
-use syntax::parse::PResult;
-
-fn syntax_extension(cx: &ExtCtxt) {
-    let e_toks : Vec<syntax::tokenstream::TokenTree> = quote_tokens!(cx, 1 + 2);
-    let p_toks : Vec<syntax::tokenstream::TokenTree> = quote_tokens!(cx, (x, 1 .. 4, *));
-
-    let a: P<syntax::ast::Expr> = quote_expr!(cx, 1 + 2);
-    let _b: Option<P<syntax::ast::Item>> = quote_item!(cx, static foo : isize = $e_toks; );
-    let _c: P<syntax::ast::Pat> = quote_pat!(cx, (x, 1 .. 4, *) );
-    let _d: Option<syntax::ast::Stmt> = quote_stmt!(cx, let x = $a; );
-    let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) );
-    let _e: P<syntax::ast::Expr> = quote_expr!(cx, match foo { $p_toks => 10 } );
-
-    let _f: P<syntax::ast::Expr> = quote_expr!(cx, ());
-    let _g: P<syntax::ast::Expr> = quote_expr!(cx, true);
-    let _h: P<syntax::ast::Expr> = quote_expr!(cx, 'a');
-
-    let i: Option<P<syntax::ast::Item>> = quote_item!(cx, #[derive(Eq)] struct Foo; );
-    assert!(i.is_some());
-
-    let _l: P<syntax::ast::Ty> = quote_ty!(cx, &isize);
-
-    let _n: syntax::ast::Attribute = quote_attr!(cx, #![cfg(foo, bar = "baz")]);
-
-    let _o: Option<P<syntax::ast::Item>> = quote_item!(cx, fn foo<T: ?Sized>() {});
-
-    let stmts = vec![
-        quote_stmt!(cx, let x = 1;).unwrap(),
-        quote_stmt!(cx, let y = 2;).unwrap(),
-    ];
-    let expr: P<syntax::ast::Expr> = quote_expr!(cx, x + y);
-}
-
-fn main() {
-}
diff --git a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs
deleted file mode 100644 (file)
index 1568bf2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#![allow(dead_code)]
-// ignore-cross-compile
-#![feature(quote, rustc_private)]
-#![deny(unused_variables)]
-
-extern crate syntax;
-
-use syntax::ext::base::ExtCtxt;
-
-fn test(cx: &mut ExtCtxt) {
-    let foo = 10;
-    let _e = quote_expr!(cx, $foo);
-}
-
-pub fn main() { }
diff --git a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
deleted file mode 100644 (file)
index 7c236fd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// aux-build:syntax_extension_with_dll_deps_1.rs
-// aux-build:syntax_extension_with_dll_deps_2.rs
-// ignore-stage1
-
-#![feature(plugin, rustc_private)]
-#![plugin(syntax_extension_with_dll_deps_2)]
-
-fn main() {
-    foo!();
-}
diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-bitmask.rs b/src/test/run-pass/simd/simd-intrinsic-generic-bitmask.rs
new file mode 100644 (file)
index 0000000..b28f742
--- /dev/null
@@ -0,0 +1,61 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// ignore-emscripten
+
+// Test that the simd_bitmask intrinsic produces correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u8x4(pub u8, pub u8, pub u8, pub u8);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct Tx4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+fn main() {
+    let z = u32x4(0, 0, 0, 0);
+    let ez = 0_u8;
+
+    let o = u32x4(!0, !0, !0, !0);
+    let eo = 0b_1111_u8;
+
+    let m0 = u32x4(!0, 0, !0, 0);
+    let e0 = 0b_0000_0101_u8;
+
+    // Check that the MSB is extracted:
+    let m = u8x4(0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111);
+    let e = 0b_1101;
+
+    // Check usize / isize
+    let msize: Tx4<usize> = Tx4(usize::max_value(), 0, usize::max_value(), usize::max_value());
+
+    unsafe {
+        let r: u8 = simd_bitmask(z);
+        assert_eq!(r, ez);
+
+        let r: u8 = simd_bitmask(o);
+        assert_eq!(r, eo);
+
+        let r: u8 = simd_bitmask(m0);
+        assert_eq!(r, e0);
+
+        let r: u8 = simd_bitmask(m);
+        assert_eq!(r, e);
+
+        let r: u8 = simd_bitmask(msize);
+        assert_eq!(r, e);
+
+    }
+}
diff --git a/src/test/run-pass/try_from.rs b/src/test/run-pass/try_from.rs
new file mode 100644 (file)
index 0000000..4522ce3
--- /dev/null
@@ -0,0 +1,37 @@
+// This test relies on `TryFrom` being blanket impl for all `T: Into`
+// and `TryInto` being blanket impl for all `U: TryFrom`
+
+// This test was added to show the motivation for doing this
+// over `TryFrom` being blanket impl for all `T: From`
+
+#![feature(try_from, never_type)]
+
+use std::convert::TryInto;
+
+struct Foo<T> {
+    t: T,
+}
+
+// This fails to compile due to coherence restrictions
+// as of Rust version 1.32.x, therefore it could not be used
+// instead of the `Into` version of the impl, and serves as
+// motivation for a blanket impl for all `T: Into`, instead
+// of a blanket impl for all `T: From`
+/*
+impl<T> From<Foo<T>> for Box<T> {
+    fn from(foo: Foo<T>) -> Box<T> {
+        Box::new(foo.t)
+    }
+}
+*/
+
+impl<T> Into<Vec<T>> for Foo<T> {
+    fn into(self) -> Vec<T> {
+        vec![self.t]
+    }
+}
+
+pub fn main() {
+    let _: Result<Vec<i32>, !> = Foo { t: 10 }.try_into();
+}
+
index 537816be8d73528f0487ba6c4cd1c5f21e1a4872..924e0386d3191e00b3414db3392ee43af9e26133 100644 (file)
@@ -1,7 +1,66 @@
 // compile-pass
-// compile-flags: --error-format=human
 
 /// ```
 /// \__________pkt->size___________/          \_result->size_/ \__pkt->size__/
 /// ```
 pub fn foo() {}
+
+/// ```
+///    |
+/// LL | use foobar::Baz;
+///    |     ^^^^^^ did you mean `baz::foobar`?
+/// ```
+pub fn bar() {}
+
+/// ```
+/// valid
+/// ```
+///
+/// ```
+/// \_
+/// ```
+///
+/// ```text
+/// "invalid
+/// ```
+pub fn valid_and_invalid() {}
+
+/// This is a normal doc comment, but...
+///
+/// There's a code block with bad syntax in it:
+///
+/// ```rust
+/// \_
+/// ```
+///
+/// Good thing we tested it!
+pub fn baz() {}
+
+/// Indented block start
+///
+///     code with bad syntax
+///     \_
+///
+/// Indented block end
+pub fn quux() {}
+
+/// Unclosed fence
+///
+/// ```
+/// slkdjf
+pub fn xyzzy() {}
+
+/// Indented code that contains a fence
+///
+///     ```
+pub fn blah() {}
+
+/// ```edition2018
+/// \_
+/// ```
+pub fn blargh() {}
+
+#[doc = "```"]
+/// \_
+#[doc = "```"]
+pub fn crazy_attrs() {}
index b5661332e8d0e587ba38ae0eaabba31fbe6ae92a..10800380a05d3ca34d13d4ab0fd04431d426edb7 100644 (file)
@@ -1,10 +1,97 @@
-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)
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:3:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | /// /__________pkt->size___________/          /_result->size_/ /__pkt->size__/
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:8:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | ///    |
+LL | | /// LL | use foobar::Baz;
+LL | | ///    |     ^^^^^^ did you mean `baz::foobar`?
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: `
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:19:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | /// /_
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:32:5
+   |
+LL |   /// ```rust
+   |  _____^
+LL | | /// /_
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:41:9
+   |
+LL |   ///     code with bad syntax
+   |  _________^
+LL | | ///     /_
+   | |__________^
+   |
+   = note: error from rustc: unknown start of token: /
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:55:9
+   |
+LL | ///     ```
+   |         ^^^
+   |
+   = note: error from rustc: unknown start of token: `
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:58:5
+   |
+LL |   /// ```edition2018
+   |  _____^
+LL | | /// /_
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+
+warning: doc comment contains an invalid Rust code block
+  --> $DIR/invalid-syntax.rs:63:1
+   |
+LL | / #[doc = "```"]
+LL | | /// /_
+LL | | #[doc = "```"]
+   | |______________^
+   |
+   = help: mark blocks that do not contain Rust code as text: ```text
 
diff --git a/src/test/rustdoc/bad-codeblock-syntax.rs b/src/test/rustdoc/bad-codeblock-syntax.rs
new file mode 100644 (file)
index 0000000..0ab2f68
--- /dev/null
@@ -0,0 +1,27 @@
+// @has bad_codeblock_syntax/fn.foo.html
+// @has - '//*[@class="docblock"]/pre/code' '\_'
+/// ```
+/// \_
+/// ```
+pub fn foo() {}
+
+// @has bad_codeblock_syntax/fn.bar.html
+// @has - '//*[@class="docblock"]/pre/code' '`baz::foobar`'
+/// ```
+/// `baz::foobar`
+/// ```
+pub fn bar() {}
+
+// @has bad_codeblock_syntax/fn.quux.html
+// @has - '//*[@class="docblock"]/pre/code' '\_'
+/// ```rust
+/// \_
+/// ```
+pub fn quux() {}
+
+// @has bad_codeblock_syntax/fn.ok.html
+// @has - '//*[@class="docblock"]/pre/code[@class="language-text"]' '\_'
+/// ```text
+/// \_
+/// ```
+pub fn ok() {}
index d4d70d04f5b4eca38407f525496c0bc7a250fade..1e396f1be0e0440ce8c24e3b23bce3e26d780824 100644 (file)
@@ -4,6 +4,11 @@
 #![crate_type="proc-macro"]
 #![crate_name="some_macros"]
 
+// @has some_macros/index.html
+// @has - '//a/[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
+
+//! include a link to [some_proc_attr] to make sure it works.
+
 extern crate proc_macro;
 
 use proc_macro::TokenStream;
diff --git a/src/test/ui-fulldeps/auxiliary/macro_crate_test.rs b/src/test/ui-fulldeps/auxiliary/macro_crate_test.rs
deleted file mode 100644 (file)
index a364aa0..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-// force-host
-
-#![feature(plugin_registrar, quote, rustc_private)]
-
-extern crate syntax;
-extern crate syntax_pos;
-extern crate rustc;
-extern crate rustc_plugin;
-
-use syntax::ast::{self, Item, MetaItem, ItemKind};
-use syntax::ext::base::*;
-use syntax::parse;
-use syntax::ptr::P;
-use syntax::symbol::Symbol;
-use syntax::tokenstream::TokenTree;
-use syntax_pos::Span;
-use rustc_plugin::Registry;
-
-#[macro_export]
-macro_rules! exported_macro { () => (2) }
-macro_rules! unexported_macro { () => (3) }
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_macro("make_a_1", expand_make_a_1);
-    reg.register_macro("identity", expand_identity);
-    reg.register_syntax_extension(
-        Symbol::intern("into_multi_foo"),
-        MultiModifier(Box::new(expand_into_foo_multi)));
-    reg.register_syntax_extension(
-        Symbol::intern("noop_attribute"),
-        MultiModifier(Box::new(expand_noop_attribute)));
-    reg.register_syntax_extension(
-        Symbol::intern("duplicate"),
-        MultiDecorator(Box::new(expand_duplicate)));
-}
-
-fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
-                   -> Box<MacResult+'static> {
-    if !tts.is_empty() {
-        cx.span_fatal(sp, "make_a_1 takes no arguments");
-    }
-    MacEager::expr(quote_expr!(cx, 1))
-}
-
-// See Issue #15750
-fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree])
-                   -> Box<MacResult+'static> {
-    // Parse an expression and emit it unchanged.
-    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.to_vec());
-    let expr = parser.parse_expr().unwrap();
-    MacEager::expr(quote_expr!(&mut *cx, $expr))
-}
-
-fn expand_into_foo_multi(cx: &mut ExtCtxt,
-                         _sp: Span,
-                         _attr: &MetaItem,
-                         it: Annotatable) -> Annotatable {
-    match it {
-        Annotatable::Item(it) => {
-            Annotatable::Item(P(Item {
-                attrs: it.attrs.clone(),
-                ..(*quote_item!(cx, enum Foo2 { Bar2, Baz2 }).unwrap()).clone()
-            }))
-        }
-        Annotatable::ImplItem(_) => {
-            quote_item!(cx, impl X { fn foo(&self) -> i32 { 42 } }).unwrap().and_then(|i| {
-                match i.node {
-                    ItemKind::Impl(.., mut items) => {
-                        Annotatable::ImplItem(P(items.pop().expect("impl method not found")))
-                    }
-                    _ => unreachable!("impl parsed to something other than impl")
-                }
-            })
-        }
-        Annotatable::TraitItem(_) => {
-            quote_item!(cx, trait X { fn foo(&self) -> i32 { 0 } }).unwrap().and_then(|i| {
-                match i.node {
-                    ItemKind::Trait(.., mut items) => {
-                        Annotatable::TraitItem(P(items.pop().expect("trait method not found")))
-                    }
-                    _ => unreachable!("trait parsed to something other than trait")
-                }
-            })
-        }
-        // covered in proc_macro/macros-in-extern.rs
-        Annotatable::ForeignItem(_) => unimplemented!(),
-        // covered in proc_macro/attr-stmt-expr.rs
-        Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
-    }
-}
-
-fn expand_noop_attribute(_cx: &mut ExtCtxt,
-                         _sp: Span,
-                         _attr: &MetaItem,
-                         it: Annotatable) -> Annotatable {
-    it
-}
-
-// Create a duplicate of the annotatable, based on the MetaItem
-fn expand_duplicate(cx: &mut ExtCtxt,
-                    _sp: Span,
-                    mi: &MetaItem,
-                    it: &Annotatable,
-                    push: &mut FnMut(Annotatable))
-{
-    let copy_name = match mi.node {
-        ast::MetaItemKind::List(ref xs) => {
-            if let Some(word) = xs[0].word() {
-                word.ident.segments.last().unwrap().ident
-            } else {
-                cx.span_err(mi.span, "Expected word");
-                return;
-            }
-        }
-        _ => {
-            cx.span_err(mi.span, "Expected list");
-            return;
-        }
-    };
-
-    // Duplicate the item but replace its ident by the MetaItem
-    match it.clone() {
-        Annotatable::Item(it) => {
-            let mut new_it = (*it).clone();
-            new_it.attrs.clear();
-            new_it.ident = copy_name;
-            push(Annotatable::Item(P(new_it)));
-        }
-        Annotatable::ImplItem(it) => {
-            let mut new_it = (*it).clone();
-            new_it.attrs.clear();
-            new_it.ident = copy_name;
-            push(Annotatable::ImplItem(P(new_it)));
-        }
-        Annotatable::TraitItem(tt) => {
-            let mut new_it = (*tt).clone();
-            new_it.attrs.clear();
-            new_it.ident = copy_name;
-            push(Annotatable::TraitItem(P(new_it)));
-        }
-        // covered in proc_macro/macros-in-extern.rs
-        Annotatable::ForeignItem(_) => unimplemented!(),
-        // covered in proc_macro/attr-stmt-expr.rs
-        Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
-    }
-}
-
-pub fn foo() {}
index 3a138d9af03cab38ff698b82951ef1838648a619..a647585e621fe5df0745283484340319bd016db4 100644 (file)
@@ -1,6 +1,6 @@
-// aux-build:macro_crate_test.rs
+// aux-build:attr_plugin_test.rs
 
-#![plugin(macro_crate_test)]
+#![plugin(attr_plugin_test)]
 //~^ ERROR compiler plugins are experimental and possibly buggy
 
 fn main() {}
index a72a45833d0114bb21e8d5d2cfc1ac736105fd15..37c2b4432470d881f0891d9458e4f98e591c8ad5 100644 (file)
@@ -1,7 +1,7 @@
 error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
   --> $DIR/gated-plugin.rs:3:1
    |
-LL | #![plugin(macro_crate_test)]
+LL | #![plugin(attr_plugin_test)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(plugin)] to the crate attributes to enable
diff --git a/src/test/ui-fulldeps/gated-quote.rs b/src/test/ui-fulldeps/gated-quote.rs
deleted file mode 100644 (file)
index 86848e3..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// Test that `quote`-related macro are gated by `quote` feature gate.
-
-// (To sanity-check the code, uncomment this.)
-// #![feature(quote)]
-
-// FIXME the error message that is current emitted seems pretty bad.
-
-// gate-test-quote
-
-#![feature(rustc_private)]
-#![allow(dead_code, unused_imports, unused_variables)]
-
-#[macro_use]
-extern crate syntax;
-
-use syntax::ast;
-use syntax::parse;
-
-struct ParseSess;
-
-impl ParseSess {
-    fn cfg(&self) -> ast::CrateConfig { loop { } }
-    fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { loop { } }
-    fn call_site(&self) -> () { loop { } }
-    fn ident_of(&self, st: &str) -> ast::Ident { loop { } }
-    fn name_of(&self, st: &str) -> ast::Name { loop { } }
-}
-
-pub fn main() {
-    let ecx = &ParseSess;
-    let x = quote_tokens!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_tokens!` in this scope
-    let x = quote_expr!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_expr!` in this scope
-    let x = quote_ty!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_ty!` in this scope
-    let x = quote_method!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_method!` in this scope
-    let x = quote_item!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_item!` in this scope
-    let x = quote_pat!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_pat!` in this scope
-    let x = quote_arm!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_arm!` in this scope
-    let x = quote_stmt!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_stmt!` in this scope
-    let x = quote_attr!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_attr!` in this scope
-    let x = quote_arg!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_arg!` in this scope
-    let x = quote_block!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_block!` in this scope
-    let x = quote_meta_item!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_meta_item!` in this scope
-    let x = quote_path!(ecx, 3);
-    //~^ ERROR cannot find macro `quote_path!` in this scope
-}
diff --git a/src/test/ui-fulldeps/gated-quote.stderr b/src/test/ui-fulldeps/gated-quote.stderr
deleted file mode 100644 (file)
index 897e97b..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-error: cannot find macro `quote_path!` in this scope
-  --> $DIR/gated-quote.rs:55:13
-   |
-LL |     let x = quote_path!(ecx, 3);
-   |             ^^^^^^^^^^
-
-error: cannot find macro `quote_meta_item!` in this scope
-  --> $DIR/gated-quote.rs:53:13
-   |
-LL |     let x = quote_meta_item!(ecx, 3);
-   |             ^^^^^^^^^^^^^^^
-
-error: cannot find macro `quote_block!` in this scope
-  --> $DIR/gated-quote.rs:51:13
-   |
-LL |     let x = quote_block!(ecx, 3);
-   |             ^^^^^^^^^^^
-
-error: cannot find macro `quote_arg!` in this scope
-  --> $DIR/gated-quote.rs:49:13
-   |
-LL |     let x = quote_arg!(ecx, 3);
-   |             ^^^^^^^^^
-
-error: cannot find macro `quote_attr!` in this scope
-  --> $DIR/gated-quote.rs:47:13
-   |
-LL |     let x = quote_attr!(ecx, 3);
-   |             ^^^^^^^^^^
-
-error: cannot find macro `quote_stmt!` in this scope
-  --> $DIR/gated-quote.rs:45:13
-   |
-LL |     let x = quote_stmt!(ecx, 3);
-   |             ^^^^^^^^^^
-
-error: cannot find macro `quote_arm!` in this scope
-  --> $DIR/gated-quote.rs:43:13
-   |
-LL |     let x = quote_arm!(ecx, 3);
-   |             ^^^^^^^^^
-
-error: cannot find macro `quote_pat!` in this scope
-  --> $DIR/gated-quote.rs:41:13
-   |
-LL |     let x = quote_pat!(ecx, 3);
-   |             ^^^^^^^^^
-
-error: cannot find macro `quote_item!` in this scope
-  --> $DIR/gated-quote.rs:39:13
-   |
-LL |     let x = quote_item!(ecx, 3);
-   |             ^^^^^^^^^^
-
-error: cannot find macro `quote_method!` in this scope
-  --> $DIR/gated-quote.rs:37:13
-   |
-LL |     let x = quote_method!(ecx, 3);
-   |             ^^^^^^^^^^^^
-
-error: cannot find macro `quote_ty!` in this scope
-  --> $DIR/gated-quote.rs:35:13
-   |
-LL |     let x = quote_ty!(ecx, 3);
-   |             ^^^^^^^^
-
-error: cannot find macro `quote_expr!` in this scope
-  --> $DIR/gated-quote.rs:33:13
-   |
-LL |     let x = quote_expr!(ecx, 3);
-   |             ^^^^^^^^^^
-
-error: cannot find macro `quote_tokens!` in this scope
-  --> $DIR/gated-quote.rs:31:13
-   |
-LL |     let x = quote_tokens!(ecx, 3);
-   |             ^^^^^^^^^^^^
-
-error: aborting due to 13 previous errors
-
diff --git a/src/test/ui-fulldeps/issue-48941.rs b/src/test/ui-fulldeps/issue-48941.rs
deleted file mode 100644 (file)
index 8c4c244..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// This is a regression test against an ICE that used to occur
-// on malformed attributes for a custom MultiModifier.
-
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(macro_crate_test)]
-
-#[noop_attribute("hi", rank = a)] //~ ERROR expected unsuffixed literal or identifier, found a
-fn knight() { }
-
-#[noop_attribute("/user", data= = "<user")] //~ ERROR literal or identifier
-fn nite() { }
-
-fn main() {}
diff --git a/src/test/ui-fulldeps/issue-48941.stderr b/src/test/ui-fulldeps/issue-48941.stderr
deleted file mode 100644 (file)
index 6ccea43..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: expected unsuffixed literal or identifier, found a
-  --> $DIR/issue-48941.rs:10:24
-   |
-LL | #[noop_attribute("hi", rank = a)] //~ ERROR expected unsuffixed literal or identifier, found a
-   |                        ^^^^
-
-error: expected unsuffixed literal or identifier, found =
-  --> $DIR/issue-48941.rs:13:27
-   |
-LL | #[noop_attribute("/user", data= = "<user")] //~ ERROR literal or identifier
-   |                           ^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui-fulldeps/macro-crate-doesnt-resolve.rs b/src/test/ui-fulldeps/macro-crate-doesnt-resolve.rs
deleted file mode 100644 (file)
index 1e8de12..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// aux-build:macro_crate_test.rs
-
-#[macro_use] #[no_link]
-extern crate macro_crate_test;
-
-fn main() {
-    macro_crate_test::foo(); //~ ERROR cannot find function `foo` in module `macro_crate_test`
-}
diff --git a/src/test/ui-fulldeps/macro-crate-doesnt-resolve.stderr b/src/test/ui-fulldeps/macro-crate-doesnt-resolve.stderr
deleted file mode 100644 (file)
index 510cedb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find function `foo` in module `macro_crate_test`
-  --> $DIR/macro-crate-doesnt-resolve.rs:7:23
-   |
-LL |     macro_crate_test::foo(); //~ ERROR cannot find function `foo` in module `macro_crate_test`
-   |                       ^^^ not found in `macro_crate_test`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui-fulldeps/macro-crate-unexported-macro.rs b/src/test/ui-fulldeps/macro-crate-unexported-macro.rs
deleted file mode 100644 (file)
index 8cf0cc4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// aux-build:macro_crate_test.rs
-
-#[macro_use] #[no_link]
-extern crate macro_crate_test;
-
-fn main() {
-    unexported_macro!();
-    //~^ ERROR cannot find macro `unexported_macro!` in this scope
-}
diff --git a/src/test/ui-fulldeps/macro-crate-unexported-macro.stderr b/src/test/ui-fulldeps/macro-crate-unexported-macro.stderr
deleted file mode 100644 (file)
index 0d1b4b6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: cannot find macro `unexported_macro!` in this scope
-  --> $DIR/macro-crate-unexported-macro.rs:7:5
-   |
-LL |     unexported_macro!();
-   |     ^^^^^^^^^^^^^^^^ help: you could try the macro: `exported_macro`
-
-error: aborting due to previous error
-
index f192694dc731872bc782cc18af14e8fcffad72eb..37ac8dfa391013a67a6544d23ac1029a38aec4d8 100644 (file)
@@ -1,12 +1,12 @@
-// aux-build:macro_crate_test.rs
+// aux-build:attr_plugin_test.rs
 // ignore-cross-compile
 //
-// macro_crate_test will not compile on a cross-compiled target because
+// attr_plugin_test will not compile on a cross-compiled target because
 // libsyntax is not compiled for it.
 
 #![deny(plugin_as_library)]
 #![allow(unused_extern_crates)]
 
-extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
+extern crate attr_plugin_test; //~ ERROR compiler plugin used as an ordinary library
 
 fn main() { }
index f0406d5181aa179b6958e318c7ce522451fed910..4a5a53980eb8a00a1c02419ec2a4f1e02893dc45 100644 (file)
@@ -1,7 +1,7 @@
 error: compiler plugin used as an ordinary library
   --> $DIR/plugin-as-extern-crate.rs:10:1
    |
-LL | extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
+LL | extern crate attr_plugin_test; //~ ERROR compiler plugin used as an ordinary library
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
diff --git a/src/test/ui-fulldeps/plugin-plus-extern-crate.rs b/src/test/ui-fulldeps/plugin-plus-extern-crate.rs
deleted file mode 100644 (file)
index db13954..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-// ignore-cross-compile
-//
-// macro_crate_test will not compile on a cross-compiled target because
-// libsyntax is not compiled for it.
-
-#![deny(plugin_as_library)]
-#![feature(plugin)]
-#![plugin(macro_crate_test)]
-
-extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
-
-fn main() {
-    assert_eq!(1, make_a_1!());
-    macro_crate_test::foo();
-}
diff --git a/src/test/ui-fulldeps/plugin-plus-extern-crate.stderr b/src/test/ui-fulldeps/plugin-plus-extern-crate.stderr
deleted file mode 100644 (file)
index 284d76b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: compiler plugin used as an ordinary library
-  --> $DIR/plugin-plus-extern-crate.rs:12:1
-   |
-LL | extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: lint level defined here
-  --> $DIR/plugin-plus-extern-crate.rs:8:9
-   |
-LL | #![deny(plugin_as_library)]
-   |         ^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui-fulldeps/qquote.rs b/src/test/ui-fulldeps/qquote.rs
deleted file mode 100644 (file)
index 99e365d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// ignore-cross-compile
-
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-extern crate syntax_pos;
-
-use syntax::ast;
-use syntax::source_map::FilePathMapping;
-use syntax::print::pprust;
-use syntax::symbol::Symbol;
-use syntax_pos::DUMMY_SP;
-
-fn main() {
-    let ps = syntax::parse::ParseSess::new(FilePathMapping::empty());
-    let mut resolver = syntax::ext::base::DummyResolver;
-    let mut cx = syntax::ext::base::ExtCtxt::new(
-        &ps,
-        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()),
-        &mut resolver);
-    let cx = &mut cx;
-
-    assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");
-
-    let expr = quote_expr!(&cx, 2 - $abcd + 7); //~ ERROR cannot find value `abcd` in this scope
-    assert_eq!(pprust::expr_to_string(&*expr), "2 - $abcd + 7");
-}
diff --git a/src/test/ui-fulldeps/qquote.stderr b/src/test/ui-fulldeps/qquote.stderr
deleted file mode 100644 (file)
index a51318b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `abcd` in this scope
-  --> $DIR/qquote.rs:25:38
-   |
-LL |     let expr = quote_expr!(&cx, 2 - $abcd + 7); //~ ERROR cannot find value `abcd` in this scope
-   |                                      ^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
index ab57fec0e73378a1a2b091c0caac9449228c9cbe..356e24d18a78fad3609c348cd9d3da5bf2744eda 100644 (file)
@@ -2,12 +2,11 @@ error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut(); //~ ERROR no method named `test_mut` found
-   |       ^^^^^^^^
+   |       ^^^^^^^^ help: did you mean: `get_mut`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
            candidate #1: `MyIter`
-   = help: did you mean `get_mut`?
 
 error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
diff --git a/src/test/ui/binop/binop-consume-args.nll.stderr b/src/test/ui/binop/binop-consume-args.nll.stderr
new file mode 100644 (file)
index 0000000..59b5aba
--- /dev/null
@@ -0,0 +1,253 @@
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:7:10
+   |
+LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs + rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:8:10
+   |
+LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs + rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:13:10
+   |
+LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs - rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:14:10
+   |
+LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs - rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:19:10
+   |
+LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs * rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:20:10
+   |
+LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs * rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:25:10
+   |
+LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs / rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:26:10
+   |
+LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs / rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:31:10
+   |
+LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs % rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:32:10
+   |
+LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs % rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:37:10
+   |
+LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+   |           -                           --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |           |
+   |           consider adding a `Copy` constraint to this type argument
+LL |     lhs & rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:38:10
+   |
+LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                    -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                                    |
+   |                                    consider adding a `Copy` constraint to this type argument
+LL |     lhs & rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:43:10
+   |
+LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |          -                          --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |          |
+   |          consider adding a `Copy` constraint to this type argument
+LL |     lhs | rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:44:10
+   |
+LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                  -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                                  |
+   |                                  consider adding a `Copy` constraint to this type argument
+LL |     lhs | rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:49:10
+   |
+LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+   |           -                           --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |           |
+   |           consider adding a `Copy` constraint to this type argument
+LL |     lhs ^ rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:50:10
+   |
+LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                    -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                                    |
+   |                                    consider adding a `Copy` constraint to this type argument
+LL |     lhs ^ rhs;
+   |           --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:55:10
+   |
+LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs << rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:56:10
+   |
+LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs << rhs;
+   |            --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:61:10
+   |
+LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs >> rhs;
+   |     --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:62:10
+   |
+LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs >> rhs;
+   |            --- value moved here
+LL |     drop(lhs);  //~ ERROR use of moved value: `lhs`
+LL |     drop(rhs);  //~ ERROR use of moved value: `rhs`
+   |          ^^^ value used here after move
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
index 950772dc75c9ed46bdf6f0ea0b593076d87d5ca5..7c84e8833a9e6dfb860094e54cb2887762721c6d 100644 (file)
@@ -1,24 +1,28 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/binop-move-semantics.rs:8:5
    |
+LL | fn double_move<T: Add<Output=()>>(x: T) {
+   |                -                  - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                |
+   |                consider adding a `Copy` constraint to this type argument
 LL |     x
    |     - value moved here
 LL |     +
 LL |     x;  //~ ERROR: use of moved value
    |     ^ value used here after move
-   |
-   = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/binop-move-semantics.rs:14:5
    |
+LL | fn move_then_borrow<T: Add<Output=()> + Clone>(x: T) {
+   |                     -                          - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                     |
+   |                     consider adding a `Copy` constraint to this type argument
 LL |     x
    |     - value moved here
 LL |     +
 LL |     x.clone();  //~ ERROR: use of moved value
    |     ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait
 
 error[E0505]: cannot move out of `x` because it is borrowed
   --> $DIR/binop-move-semantics.rs:21:5
index 7f386630de590ee031d8b29af55d4c6b3c28bab9..a6346a5233f4c3d12877c10fbdfb39bf25093546 100644 (file)
@@ -2,9 +2,7 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
-   |                 ^
-   |
-   = help: did you mean `a`?
+   |                 ^ help: did you mean: `a`
 
 error: aborting due to previous error
 
index 9c47845a528309cbc35ff31de62986be5eabe62e..86e4832b3873ce49ae1bc09a2247e1b3e5af6fde 100644 (file)
@@ -1,13 +1,14 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-asm.rs:27:17
    |
+LL |         let x = &mut 0isize;
+   |             - move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
+LL |         unsafe {
 LL |             asm!("nop" : : "r"(x));
    |                                - value moved here
 LL |         }
 LL |         let z = x;  //[ast]~ ERROR use of moved value: `x`
    |                 ^ value used here after move
-   |
-   = note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
 
 error[E0503]: cannot use `x` because it was mutably borrowed
   --> $DIR/borrowck-asm.rs:35:32
@@ -66,12 +67,13 @@ LL |         let z = y;
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-asm.rs:86:40
    |
+LL |         let x = &mut 2;
+   |             - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
+LL |         unsafe {
 LL |             asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
    |                                -       ^ value used here after move
    |                                |
    |                                value moved here
-   |
-   = note: move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
 
 error: aborting due to 7 previous errors
 
index 9c47845a528309cbc35ff31de62986be5eabe62e..86e4832b3873ce49ae1bc09a2247e1b3e5af6fde 100644 (file)
@@ -1,13 +1,14 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-asm.rs:27:17
    |
+LL |         let x = &mut 0isize;
+   |             - move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
+LL |         unsafe {
 LL |             asm!("nop" : : "r"(x));
    |                                - value moved here
 LL |         }
 LL |         let z = x;  //[ast]~ ERROR use of moved value: `x`
    |                 ^ value used here after move
-   |
-   = note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
 
 error[E0503]: cannot use `x` because it was mutably borrowed
   --> $DIR/borrowck-asm.rs:35:32
@@ -66,12 +67,13 @@ LL |         let z = y;
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-asm.rs:86:40
    |
+LL |         let x = &mut 2;
+   |             - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
+LL |         unsafe {
 LL |             asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
    |                                -       ^ value used here after move
    |                                |
    |                                value moved here
-   |
-   = note: move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr b/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr
new file mode 100644 (file)
index 0000000..ea7683a
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `b`
+  --> $DIR/borrowck-consume-unsize-vec.rs:8:13
+   |
+LL | fn foo(b: Box<[i32;5]>) {
+   |        - move occurs because `b` has type `std::boxed::Box<[i32; 5]>`, which does not implement the `Copy` trait
+LL |     consume(b);
+   |             - value moved here
+LL |     consume(b); //~ ERROR use of moved value
+   |             ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index 7357d0973dbc0d9bc734713d2fcaf358d0442254..15cf359326be96aea02e028e6ea26ba6a6d351c2 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `b`
   --> $DIR/borrowck-consume-upcast-box.rs:10:13
    |
+LL | fn foo(b: Box<Foo+Send>) {
+   |        - move occurs because `b` has type `std::boxed::Box<dyn Foo + std::marker::Send>`, which does not implement the `Copy` trait
 LL |     consume(b);
    |             - value moved here
 LL |     consume(b); //~ ERROR use of moved value
    |             ^ value used here after move
-   |
-   = note: move occurs because `b` has type `std::boxed::Box<dyn Foo + std::marker::Send>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index d395b7734f9b794221c5fb681f28e5fc517f61d1..07b597f480feba33d7c40c018b55c80a6b18de8f 100644 (file)
@@ -1,13 +1,14 @@
 error[E0382]: use of moved value: `my_str`
   --> $DIR/borrowck-drop-from-guard.rs:11:23
    |
+LL |     let my_str = "hello".to_owned();
+   |         ------ move occurs because `my_str` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     match Some(42) {
 LL |         Some(_) if { drop(my_str); false } => {}
    |                           ------ value moved here
 LL |         Some(_) => {}
 LL |         None => { foo(my_str); } //~ ERROR [E0382]
    |                       ^^^^^^ value used here after move
-   |
-   = note: move occurs because `my_str` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 9d53d82265ecaf95af6bdf8c948837e9dc9fa135..de4894d5b526b8e5baf7c6400836cbe765e3e502 100644 (file)
@@ -1,22 +1,22 @@
 error[E0382]: use of moved value: `src`
   --> $DIR/borrowck-issue-48962.rs:16:5
    |
+LL |     let mut src = &mut node;
+   |         ------- move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait
 LL |     {src};
    |      --- value moved here
 LL |     src.next = None; //~ ERROR use of moved value: `src` [E0382]
    |     ^^^^^^^^ value used here after move
-   |
-   = note: move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `src`
   --> $DIR/borrowck-issue-48962.rs:22:5
    |
+LL |     let mut src = &mut (22, 44);
+   |         ------- move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait
 LL |     {src};
    |      --- value moved here
 LL |     src.0 = 66; //~ ERROR use of moved value: `src` [E0382]
    |     ^^^^^^^^^^ value used here after move
-   |
-   = note: move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index 72d2d1fe59f66f4285649915797e16daf4053609..095ae7f56b22e5643219552e332d6538596c2a4c 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/borrowck-loan-in-overloaded-op.rs:21:20
    |
+LL |     let x = Foo(box 3);
+   |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
 LL |     let _y = {x} + x.clone(); // the `{x}` forces a move to occur
    |               -    ^ value borrowed here after move
    |               |
    |               value moved here
-   |
-   = note: move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 24b9b4338a58ca2877e47525322c053c79ca5634..0789926563ce7fe6fdfcd07de377a7d2435cc185 100644 (file)
@@ -1,6 +1,9 @@
 error[E0382]: use of moved value: `t`
   --> $DIR/borrowck-move-moved-value-into-closure.rs:14:12
    |
+LL |     let t: Box<_> = box 3;
+   |         - move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL | 
 LL |     call_f(move|| { *t + 1 });
    |            ------    - variable moved due to use in closure
    |            |
@@ -9,8 +12,6 @@ LL |     call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
    |            ^^^^^^    - use occurs due to use in closure
    |            |
    |            value used here after move
-   |
-   = note: move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 24b9b4338a58ca2877e47525322c053c79ca5634..0789926563ce7fe6fdfcd07de377a7d2435cc185 100644 (file)
@@ -1,6 +1,9 @@
 error[E0382]: use of moved value: `t`
   --> $DIR/borrowck-move-moved-value-into-closure.rs:14:12
    |
+LL |     let t: Box<_> = box 3;
+   |         - move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL | 
 LL |     call_f(move|| { *t + 1 });
    |            ------    - variable moved due to use in closure
    |            |
@@ -9,8 +12,6 @@ LL |     call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
    |            ^^^^^^    - use occurs due to use in closure
    |            |
    |            value used here after move
-   |
-   = note: move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 6f4cad2a01e48201a80c26966320b5f15feac58d..d0065a2e7dc3d817ee80f60761804a3b0403a91f 100644 (file)
@@ -29,6 +29,8 @@ LL |     borrow(&*p2);
 error[E0382]: use of moved value: `x1`
   --> $DIR/borrowck-multiple-captures.rs:25:19
    |
+LL |     let x1: Box<_> = box 1;
+   |         -- move occurs because `x1` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 LL |     drop(x1);
    |          -- value moved here
 ...
@@ -36,12 +38,12 @@ LL |     thread::spawn(move|| {
    |                   ^^^^^^ value used here after move
 LL |         drop(x1); //~ ERROR capture of moved value: `x1`
    |              -- use occurs due to use in closure
-   |
-   = note: move occurs because `x1` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `x2`
   --> $DIR/borrowck-multiple-captures.rs:25:19
    |
+LL |     let x2: Box<_> = box 2;
+   |         -- move occurs because `x2` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 LL |     drop(x2);
    |          -- value moved here
 LL |     thread::spawn(move|| {
@@ -49,8 +51,6 @@ LL |     thread::spawn(move|| {
 LL |         drop(x1); //~ ERROR capture of moved value: `x1`
 LL |         drop(x2); //~ ERROR capture of moved value: `x2`
    |              -- use occurs due to use in closure
-   |
-   = note: move occurs because `x2` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-multiple-captures.rs:36:14
@@ -88,14 +88,14 @@ LL |         drop(x); //~ ERROR use of moved value: `x`
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-multiple-captures.rs:44:19
    |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 LL |     drop(x);
    |          - value moved here
 LL |     thread::spawn(move|| {
    |                   ^^^^^^ value used here after move
 LL |         drop(x); //~ ERROR capture of moved value: `x`
    |              - use occurs due to use in closure
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to 8 previous errors
 
index 1b4a6610ab1a4e64fc28445366084334834e85aa..c5a4c4e005aa7d8177ee6e85b37b13ddd5766758 100644 (file)
@@ -20,12 +20,13 @@ LL |     s(3);   //~ ERROR cannot borrow immutable local variable `s` as mutable
 error[E0382]: use of moved value: `s`
   --> $DIR/borrowck-overloaded-call.rs:75:5
    |
+LL |     let s = SFnOnce {
+   |         - move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait
+...
 LL |     s(" world".to_string());
    |     - value moved here
 LL |     s(" world".to_string());    //~ ERROR use of moved value: `s`
    |     ^ value used here after move
-   |
-   = note: move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait
 
 error: aborting due to 3 previous errors
 
index a19baa167de91a97eed406d886c57f66f038d8a1..de60067f1a613702080d4b60dccd47cbad3177bf 100644 (file)
@@ -25,13 +25,14 @@ LL |     use_mut(rs);
 error[E0382]: use of moved value: `s`
   --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
    |
+LL |     let mut s = "hello".to_string();
+   |         ----- move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |     println!("{}", f[s]);
    |                      - value moved here
 ...
 LL |     f[s] = 10;
    |       ^ value used here after move
-   |
-   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to 3 previous errors
 
index 09a85bd7c13a9124cdd5159180c61a86b8cdfb40..65f2bd6cfbda9c1b113e6f511051aa3f7f2dd0f0 100644 (file)
@@ -1,22 +1,24 @@
 error[E0382]: assign of moved value: `t`
   --> $DIR/borrowck-partial-reinit-1.rs:27:5
    |
+LL |     let mut t = Test2 { b: None };
+   |         ----- move occurs because `t` has type `Test2`, which does not implement the `Copy` trait
+LL |     let u = Test;
 LL |     drop(t);
    |          - value moved here
 LL |     t.b = Some(u);
    |     ^^^ value assigned here after move
-   |
-   = note: move occurs because `t` has type `Test2`, which does not implement the `Copy` trait
 
 error[E0382]: assign of moved value: `t`
   --> $DIR/borrowck-partial-reinit-1.rs:33:5
    |
+LL |     let mut t = Test3(None);
+   |         ----- move occurs because `t` has type `Test3`, which does not implement the `Copy` trait
+LL |     let u = Test;
 LL |     drop(t);
    |          - value moved here
 LL |     t.0 = Some(u);
    |     ^^^ value assigned here after move
-   |
-   = note: move occurs because `t` has type `Test3`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index 03608a1b99d2427fb2caa21b79657085c6d126fc..36a871fbb12a18d2bc2ef5e59f113be8b3a6bd01 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: assign of moved value: `t`
   --> $DIR/borrowck-partial-reinit-2.rs:15:5
    |
+LL |     let mut t = Test { a: 1, b: None};
+   |         ----- move occurs because `t` has type `Test`, which does not implement the `Copy` trait
 LL |     let mut u = Test { a: 2, b: Some(Box::new(t))};
    |                                               - value moved here
 LL |     t.b = Some(Box::new(u));
    |     ^^^ value assigned here after move
-   |
-   = note: move occurs because `t` has type `Test`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 918452726a06cb1350a7e1cb394b6b068ab4febd..96f3981ac2fe6b0c8eed50b25ebfa8b647df1a84 100644 (file)
@@ -11,12 +11,13 @@ LL |     let _ = (1,x); //~ ERROR use of moved value: `x` (Ast)
 error[E0382]: use of moved value: `x` (Mir)
   --> $DIR/borrowck-reinit.rs:8:16
    |
+LL |     let mut x = Box::new(0);
+   |         ----- move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
 LL |     drop(x);
    |          - value moved here
 LL |     let _ = (1,x); //~ ERROR use of moved value: `x` (Ast)
    |                ^ value used here after move
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index 86baa0db961219d2b6fd0c38043c17123ecbb7ed..363a5a69a07e394db6db4c63cf3706125b45473a 100644 (file)
@@ -19,12 +19,14 @@ LL |     f(1, 2);    //~ ERROR cannot borrow immutable argument
 error[E0382]: use of moved value: `f`
   --> $DIR/borrowck-unboxed-closures.rs:12:5
    |
+LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
+   |      -                                - move occurs because `f` has type `F`, which does not implement the `Copy` trait
+   |      |
+   |      consider adding a `Copy` constraint to this type argument
 LL |     f(1, 2);
    |     - value moved here
 LL |     f(1, 2);    //~ ERROR use of moved value
    |     ^ value used here after move
-   |
-   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
 
 error: aborting due to 3 previous errors
 
index bf0d0a45fcff72cbb367d577e806794193e3f785..e59fef2dc0d2f181305f5869861ac55931ab58b2 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move-assign.rs:17:21
    |
+LL |             let mut u = U { a: A };
+   |                 ----- move occurs because `u` has type `U`, which does not implement the `Copy` trait
 LL |             let a = u.a;
    |                     --- value moved here
 LL |             let a = u.a; //~ ERROR use of moved value: `u.a`
    |                     ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index fd90fc47a218dab51db6859c825ab379b38934b9..1392a7931c30a157bb0e3f5eaa4e384bebd484c2 100644 (file)
@@ -1,62 +1,62 @@
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move.rs:26:21
    |
+LL |             let mut u = Unn { n1: NonCopy };
+   |                 ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
 LL |             let a = u.n1;
    |                     ---- value moved here
 LL |             let a = u.n1; //~ ERROR use of moved value: `u.n1`
    |                     ^^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move.rs:31:21
    |
+LL |             let mut u = Unn { n1: NonCopy };
+   |                 ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
 LL |             let a = u.n1;
    |                     ---- value moved here
 LL |             let a = u; //~ ERROR use of partially moved value: `u`
    |                     ^ value used here after move
-   |
-   = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move.rs:36:21
    |
+LL |             let mut u = Unn { n1: NonCopy };
+   |                 ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
 LL |             let a = u.n1;
    |                     ---- value moved here
 LL |             let a = u.n2; //~ ERROR use of moved value: `u.n2`
    |                     ^^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move.rs:63:21
    |
+LL |             let mut u = Ucn { c: Copy };
+   |                 ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
 LL |             let a = u.n;
    |                     --- value moved here
 LL |             let a = u.n; //~ ERROR use of moved value: `u.n`
    |                     ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move.rs:68:21
    |
+LL |             let mut u = Ucn { c: Copy };
+   |                 ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
 LL |             let a = u.n;
    |                     --- value moved here
 LL |             let a = u.c; //~ ERROR use of moved value: `u.c`
    |                     ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `u`
   --> $DIR/borrowck-union-move.rs:83:21
    |
+LL |             let mut u = Ucn { c: Copy };
+   |                 ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
 LL |             let a = u.n;
    |                     --- value moved here
 LL |             let a = u; //~ ERROR use of partially moved value: `u`
    |                     ^ value used here after move
-   |
-   = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
 
 error: aborting due to 6 previous errors
 
index 7861087ad02ebd9b079e9048c12f72c4c241e6de..42aa03817023813b752a67cc69ba2a93ed5a21a5 100644 (file)
@@ -1,32 +1,32 @@
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:23:9
    |
+LL |         let mut t: Tuple = (S(0), 0);
+   |             ----- move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
 LL |         drop(t);
    |              - value moved here
 LL |         t.0 = S(1);
    |         ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `u`
   --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:34:9
    |
+LL |         let mut u: Tpair = Tpair(S(0), 0);
+   |             ----- move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
 LL |         drop(u);
    |              - value moved here
 LL |         u.0 = S(1);
    |         ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `v`
   --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:45:9
    |
+LL |         let mut v: Spair = Spair { x: S(0), y: 0 };
+   |             ----- move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
 LL |         drop(v);
    |              - value moved here
 LL |         v.x = S(1);
    |         ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
 
 error: aborting due to 3 previous errors
 
index d35d0058027d42ed81a0bd01ebc6a86d41032e12..1184907f307cb8e541568f794858646e61c2aee8 100644 (file)
@@ -10,12 +10,12 @@ LL |         t.0 = S(1);
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
    |
+LL |         let t: Tuple = (S(0), 0);
+   |             - move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
 LL |         drop(t);
    |              - value moved here
 LL |         t.0 = S(1);
    |         ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
 
 error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable
   --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9
@@ -38,12 +38,12 @@ LL |         u.0 = S(1);
 error[E0382]: assign to part of moved value: `u`
   --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
    |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
 LL |         drop(u);
    |              - value moved here
 LL |         u.0 = S(1);
    |         ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
 
 error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable
   --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9
@@ -66,12 +66,12 @@ LL |         v.x = S(1);
 error[E0382]: assign to part of moved value: `v`
   --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
    |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
 LL |         drop(v);
    |              - value moved here
 LL |         v.x = S(1);
    |         ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
 
 error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable
   --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9
index 0e99e158eda027a6fde6c9ffce0b01f02c8bcabf..d026f81b7aad6f2ea7af7620f97c2f02dc0759f2 100644 (file)
@@ -10,6 +10,8 @@ LL |         f(f(10));
 error[E0382]: use of moved value: `*f`
   --> $DIR/two-phase-nonrecv-autoref.rs:69:11
    |
+LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
+   |                     - consider adding a `Copy` constraint to this type argument
 LL |         f(f(10));
    |         - ^ value used here after move
    |         |
index 0e99e158eda027a6fde6c9ffce0b01f02c8bcabf..d026f81b7aad6f2ea7af7620f97c2f02dc0759f2 100644 (file)
@@ -10,6 +10,8 @@ LL |         f(f(10));
 error[E0382]: use of moved value: `*f`
   --> $DIR/two-phase-nonrecv-autoref.rs:69:11
    |
+LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
+   |                     - consider adding a `Copy` constraint to this type argument
 LL |         f(f(10));
    |         - ^ value used here after move
    |         |
index 70b4869ef63cefa3115ee9b1e4207b27743128b8..ac153cb57423fd8f731cd36ac265187d78f91175 100644 (file)
@@ -1,7 +1,11 @@
 // gate-test-const_raw_ptr_to_usize_cast
 
 fn main() {
-    const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
+    const X: u32 = unsafe {
+        main as u32 //~ ERROR casting pointers to integers in constants is unstable
+    };
     const Y: u32 = 0;
-    const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
+    const Z: u32 = unsafe {
+        &Y as *const u32 as u32 //~ ERROR is unstable
+    };
 }
index 3cce07d64ecd0618dbd292d3b9dddaecf8a328ad..d04595ee4e887d98889c757779fbdecf53bbefbc 100644 (file)
@@ -1,16 +1,16 @@
 error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
-  --> $DIR/cast-ptr-to-int-const.rs:4:20
+  --> $DIR/cast-ptr-to-int-const.rs:5:9
    |
-LL |     const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
-   |                    ^^^^^^^^^^^
+LL |         main as u32 //~ ERROR casting pointers to integers in constants is unstable
+   |         ^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
-  --> $DIR/cast-ptr-to-int-const.rs:6:20
+  --> $DIR/cast-ptr-to-int-const.rs:9:9
    |
-LL |     const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^
+LL |         &Y as *const u32 as u32 //~ ERROR is unstable
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
index 55117ff2b187673d37fb793ef25f1f539b7e6c74..3b8507a067ded31725ab9219b7ce445c9417ca9a 100644 (file)
@@ -1,13 +1,13 @@
 error[E0382]: borrow of moved value: `some_vec`
   --> $DIR/tab_3.rs:7:20
    |
+LL |     let some_vec = vec!["hi"];
+   |         -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
 LL |     some_vec.into_iter();
    |     -------- value moved here
 LL |     {
 LL |         println!("{:?}", some_vec); //~ ERROR use of moved
    |                          ^^^^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 63bac17f1c0f380221a0390073684ec0dd27dea2..44266682a5c6c202f84f7d0dd6d61a275d2a72c7 100644 (file)
@@ -3,13 +3,13 @@
 fn main() {}
 
 // unconst and bad, will thus error in miri
-const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause
+const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
 // unconst and fine
-const X2: bool = 42 as *const i32 == 43 as *const i32;
+const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
 // unconst and fine
-const Y: usize = 42usize as *const i32 as usize + 1;
+const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
 // unconst and bad, will thus error in miri
-const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause
+const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
 // unconst and fine
 const Z: i32 = unsafe { *(&1 as *const i32) };
 // unconst and bad, will thus error in miri
index ea11359af85ed6c2b38c51462dd947da10de6a67..6be54c0bad4f9c7858539151fea205a8680fe6dd 100644 (file)
@@ -1,20 +1,20 @@
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:6:1
    |
-LL | const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause
-   | ^^^^^^^^^^^^^^^^------------------------------------^
-   |                 |
-   |                 "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+   |                          |
+   |                          "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
    |
    = note: #[deny(const_err)] on by default
 
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:12:1
    |
-LL | const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause
-   | ^^^^^^^^^^^^^^^^^^-----------------------------^
-   |                   |
-   |                   "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------^^^
+   |                            |
+   |                            "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
 
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:16:1
index 7fbcab8245a0fd615fb43cfe6f3e0c6960db4b70..3e0b0948ef3c3ff4b536809a261fb28bc50d6c72 100644 (file)
 const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+union Transmute {
+    uninit: (),
+    out: NonZeroU8,
+}
+const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+//~^ ERROR it is undefined behavior to use this value
+
 // Also test other uses of rustc_layout_scalar_valid_range_start
 
 #[rustc_layout_scalar_valid_range_start(10)]
index 5f8e0c73fbb2a857058f10613956edc4de52772d..6230712ad6f232497c7123a6acf4d3b378470093 100644 (file)
@@ -23,7 +23,15 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    = 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]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:21:1
+  --> $DIR/ub-nonnull.rs:20:1
+   |
+LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:28:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -31,13 +39,13 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    = 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]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:27:1
+  --> $DIR/ub-nonnull.rs:34:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
    |
    = 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 5 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 8f9498e834d8ff11bcdc6c80727b9e80eda9b566..8f8eb38e938737bb0faa23514ff476a77f4ff57c 100644 (file)
@@ -9,8 +9,8 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}`...
    |
 LL |     intrinsics::size_of::<T>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires computing layout of `Foo`...
-note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
+   = note: ...which requires computing layout of `Foo`...
+   = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
 note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}`...
   --> $DIR/const-size_of-cycle.rs:6:17
    |
diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs
new file mode 100644 (file)
index 0000000..53c5782
--- /dev/null
@@ -0,0 +1,10 @@
+// https://github.com/rust-lang/rust/issues/53708
+
+struct S;
+
+fn main() {
+    const C: &S = &S;
+    match C { //~ ERROR non-exhaustive
+        C => {} // this is a common bug around constants and references in patterns
+    }
+}
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
new file mode 100644 (file)
index 0000000..e6e04e2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0004]: non-exhaustive patterns: `&S` not covered
+  --> $DIR/match_ice.rs:7:11
+   |
+LL |     match C { //~ ERROR non-exhaustive
+   |           ^ pattern `&S` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
index d8abd9765580535c5bd07b2dad7cc2a987888e6e..c2600f894dc42a7c450d72e541036eb274b6b7b6 100644 (file)
@@ -1,5 +1,5 @@
 const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable
-    x == y
+    unsafe { x == y }
 }
 
 fn main() {}
index 91b076097b0183ec730ad482f02e0ab0993e1455..763c69e8050309a045a5dbd60402b3f64ac47190 100644 (file)
@@ -95,97 +95,109 @@ 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:94:42
+  --> $DIR/min_const_fn.rs:94:63
+   |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:96:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
 
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:98:63
+   |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:96:38
+  --> $DIR/min_const_fn.rs:100: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:98:29
+  --> $DIR/min_const_fn.rs:102:29
    |
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:100:44
+  --> $DIR/min_const_fn.rs:104: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:102:44
+  --> $DIR/min_const_fn.rs:106: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:104:14
+  --> $DIR/min_const_fn.rs:108: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:109:6
+  --> $DIR/min_const_fn.rs:113: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:114:6
+  --> $DIR/min_const_fn.rs:118: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:119:6
+  --> $DIR/min_const_fn.rs:123:6
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:125:24
+  --> $DIR/min_const_fn.rs:129: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:127:34
+  --> $DIR/min_const_fn.rs:131: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:129:22
+  --> $DIR/min_const_fn.rs:133: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:130:23
+  --> $DIR/min_const_fn.rs:134: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:131:23
+  --> $DIR/min_const_fn.rs:135: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:132:32
+  --> $DIR/min_const_fn.rs:136:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning[E0515]: cannot return reference to temporary value
-  --> $DIR/min_const_fn.rs:132:63
+  --> $DIR/min_const_fn.rs:136:63
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                                               ^--
@@ -197,24 +209,24 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:137:41
+  --> $DIR/min_const_fn.rs:141: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:140:21
+  --> $DIR/min_const_fn.rs:144:21
    |
 LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:142:27
+  --> $DIR/min_const_fn.rs:146:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 36 previous errors
 
 Some errors occurred: E0493, E0515.
 For more information about an error, try `rustc --explain E0493`.
index 05cf3d5f1f1731aa69eb49a91bc2514d24b9c246..ee3ffcd4026d3b6f5745a9dcf34e357ce37b71b7 100644 (file)
@@ -90,9 +90,13 @@ const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
 const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
 const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
 const fn foo30(x: *const u32) -> usize { x as usize }
-//~^ ERROR casting pointers to int
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
 const fn foo30_2(x: *mut u32) -> usize { x as usize }
-//~^ ERROR casting pointers to int
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
 const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
index 2cae714fbf727cbb25dc889b73bbe208d75a2196..52c60c57b8fb359b4d552e0e6a555f4860aedda9 100644 (file)
@@ -95,113 +95,125 @@ 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:94:42
+  --> $DIR/min_const_fn.rs:94:63
+   |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:96:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
 
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:98:63
+   |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:96:38
+  --> $DIR/min_const_fn.rs:100: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:98:29
+  --> $DIR/min_const_fn.rs:102:29
    |
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:100:44
+  --> $DIR/min_const_fn.rs:104: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:102:44
+  --> $DIR/min_const_fn.rs:106: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:104:14
+  --> $DIR/min_const_fn.rs:108: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:109:6
+  --> $DIR/min_const_fn.rs:113: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:114:6
+  --> $DIR/min_const_fn.rs:118: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:119:6
+  --> $DIR/min_const_fn.rs:123:6
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:125:24
+  --> $DIR/min_const_fn.rs:129: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:127:34
+  --> $DIR/min_const_fn.rs:131: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:129:22
+  --> $DIR/min_const_fn.rs:133: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:130:23
+  --> $DIR/min_const_fn.rs:134: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:131:23
+  --> $DIR/min_const_fn.rs:135: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:132:32
+  --> $DIR/min_const_fn.rs:136: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:137:41
+  --> $DIR/min_const_fn.rs:141: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:140:21
+  --> $DIR/min_const_fn.rs:144:21
    |
 LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:142:27
+  --> $DIR/min_const_fn.rs:146:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 36 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
index 140f98b40382ac250a1c96dacc38fbbd587eec80..d6d5ce4d1a7d2b34c5249323e91e2d9123fd338a 100644 (file)
@@ -8,7 +8,7 @@ LL |     f1.foo(1usize);
              <Bar as Foo<i16>>
              <Bar as Foo<i32>>
              <Bar as Foo<i8>>
-             <Bar as Foo<u8>>
+             <Bar as Foo<u16>>
            and 2 others
 
 error: aborting due to previous error
index 23466980f92525b19e9409aa4694fa2e3ea710f4..3411958be62a93b46600719561ba42521d5678f3 100644 (file)
@@ -40,10 +40,10 @@ LL |     Foo::<i32>::bar(&true); //~ ERROR is not satisfied
    |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool`
    |
    = help: the following implementations were found:
+             <bool as Foo<bool>>
+             <bool as Foo<i8>>
              <bool as Foo<u16>>
              <bool as Foo<u32>>
-             <bool as Foo<u64>>
-             <bool as Foo<u8>>
            and 2 others
 note: required by `Foo::bar`
   --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
index d94e4dc5b6e79af5a65c17f9be9d4623391df6f1..c2ae321aa5e504f09980313c3ac3a1f02646030f 100644 (file)
@@ -25,7 +25,7 @@ LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
    |
    = note: conflicting implementation in crate `core`:
            - impl<T, U> std::convert::TryFrom<U> for T
-             where T: std::convert::From<U>;
+             where U: std::convert::Into<T>;
 
 error: aborting due to 3 previous errors
 
index e595e0ccb9293278179763a34f3dd21d214eda52..19844503a48048e345967c0dbbe10cc27498e904 100644 (file)
@@ -51,20 +51,18 @@ error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the
    |
 LL |     let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type
    |               ----^^^^^^
-   |               |
+   |               |   |
+   |               |   help: did you mean: `XEmpty3`
    |               variant not found in `empty_struct::XE`
-   |
-   = help: did you mean `XEmpty3`?
 
 error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:23:19
    |
 LL |     let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type
    |               ----^^^^^^
-   |               |
+   |               |   |
+   |               |   help: did you mean: `XEmpty3`
    |               variant not found in `empty_struct::XE`
-   |
-   = help: did you mean `XEmpty3`?
 
 error: aborting due to 8 previous errors
 
index 08a98b1c3bf3def31cf86e50a32aa7b02939e5e3..a10f2c00578c63d41af185fa0f96868b8f3d104f 100644 (file)
@@ -1,8 +1,11 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/E0214.rs:2:15
    |
 LL |     let v: Vec(&str) = vec!["foo"];
-   |               ^^^^^^ only traits may use parentheses
+   |               ^^^^^^
+   |               |
+   |               only `Fn` traits may use parentheses
+   |               help: use angle brackets instead: `<&str>`
 
 error: aborting due to previous error
 
index c2de56c413f05d441ba5f4dc380b705097a1c888..9657bbdeadc17a367c274fbf73c53cc349b50707 100644 (file)
@@ -3,6 +3,6 @@
 static FOO: i32 = 42;
 static BAR: i32 = 42;
 
-static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
 fn main() {
 }
index 45e1ba05ff9965bf907d7d8da222763f076b14ff..cc7d94e22eb6b8e5056fbde0d08a361daec684d5 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: comparing raw pointers inside static (see issue #53020)
-  --> $DIR/E0395.rs:6:22
+  --> $DIR/E0395.rs:6:29
    |
-LL | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
 
diff --git a/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs b/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
new file mode 100644 (file)
index 0000000..af2d209
--- /dev/null
@@ -0,0 +1,12 @@
+// Crate that exports an existential type. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+
+#![feature(existential_type)]
+
+pub existential type Foo: std::fmt::Debug;
+
+pub fn foo() -> Foo {
+    5
+}
+
diff --git a/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs b/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
new file mode 100644 (file)
index 0000000..39ec539
--- /dev/null
@@ -0,0 +1,21 @@
+// Crate that exports an existential type. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+
+#![feature(existential_type)]
+
+pub trait View {
+    type Tmp: Iterator<Item = u32>;
+
+    fn test(&self) -> Self::Tmp;
+}
+
+pub struct X;
+
+impl View for X {
+    existential type Tmp: Iterator<Item = u32>;
+
+    fn test(&self) -> Self::Tmp {
+        vec![1,2,3].into_iter()
+    }
+}
diff --git a/src/test/ui/existential_types/cross_crate_ice.rs b/src/test/ui/existential_types/cross_crate_ice.rs
new file mode 100644 (file)
index 0000000..c5d5ca9
--- /dev/null
@@ -0,0 +1,16 @@
+// aux-build:cross_crate_ice.rs
+// compile-pass
+
+extern crate cross_crate_ice;
+
+struct Bar(cross_crate_ice::Foo);
+
+impl Bar {
+    fn zero(&self) -> &cross_crate_ice::Foo {
+        &self.0
+    }
+}
+
+fn main() {
+    let _ = cross_crate_ice::foo();
+}
diff --git a/src/test/ui/existential_types/cross_crate_ice2.rs b/src/test/ui/existential_types/cross_crate_ice2.rs
new file mode 100644 (file)
index 0000000..a0f3933
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:cross_crate_ice2.rs
+// compile-pass
+
+extern crate cross_crate_ice2;
+
+use cross_crate_ice2::View;
+
+fn main() {
+    let v = cross_crate_ice2::X;
+    v.test();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
new file mode 100644 (file)
index 0000000..078ecc5
--- /dev/null
@@ -0,0 +1,13 @@
+fn main() {
+    // Assert `Iterator` methods are feature gated
+    assert!([1, 2, 2, 9].iter().is_sorted());
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+    assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+
+    // Assert `[T]` methods are feature gated
+    assert!([1, 2, 2, 9].is_sorted());
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+    assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+}
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.stderr b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
new file mode 100644 (file)
index 0000000..8230c1e
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:3:33
+   |
+LL |     assert!([1, 2, 2, 9].iter().is_sorted());
+   |                                 ^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:5:39
+   |
+LL |     assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+   |                                       ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:9:26
+   |
+LL |     assert!([1, 2, 2, 9].is_sorted());
+   |                          ^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:11:32
+   |
+LL |     assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+   |                                ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 9a33d29766fb967e339bcfb369b19880e371f3fc..47bb5e475b473e5ee4ff2886e04fcb6dbc39bb74 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/fully-qualified-type-name2.rs:12:12
    |
+LL | fn bar(x: x::Foo) -> y::Foo {
+   |                      ------ expected `y::Foo` because of return type
 LL |     return x;
    |            ^ expected enum `y::Foo`, found enum `x::Foo`
    |
index f03aaa67edbb8812bc0b5543ce26f57ee741e5c9..b341879ab919afaf78070b8058ad81f129da47a8 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/fully-qualified-type-name4.rs:6:12
    |
+LL | fn bar(x: usize) -> Option<usize> {
+   |                     ------------- expected `std::option::Option<usize>` because of return type
 LL |     return x;
    |            ^ expected enum `std::option::Option`, found usize
    |
index 4acc400f8e79982f9d710d1457f842fcc7a33ea2..b936fed85f48efbf8753a567c214f94943fd06b9 100644 (file)
@@ -9,7 +9,7 @@ note: ...which requires processing `cycle1`...
    |
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:23:16
    |
@@ -20,7 +20,7 @@ note: ...which requires processing `cycle2`...
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
    = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:3:1
@@ -45,7 +45,7 @@ note: ...which requires processing `cycle1`...
    |
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:23:16
    |
index 57bd70de7c68f5137fd335e7f1ceea3cd9218e4c..6cd9d07748c27043ddd019388e3b08cd98373007 100644 (file)
@@ -1,8 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
+LL | fn two(x: bool) -> impl Foo {
+   |                    -------- expected because this return type...
+LL |     if x {
 LL |         return 1_i32;
-   |                ----- expected because of this statement
+   |                ----- ...is found to be `i32` here
 LL |     }
 LL |     0_u32
    |     ^^^^^ expected i32, found u32
index c8b23d812e1b53bfc7c4845a46346c0ad319bc6e..4c585a958c14bcd0955d6cdda49e01993dba70a5 100644 (file)
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[{integer}]>` is not satisfied
+error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
   --> $DIR/index-help.rs:3:5
    |
 LL |     x[0i32]; //~ ERROR E0277
index 2db3c58ec519f71fe5e7ec76932a3557168bff2d..dbe9b44a13890b8b09289cd91d385f7ea97f3c44 100644 (file)
@@ -3,7 +3,7 @@
 
 fn main() {
     fn bar<T>(_: T) {}
-    [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+    [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
 
     [0][0]; // should infer to be a usize
 
index 767f1af2c46e92936c16317157e1003996c2e3ec..363c3d0d45853e7fea18fdbb8bf96339702b2239 100644 (file)
@@ -1,7 +1,7 @@
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+error[E0277]: the type `[{integer}]` cannot be indexed by `u8`
   --> $DIR/indexing-requires-a-uint.rs:6:5
    |
-LL |     [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+LL |     [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
    |     ^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `u8`
index 7bdbc45879b9d45d27468820514c7a096a815d91..f076dfcb0a42c039febb89f54ab94a26c596f9c9 100644 (file)
@@ -3,14 +3,14 @@ pub fn main() {
     let s: String = "abcdef".to_string();
     v[3_usize];
     v[3];
-    v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+    v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
+    v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
+    v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
+    v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
     s.as_bytes()[3_usize];
     s.as_bytes()[3];
-    s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3i8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+    s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
+    s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
+    s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
+    s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
 }
index 7f2dddcf7b8c3dee319dd568be0881f0bb35aabf..efbad86c4d31b3126546cba841a2e98afcaca9f0 100644 (file)
@@ -1,70 +1,70 @@
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:6:5
    |
-LL |     v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
    |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u8`
    = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `i8: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:7:5
    |
-LL |     v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
    |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i8`
    = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `u32: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:8:5
    |
-LL |     v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
    |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u32`
    = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:9:5
    |
-LL |     v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
    |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i32`
    = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:12:5
    |
-LL |     s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
    |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u8`
    = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `[u8]`
 
-error[E0277]: the trait bound `i8: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:13:5
    |
-LL |     s.as_bytes()[3i8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
    |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i8`
    = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `[u8]`
 
-error[E0277]: the trait bound `u32: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:14:5
    |
-LL |     s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
    |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u32`
    = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `[u8]`
 
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:15:5
    |
-LL |     s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
    |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i32`
diff --git a/src/test/ui/issues/auxiliary/issue-56943.rs b/src/test/ui/issues/auxiliary/issue-56943.rs
new file mode 100644 (file)
index 0000000..65b9beb
--- /dev/null
@@ -0,0 +1,3 @@
+pub struct S;
+mod m { pub struct S; }
+pub use crate::m::S as S2;
index 24080a3b387f2506248e5844dee20a65619e369d..20198f19dd5f54286075b5d9d4631ef28fbe6313 100644 (file)
@@ -1,23 +1,23 @@
 error[E0382]: use of moved value: `foo`
   --> $DIR/issue-17385.rs:19:11
    |
+LL |     let foo = X(1);
+   |         --- move occurs because `foo` has type `X`, which does not implement the `Copy` trait
 LL |     drop(foo);
    |          --- value moved here
 LL |     match foo { //~ ERROR use of moved value
 LL |         X(1) => (),
    |           ^ value used here after move
-   |
-   = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `e`
   --> $DIR/issue-17385.rs:25:11
    |
+LL |     let e = Enum::Variant2;
+   |         - move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
 LL |     drop(e);
    |          - value moved here
 LL |     match e { //~ ERROR use of moved value
    |           ^ value used here after move
-   |
-   = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index d7a1752b96c44a38fc84e40141f8941afa2f0220..444e94d829bf8c0f76d08109a2b0138fd2d891bd 100644 (file)
@@ -1,4 +1,4 @@
-static X: usize = 0 as *const usize as usize;
+static X: usize = unsafe { 0 as *const usize as usize };
 //~^ ERROR: casting pointers to integers in statics is unstable
 
 fn main() {
index 04921419ae01a0223f41818b47ed69fb1b46e04d..a1a8ed9f0cdcb6cc943b5bdf3231cfd633ad7016 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: casting pointers to integers in statics is unstable (see issue #51910)
-  --> $DIR/issue-17458.rs:1:19
+  --> $DIR/issue-17458.rs:1:28
    |
-LL | static X: usize = 0 as *const usize as usize;
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static X: usize = unsafe { 0 as *const usize as usize };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
index df4fd1642f2bc47454b3ab3aaf2c17019255f330..1c2229fb9eae4f9258ff8505ba305130a2138ba5 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
     const X: u32 = 1;
-    const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
     println!("{}", Y);
 }
index 2af7f45628e37110da3e7969587373469929686b..f3e8ab1a31307cfbaf425ee6601d161c62b93d62 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
-  --> $DIR/issue-18294.rs:3:22
+  --> $DIR/issue-18294.rs:3:31
    |
-LL |     const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
index 208d0cc499a80024011d2467439b515ac5f6e582..9cad002036fff4cc8b6f9fc1de814fab0e0b6df2 100644 (file)
@@ -5,10 +5,9 @@ LL | pub enum SomeEnum {
    | ----------------- variant `A` not found here
 LL |     B = SomeEnum::A,
    |         ----------^
-   |         |
+   |         |         |
+   |         |         help: did you mean: `B`
    |         variant not found in `SomeEnum`
-   |
-   = help: did you mean `B`?
 
 error: aborting due to previous error
 
index a59710a1a3cdeb3db06ba7a3354280e413b7c208..1c640af8d02b9311b8dae6a75025853a8fda3194 100644 (file)
@@ -1,4 +1,5 @@
 fn main() {
     let v: Vec(&str) = vec!['1', '2'];
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| ERROR mismatched types
 }
index e6e07c167f349c5c06a621447c7d3eb8c5c7cff7..bc2007ba39cc632965b4128485a5f194ecbac66f 100644 (file)
@@ -1,9 +1,22 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-23589.rs:2:15
    |
 LL |     let v: Vec(&str) = vec!['1', '2'];
-   |               ^^^^^^ only traits may use parentheses
+   |               ^^^^^^
+   |               |
+   |               only `Fn` traits may use parentheses
+   |               help: use angle brackets instead: `<&str>`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-23589.rs:2:29
+   |
+LL |     let v: Vec(&str) = vec!['1', '2'];
+   |                             ^^^ expected &str, found char
+   |
+   = note: expected type `&str`
+              found type `char`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0214`.
+Some errors occurred: E0214, E0308.
+For more information about an error, try `rustc --explain E0214`.
index 06de9537af031b6f4eaf49764ea6245e37f1f87d..310535434cd0807185a8e358cf98d7653b8fcba8 100644 (file)
@@ -1,6 +1,8 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/issue-24357.rs:6:12
    |
+LL |    let x = NoCopy;
+   |        - move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait
 LL |    let f = move || { let y = x; };
    |            -------           - variable moved due to use in closure
    |            |
@@ -8,8 +10,6 @@ LL |    let f = move || { let y = x; };
 LL |    //~^ NOTE value moved (into closure) here
 LL |    let z = x;
    |            ^ value used here after move
-   |
-   = note: move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-25700.nll.stderr b/src/test/ui/issues/issue-25700.nll.stderr
new file mode 100644 (file)
index 0000000..ba5403c
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/issue-25700.rs:13:10
+   |
+LL |     let t = S::<()>(None);
+   |         - move occurs because `t` has type `S<()>`, which does not implement the `Copy` trait
+LL |     drop(t);
+   |          - value moved here
+LL |     drop(t); //~ ERROR use of moved value
+   |          ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index e6022653d9c3b2ae81e15ced1dabe531132daa18..36a69cf4c22ff9895bc476983be8d0be4c29e592 100644 (file)
@@ -1,6 +1,6 @@
 fn id<T>(t: T) -> T { t }
 fn main() {
-    const A: bool = id::<u8> as *const () < id::<u16> as *const ();
+    const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
     //~^ ERROR comparing raw pointers inside constant
     println!("{}", A);
 }
index 73ebf29d08e785aa278c09b70d43925cbf825187..dc547f7c32c941fd2e512b2c721a148acccf0b56 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: comparing raw pointers inside constant (see issue #53020)
-  --> $DIR/issue-25826.rs:3:21
+  --> $DIR/issue-25826.rs:3:30
    |
-LL |     const A: bool = id::<u8> as *const () < id::<u16> as *const ();
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
 
index 84604f31d1e7f6c380aad5726ee9ff3f562cf699..ff197eeeb0fe92429eba624a897ac1db2afe53b0 100644 (file)
@@ -1,6 +1,6 @@
 error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
    |
-note: ...which requires computing layout of `S`...
+   = note: ...which requires computing layout of `S`...
    = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
 note: cycle used when processing `main`
   --> $DIR/issue-26548.rs:9:1
index 8ea2bdb693d31499883050b254bd98d0ace2e2cd..6993419326c8e259323af3375cad48dba34e786c 100644 (file)
@@ -1,6 +1,9 @@
 error[E0382]: use of moved value: `b`
   --> $DIR/issue-27282-move-match-input-into-guard.rs:18:14
    |
+LL |     let b = &mut true;
+   |         - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
+...
 LL |         _ if { (|| { let bar = b; *bar = false; })();
    |                 --             - variable moved due to use in closure
    |                 |
@@ -8,8 +11,6 @@ LL |         _ if { (|| { let bar = b; *bar = false; })();
 LL |                      false } => { },
 LL |         &mut true => { println!("You might think we should get here"); },
    |              ^^^^ value used here after move
-   |
-   = note: move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 146ebad6ce17567fc636095c2e417801d923521f..b6f520c644b32a659afd967d8a03cb7d4f9438f9 100644 (file)
@@ -11,8 +11,7 @@ LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                 --------^^^^^
    |                 |
    |                 function or associated item not found in `dyn std::ops::BitXor<_>`
-   |
-   = help: did you mean `bitxor`?
+   |                 help: did you mean: `bitxor`
 
 error[E0191]: the value of the associated type `Output` (from the trait `std::ops::BitXor`) must be specified
   --> $DIR/issue-28344.rs:8:13
@@ -27,8 +26,7 @@ LL |     let g = BitXor::bitor;
    |             --------^^^^^
    |             |
    |             function or associated item not found in `dyn std::ops::BitXor<_>`
-   |
-   = help: did you mean `bitxor`?
+   |             help: did you mean: `bitxor`
 
 error: aborting due to 4 previous errors
 
index d5dbd5f64885c2f695189680bfb507281bf8c248..77d0b53ad216bbef9be9f34168281a8a88c41df1 100644 (file)
@@ -5,9 +5,10 @@ LL | enum Foo {
    | -------- variant `Baz` not found here
 ...
 LL |             Foo::Baz(..) => (),
-   |             -----^^^---- variant not found in `Foo`
-   |
-   = help: did you mean `Bar`?
+   |             -----^^^----
+   |             |    |
+   |             |    help: did you mean: `Bar`
+   |             variant not found in `Foo`
 
 error: aborting due to previous error
 
index de858aec881f7330a9ffbd913904fc744fbc0b91..7928af5d5a5cd654df408173042b7b43be444fb4 100644 (file)
@@ -1,13 +1,14 @@
 error[E0382]: use of moved value: `s`
   --> $DIR/issue-29723.rs:12:13
    |
+LL |     let s = String::new();
+   |         - move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _s = match 0 {
 LL |         0 if { drop(s); false } => String::from("oops"),
    |                     - value moved here
 ...
 LL |             s
    |             ^ value used here after move
-   |
-   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index a4e333ec20ae0f7d3f52d31e00f29b209355f556..2234f68f246292a00449eb0ec2f11f6c5d7a389e 100644 (file)
@@ -2,11 +2,11 @@
 
 fn main() {
     { fn f<X: ::std::marker()::Send>() {} }
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 
     { fn f() -> impl ::std::marker()::Send { } }
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 }
 
@@ -14,5 +14,5 @@ fn main() {
 struct X;
 
 impl ::std::marker()::Copy for X {}
-//~^ ERROR parenthesized parameters may only be used with a trait
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
 //~| WARN previously accepted
index 0ac12b78d38429cdd15f910bafd91af86c20f48b..104b76cba2df933b107a96454adea65036331dd0 100644 (file)
@@ -1,4 +1,4 @@
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995-2.rs:4:28
    |
 LL |     { fn f<X: ::std::marker()::Send>() {} }
@@ -8,7 +8,7 @@ LL |     { fn f<X: ::std::marker()::Send>() {} }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995-2.rs:8:35
    |
 LL |     { fn f() -> impl ::std::marker()::Send { } }
@@ -17,7 +17,7 @@ LL |     { fn f() -> impl ::std::marker()::Send { } }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995-2.rs:16:19
    |
 LL | impl ::std::marker()::Copy for X {}
index 726cc85d3f4796d4c0054dad46ec016055a39e2b..c32fb63f1e5845a9c0ca18815f3516668ca58fe1 100644 (file)
@@ -2,32 +2,32 @@
 
 fn main() {
     let x: usize() = 1;
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 
     let b: ::std::boxed()::Box<_> = Box::new(1);
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 
     let p = ::std::str::()::from_utf8(b"foo").unwrap();
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 
     let p = ::std::str::from_utf8::()(b"foo").unwrap();
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 
     let o : Box<::std::marker()::Send> = Box::new(1);
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 
     let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 }
 
 fn foo<X:Default>() {
     let d : X() = Default::default();
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| WARN previously accepted
 }
index 12551bb7f1f00e17b3ee3f3431be0fcd04143c21..97b4b7fa76ca81354b7e6c6b89ce02923501a68a 100644 (file)
@@ -1,4 +1,4 @@
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995.rs:4:17
    |
 LL |     let x: usize() = 1;
@@ -8,7 +8,7 @@ LL |     let x: usize() = 1;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995.rs:8:24
    |
 LL |     let b: ::std::boxed()::Box<_> = Box::new(1);
@@ -17,25 +17,25 @@ LL |     let b: ::std::boxed()::Box<_> = Box::new(1);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
-  --> $DIR/issue-32995.rs:12:23
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:12:25
    |
 LL |     let p = ::std::str::()::from_utf8(b"foo").unwrap();
-   |                       ^^^^
+   |                         ^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
-  --> $DIR/issue-32995.rs:16:34
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:16:36
    |
 LL |     let p = ::std::str::from_utf8::()(b"foo").unwrap();
-   |                                  ^^^^
+   |                                    ^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995.rs:20:30
    |
 LL |     let o : Box<::std::marker()::Send> = Box::new(1);
@@ -44,7 +44,7 @@ LL |     let o : Box<::std::marker()::Send> = Box::new(1);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995.rs:24:37
    |
 LL |     let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
@@ -53,7 +53,7 @@ LL |     let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-32995.rs:30:14
    |
 LL |     let d : X() = Default::default();
diff --git a/src/test/ui/issues/issue-34721.rs b/src/test/ui/issues/issue-34721.rs
new file mode 100644 (file)
index 0000000..226c214
--- /dev/null
@@ -0,0 +1,34 @@
+#![feature(nll)]
+
+pub trait Foo {
+    fn zero(self) -> Self;
+}
+
+impl Foo for u32 {
+    fn zero(self) -> u32 { 0u32 }
+}
+
+pub mod bar {
+    pub use Foo;
+    pub fn bar<T: Foo>(x: T) -> T {
+      x.zero()
+    }
+}
+
+mod baz {
+    use bar;
+    use Foo;
+    pub fn baz<T: Foo>(x: T) -> T {
+        if 0 == 1 {
+            bar::bar(x.zero())
+        } else {
+            x.zero()
+        };
+        x.zero()
+        //~^ ERROR use of moved value
+    }
+}
+
+fn main() {
+    let _ = baz::baz(0u32);
+}
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
new file mode 100644 (file)
index 0000000..2ed7b54
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-34721.rs:27:9
+   |
+LL |     pub fn baz<T: Foo>(x: T) -> T {
+   |                -       - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                |
+   |                consider adding a `Copy` constraint to this type argument
+LL |         if 0 == 1 {
+LL |             bar::bar(x.zero())
+   |                      - value moved here
+LL |         } else {
+LL |             x.zero()
+   |             - value moved here
+LL |         };
+LL |         x.zero()
+   |         ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index 19c6a1fd557b42bf1439ca146eb4ddb9bd1ce68a..23cc88bab52d54dd7e83d3d4828784cd48e72394 100644 (file)
@@ -1,13 +1,13 @@
 error[E0382]: borrow of moved value: `s`
   --> $DIR/issue-42796.rs:18:20
    |
+LL |     let s = "Hello!".to_owned();
+   |         - move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let mut s_copy = s;
    |                      - value moved here
 ...
 LL |     println!("{}", s); //~ ERROR use of moved value
    |                    ^ value borrowed here after move
-   |
-   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 441f1b2a06960b27cffdff60690e4898005abb87..3f377fd27e7db29296083134fea603ff9e06c222 100644 (file)
@@ -9,8 +9,8 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}`...
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires computing layout of `Foo`...
-note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
+   = note: ...which requires computing layout of `Foo`...
+   = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
 note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}`...
   --> $DIR/issue-44415.rs:6:17
    |
index 99c4a5b03b3201a76d3cf126df44ac15bf4f2530..96d6814b0fe93762e7fd885fd3f0e9c82ce28024 100644 (file)
@@ -2,11 +2,10 @@ error[E0599]: no method named `deref_err` found for type `std::result::Result<_,
   --> $DIR/result-deref-err.rs:4:28
    |
 LL |     let _result = &Err(41).deref_err();
-   |                            ^^^^^^^^^
+   |                            ^^^^^^^^^ help: did you mean: `deref_ok`
    |
    = note: the method `deref_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::Deref`
-   = help: did you mean `deref_ok`?
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-52496.rs b/src/test/ui/issues/issue-52496.rs
new file mode 100644 (file)
index 0000000..4e94536
--- /dev/null
@@ -0,0 +1,12 @@
+struct Foo { bar: f64, baz: i64, bat: i64 }
+
+fn main() {
+    let _ = Foo { bar: .5, baz: 42 };
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR missing field `bat` in initializer of `Foo`
+    let bar = 1.5f32;
+    let _ = Foo { bar.into(), bat: -1, . };
+    //~^ ERROR expected one of
+    //~| ERROR missing fields `bar`, `baz` in initializer of `Foo`
+    //~| ERROR expected identifier, found `.`
+}
diff --git a/src/test/ui/issues/issue-52496.stderr b/src/test/ui/issues/issue-52496.stderr
new file mode 100644 (file)
index 0000000..43009a1
--- /dev/null
@@ -0,0 +1,37 @@
+error: float literals must have an integer part
+  --> $DIR/issue-52496.rs:4:24
+   |
+LL |     let _ = Foo { bar: .5, baz: 42 };
+   |                        ^^ help: must have an integer part: `0.5`
+
+error: expected one of `,` or `}`, found `.`
+  --> $DIR/issue-52496.rs:8:22
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ---      ^ expected one of `,` or `}` here
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `.`
+  --> $DIR/issue-52496.rs:8:40
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ---                        ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error[E0063]: missing field `bat` in initializer of `Foo`
+  --> $DIR/issue-52496.rs:4:13
+   |
+LL |     let _ = Foo { bar: .5, baz: 42 };
+   |             ^^^ missing `bat`
+
+error[E0063]: missing fields `bar`, `baz` in initializer of `Foo`
+  --> $DIR/issue-52496.rs:8:13
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ^^^ missing `bar`, `baz`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/issues/issue-54521-1.rs
new file mode 100644 (file)
index 0000000..d6a14a6
--- /dev/null
@@ -0,0 +1,16 @@
+// compile-pass
+
+// This test checks that the `remove extra angle brackets` error doesn't happen for some
+// potential edge-cases..
+
+struct X {
+    len: u32,
+}
+
+fn main() {
+    let x = X { len: 3 };
+
+    let _ = x.len > (3);
+
+    let _ = x.len >> (3);
+}
diff --git a/src/test/ui/issues/issue-54521-2.fixed b/src/test/ui/issues/issue-54521-2.fixed
new file mode 100644 (file)
index 0000000..a91c4fe
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521-2.rs b/src/test/ui/issues/issue-54521-2.rs
new file mode 100644 (file)
index 0000000..3639aac
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521-2.stderr b/src/test/ui/issues/issue-54521-2.stderr
new file mode 100644 (file)
index 0000000..9556b83
--- /dev/null
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:11:25
+   |
+LL |     let _ = Vec::<usize>>>>>::new();
+   |                         ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:14:25
+   |
+LL |     let _ = Vec::<usize>>>>::new();
+   |                         ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:17:25
+   |
+LL |     let _ = Vec::<usize>>>::new();
+   |                         ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521-2.rs:20:25
+   |
+LL |     let _ = Vec::<usize>>::new();
+   |                         ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-54521.fixed b/src/test/ui/issues/issue-54521.fixed
new file mode 100644 (file)
index 0000000..84ab686
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521.rs b/src/test/ui/issues/issue-54521.rs
new file mode 100644 (file)
index 0000000..f1d6850
--- /dev/null
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521.stderr b/src/test/ui/issues/issue-54521.stderr
new file mode 100644 (file)
index 0000000..ffefbfd
--- /dev/null
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:11:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+   |                                                            ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:14:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+   |                                                            ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:17:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+   |                                                            ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521.rs:20:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+   |                                                            ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-54582.rs b/src/test/ui/issues/issue-54582.rs
new file mode 100644 (file)
index 0000000..c2dbf36
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+
+pub trait Stage: Sync {}
+
+pub enum Enum {
+    A,
+    B,
+}
+
+impl Stage for Enum {}
+
+pub static ARRAY: [(&Stage, &str); 1] = [
+    (&Enum::A, ""),
+];
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56488.rs b/src/test/ui/issues/issue-56488.rs
new file mode 100644 (file)
index 0000000..e2f3996
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod alpha {
+    pub trait A {}
+    pub trait C = A;
+}
+
+#[allow(unused_imports)]
+use alpha::C;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56943.rs b/src/test/ui/issues/issue-56943.rs
new file mode 100644 (file)
index 0000000..8fc77ab
--- /dev/null
@@ -0,0 +1,8 @@
+// aux-build:issue-56943.rs
+
+extern crate issue_56943;
+
+fn main() {
+    let _: issue_56943::S = issue_56943::S2;
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-56943.stderr b/src/test/ui/issues/issue-56943.stderr
new file mode 100644 (file)
index 0000000..2720205
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-56943.rs:6:29
+   |
+LL |     let _: issue_56943::S = issue_56943::S2;
+   |                             ^^^^^^^^^^^^^^^ expected struct `issue_56943::S`, found struct `issue_56943::S2`
+   |
+   = note: expected type `issue_56943::S`
+              found type `issue_56943::S2`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57684.fixed b/src/test/ui/issues/issue-57684.fixed
new file mode 100644 (file)
index 0000000..4a43220
--- /dev/null
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This test checks that the following error is emitted when a `=` character is used to initialize
+// a struct field when a `:` is expected.
+//
+// ```
+// error: struct fields are initialized with a colon
+//   --> $DIR/issue-57684.rs:12:20
+//    |
+// LL |     let _ = X { f1 = 5 };
+//    |                    ^ help: replace equals symbol with a colon: `:`
+// ```
+
+struct X {
+    f1: i32,
+}
+
+struct Y {
+    f1: i32,
+    f2: i32,
+    f3: i32,
+}
+
+fn main() {
+    let _ = X { f1: 5 };
+    //~^ ERROR expected `:`, found `=`
+
+    let f3 = 3;
+    let _ = Y {
+        f1: 5,
+        //~^ ERROR expected `:`, found `=`
+        f2: 4,
+        f3,
+    };
+}
diff --git a/src/test/ui/issues/issue-57684.rs b/src/test/ui/issues/issue-57684.rs
new file mode 100644 (file)
index 0000000..7a62785
--- /dev/null
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This test checks that the following error is emitted when a `=` character is used to initialize
+// a struct field when a `:` is expected.
+//
+// ```
+// error: struct fields are initialized with a colon
+//   --> $DIR/issue-57684.rs:12:20
+//    |
+// LL |     let _ = X { f1 = 5 };
+//    |                    ^ help: replace equals symbol with a colon: `:`
+// ```
+
+struct X {
+    f1: i32,
+}
+
+struct Y {
+    f1: i32,
+    f2: i32,
+    f3: i32,
+}
+
+fn main() {
+    let _ = X { f1 = 5 };
+    //~^ ERROR expected `:`, found `=`
+
+    let f3 = 3;
+    let _ = Y {
+        f1 = 5,
+        //~^ ERROR expected `:`, found `=`
+        f2: 4,
+        f3,
+    };
+}
diff --git a/src/test/ui/issues/issue-57684.stderr b/src/test/ui/issues/issue-57684.stderr
new file mode 100644 (file)
index 0000000..514bbff
--- /dev/null
@@ -0,0 +1,18 @@
+error: expected `:`, found `=`
+  --> $DIR/issue-57684.rs:27:20
+   |
+LL |     let _ = X { f1 = 5 };
+   |                   -^
+   |                   |
+   |                   help: replace equals symbol with a colon: `:`
+
+error: expected `:`, found `=`
+  --> $DIR/issue-57684.rs:32:12
+   |
+LL |         f1 = 5,
+   |           -^
+   |           |
+   |           help: replace equals symbol with a colon: `:`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-57741-1.rs b/src/test/ui/issues/issue-57741-1.rs
new file mode 100644 (file)
index 0000000..d0aae23
--- /dev/null
@@ -0,0 +1,18 @@
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made
+// because the box doesn't deref to the type of the arm.
+
+enum S {
+    A { a: usize },
+    B { b: usize },
+}
+
+fn main() {
+    let x = Box::new(3u32);
+    let y = match x {
+        S::A { a } | S::B { b: a } => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+}
diff --git a/src/test/ui/issues/issue-57741-1.stderr b/src/test/ui/issues/issue-57741-1.stderr
new file mode 100644 (file)
index 0000000..d36424b
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57741-1.rs:14:9
+   |
+LL |     let y = match x {
+   |                   - this match expression has type `std::boxed::Box<u32>`
+LL |         S::A { a } | S::B { b: a } => a,
+   |         ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<u32>`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741-1.rs:14:22
+   |
+LL |     let y = match x {
+   |                   - this match expression has type `std::boxed::Box<u32>`
+LL |         S::A { a } | S::B { b: a } => a,
+   |                      ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<u32>`
+              found type `S`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57741.fixed b/src/test/ui/issues/issue-57741.fixed
new file mode 100644 (file)
index 0000000..4cae080
--- /dev/null
@@ -0,0 +1,31 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
+
+enum S {
+    A { a: usize },
+    B { b: usize },
+}
+
+enum T {
+    A(usize),
+    B(usize),
+}
+
+fn main() {
+    let x = Box::new(T::A(3));
+    let y = match *x {
+        T::A(a) | T::B(a) => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+
+    let x = Box::new(S::A { a: 3 });
+    let y = match *x {
+        S::A { a } | S::B { b: a } => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+}
diff --git a/src/test/ui/issues/issue-57741.rs b/src/test/ui/issues/issue-57741.rs
new file mode 100644 (file)
index 0000000..e265829
--- /dev/null
@@ -0,0 +1,31 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
+
+enum S {
+    A { a: usize },
+    B { b: usize },
+}
+
+enum T {
+    A(usize),
+    B(usize),
+}
+
+fn main() {
+    let x = Box::new(T::A(3));
+    let y = match x {
+        T::A(a) | T::B(a) => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+
+    let x = Box::new(S::A { a: 3 });
+    let y = match x {
+        S::A { a } | S::B { b: a } => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+}
diff --git a/src/test/ui/issues/issue-57741.stderr b/src/test/ui/issues/issue-57741.stderr
new file mode 100644 (file)
index 0000000..a26b1d2
--- /dev/null
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:20:9
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<T>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         T::A(a) | T::B(a) => a,
+   |         ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
+   |
+   = note: expected type `std::boxed::Box<T>`
+              found type `T`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:20:19
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<T>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         T::A(a) | T::B(a) => a,
+   |                   ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
+   |
+   = note: expected type `std::boxed::Box<T>`
+              found type `T`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:27:9
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<S>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         S::A { a } | S::B { b: a } => a,
+   |         ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<S>`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:27:22
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<S>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         S::A { a } | S::B { b: a } => a,
+   |                      ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<S>`
+              found type `S`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
new file mode 100644 (file)
index 0000000..0d18965
--- /dev/null
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+trait Foo {}
+
+impl Foo for dyn Send {}
+
+impl Foo for dyn Send + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync {}
+
+impl Foo for dyn Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
new file mode 100644 (file)
index 0000000..928c92e
--- /dev/null
@@ -0,0 +1,39 @@
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:7:1
+   |
+LL | impl Foo for dyn Send {}
+   | --------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Send + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   |
+   = note: #[deny(order_dependent_trait_objects)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:13:1
+   |
+LL | impl Foo for dyn Send + Sync {}
+   | ---------------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:17:1
+   |
+LL | impl Foo for dyn Sync + Send {}
+   | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: aborting due to 3 previous errors
+
index bbcbbdbe8dd5bccca7640f06f600d711e7d2faf7..a970b80fdbbd93e9da12b018c0207f75487675a5 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/liveness-forgot-ret.rs:3:19
    |
 LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
-   |    -              ^^^^^ expected isize, found ()    - expected because of this statement
+   |    -              ^^^^^ expected isize, found ()
    |    |
    |    this function's body doesn't return
    |
index 3aa89ac8a9b711f6bfe672cb40c9c9460513e416..521304d560554850b7cfaa1498471c9c0a879774 100644 (file)
@@ -1,10 +1,11 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/liveness-move-call-arg.rs:9:14
    |
+LL |     let x: Box<isize> = box 25;
+   |         - move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL |     loop {
 LL |         take(x); //~ ERROR use of moved value: `x`
    |              ^ value moved here, in previous iteration of loop
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 8a5a18f3316c757c83b6da8c06af4444ede77085..b7e973bc9140d3ef3ef9d788a41ad2948247eede 100644 (file)
@@ -1,10 +1,11 @@
 error[E0382]: use of moved value: `y`
   --> $DIR/liveness-move-in-loop.rs:11:25
    |
+LL |     let y: Box<isize> = box 42;
+   |         - move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+...
 LL |                     x = y; //~ ERROR use of moved value
    |                         ^ value moved here, in previous iteration of loop
-   |
-   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 081983d8bf0160ff3cdb8ee58c55fa90bd9cecbb..167dcc6b6437207a70fdecfdee6ead7e7eacfab0 100644 (file)
@@ -1,12 +1,13 @@
 error[E0382]: borrow of moved value: `y`
   --> $DIR/liveness-move-in-while.rs:7:24
    |
+LL |     let y: Box<isize> = box 42;
+   |         - move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+...
 LL |         println!("{}", y); //~ ERROR use of moved value: `y`
    |                        ^ value borrowed here after move
 LL |         while true { while true { while true { x = y; x.clone(); } } }
    |                                                    - value moved here, in previous iteration of loop
-   |
-   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 45fd43687f39b3801f36e72fd95df186b131c103..36c25882ccd4f6ddfc75b36b44324f0cb957be57 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/liveness-use-after-move.rs:6:20
    |
+LL |     let x: Box<_> = box 5;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 LL |     let y = x;
    |             - value moved here
 LL |     println!("{}", *x); //~ ERROR use of moved value: `*x`
    |                    ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 2b55b5d59732b9e19fc8a74a121108b079e5bbb7..d9367c871165a72d93bbe3714436f74bee56884d 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: borrow of moved value: `message`
   --> $DIR/liveness-use-after-send.rs:16:20
    |
+LL | fn test00_start(ch: Chan<Box<isize>>, message: Box<isize>, _count: Box<isize>) {
+   |                                       ------- move occurs because `message` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 LL |     send(ch, message);
    |              ------- value moved here
 LL |     println!("{}", message); //~ ERROR use of moved value: `message`
    |                    ^^^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `message` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/move-guard-same-consts.nll.stderr b/src/test/ui/moves/move-guard-same-consts.nll.stderr
new file mode 100644 (file)
index 0000000..43f99ca
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-guard-same-consts.rs:20:24
+   |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
+LL |         (1, 2) if take(x) => (),
+   |                        - value moved here
+LL |         (1, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+   |                        ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-in-guard-1.nll.stderr b/src/test/ui/moves/move-in-guard-1.nll.stderr
new file mode 100644 (file)
index 0000000..41abe6f
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-in-guard-1.rs:10:24
+   |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
+LL |         (1, _) if take(x) => (),
+   |                        - value moved here
+LL |         (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+   |                        ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index 2d939443846094579c2640c0e2d7f8b7b831a858..0b14c1620d3cf17e5865486d1c69a57f53553fdc 100644 (file)
@@ -1,10 +1,11 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/move-in-guard-2.rs:10:24
    |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
 LL |         (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
    |                        ^ value moved here, in previous iteration of loop
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 5b2e1bed0c7bf04324075bbc3c224129fc26b43c..20bfdc2bbac7202a5f0c2d118ea2ea32a48fa8a8 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `a`
   --> $DIR/move-into-dead-array-2.rs:14:5
    |
+LL | fn foo(mut a: [D; 4], i: usize) {
+   |        ----- move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait
 LL |     drop(a);
    |          - value moved here
 LL |     a[i] = d(); //~ ERROR use of moved value: `a`
    |     ^^^^ value used here after move
-   |
-   = note: move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 22968b329695fd359dd210c10f1ba2541c18a397..6ad9a2d414c77027be2c0ba75dd86ea0d066a3bd 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-access-to-field.rs:11:12
    |
+LL |     let x = vec!["hi".to_string()];
+   |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 LL |     consume(x.into_iter().next().unwrap());
    |             - value moved here
 LL |     touch(&x[0]); //~ ERROR use of moved value: `x`
    |            ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 061e871c78a733bf34beb84d20ceb7fad590590d..bed0ae7275cc525cd9d4960db3d77ee9f2775cf3 100644 (file)
@@ -1,6 +1,8 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-capture-clause-bad.rs:8:20
    |
+LL |     let x = "Hello world!".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     thread::spawn(move|| {
    |                   ------ value moved into closure here
 LL |         println!("{}", x);
@@ -8,8 +10,6 @@ LL |         println!("{}", x);
 LL |     });
 LL |     println!("{}", x); //~ ERROR use of moved value
    |                    ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 10593a6078e3b152a333c2d7f9bf55269ddfb645..07f40274f9e310f129e823cb7ae4b1d478cc15de 100644 (file)
@@ -1,24 +1,24 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:11:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = Foo { f:x };
    |                      - value moved here
 LL |     //~^ NOTE value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:20:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = Foo { f:(((x))) };
    |                      ------- value moved here
 LL |     //~^ NOTE value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index fe44803e2734b67a55b6b302570e718e4f2015bc..162aec45f5f5743453f616c7c965b00880c8d3ec 100644 (file)
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:12:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = Foo { f:x };
    |                      - value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:18:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = (x, 3);
    |               - value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:35:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |         x
    |         - value moved here
 ...
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `y`
   --> $DIR/moves-based-on-type-exprs.rs:36:11
    |
+LL |     let y = "ho".to_string();
+   |         - move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |         y
    |         - value moved here
 ...
 LL |     touch(&y); //~ ERROR use of moved value: `y`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:46:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |         true => x,
    |                 - value moved here
 ...
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `y`
   --> $DIR/moves-based-on-type-exprs.rs:47:11
    |
+LL |     let y = "ho".to_string();
+   |         - move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |         false => y
    |                  - value moved here
 ...
 LL |     touch(&y); //~ ERROR use of moved value: `y`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:58:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |         _ if guard(x) => 10,
    |                    - value moved here
 ...
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:65:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = [x];
    |               - value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:71:11
    |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = vec![x];
    |                   - value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:77:11
    |
+LL |     let x = vec!["hi".to_string()];
+   |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 LL |     let _y = x.into_iter().next().unwrap();
    |              - value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:83:11
    |
+LL |     let x = vec!["hi".to_string()];
+   |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 LL |     let _y = [x.into_iter().next().unwrap(); 1];
    |               - value moved here
 LL |     touch(&x); //~ ERROR use of moved value: `x`
    |           ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 
 error: aborting due to 11 previous errors
 
index 03a23420bbc9ea12e75f166738b86d5e6fcf656d..391dd67dbf60aa469c7fad3a83c7afb5b57d74cf 100644 (file)
@@ -10,12 +10,14 @@ LL |                     (f.c)(f, true);
 error[E0382]: borrow of moved value: `f`
   --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5
    |
+LL | fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
+   |                -  ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait
+   |                |
+   |                consider adding a `Copy` constraint to this type argument
 LL |     let mut r = R {c: Box::new(f)};
    |                                - value moved here
 LL |     f(&mut r, false) //~ ERROR use of moved value
    |     ^ value borrowed here after move
-   |
-   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index 2d2c0a15a002a8a47a42c79660e3f527946990ef..c49dbdab402108d534b89a9f62d4be3bc522ebf8 100644 (file)
@@ -11,12 +11,12 @@ LL |     box (x, x)
 error[E0382]: use of moved value: `x` (Mir)
   --> $DIR/moves-based-on-type-tuple.rs:6:13
    |
+LL | fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
+   |        - move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 LL |     box (x, x)
    |          -  ^ value used here after move
    |          |
    |          value moved here
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
index efe4c15240d2083eab4483f1688f168bbc672c2f..3ca0aefb592e0898ce1409b5a4924757d35ec897 100644 (file)
@@ -59,50 +59,50 @@ LL |     r.use_ref();
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-access-spans.rs:37:5
    |
+LL | fn closure_imm_capture_moved(mut x: String) {
+   |                              ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let r = x;
    |             - value moved here
 LL |     || x.len(); //~ ERROR
    |     ^^ - borrow occurs due to use in closure
    |     |
    |     value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-access-spans.rs:42:5
    |
+LL | fn closure_mut_capture_moved(mut x: String) {
+   |                              ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let r = x;
    |             - value moved here
 LL |     || x = String::new(); //~ ERROR
    |     ^^ - borrow occurs due to use in closure
    |     |
    |     value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-access-spans.rs:47:5
    |
+LL | fn closure_unique_capture_moved(x: &mut String) {
+   |                                 - move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
 LL |     let r = x;
    |             - value moved here
 LL |     || *x = String::new(); //~ ERROR
    |     ^^  - borrow occurs due to use in closure
    |     |
    |     value borrowed here after move
-   |
-   = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `x`
   --> $DIR/closure-access-spans.rs:52:5
    |
+LL | fn closure_move_capture_moved(x: &mut String) {
+   |                               - move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
 LL |     let r = x;
    |             - value moved here
 LL |     || x; //~ ERROR
    |     ^^ - use occurs due to use in closure
    |     |
    |     value used here after move
-   |
-   = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to 9 previous errors
 
index 3ae1912eb10bf4d7e82d2e4b48fa3acc00d5b2ae..6750c4047601a4b4627c10e760db135cca52ee44 100644 (file)
@@ -1,38 +1,38 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/closure-move-spans.rs:7:13
    |
+LL | fn move_after_move(x: String) {
+   |                    - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     || x;
    |     -- - variable moved due to use in closure
    |     |
    |     value moved into closure here
 LL |     let y = x; //~ ERROR
    |             ^ value used here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-move-spans.rs:12:13
    |
+LL | fn borrow_after_move(x: String) {
+   |                      - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     || x;
    |     -- - variable moved due to use in closure
    |     |
    |     value moved into closure here
 LL |     let y = &x; //~ ERROR
    |             ^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-move-spans.rs:17:13
    |
+LL | fn borrow_mut_after_move(mut x: String) {
+   |                          ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     || x;
    |     -- - variable moved due to use in closure
    |     |
    |     value moved into closure here
 LL |     let y = &mut x; //~ ERROR
    |             ^^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to 3 previous errors
 
index 93e095d663cc22651be10fa6d536e59a016be943..6c9e1639f88dd7f6c8066a9ee841dd8178a4bff3 100644 (file)
@@ -1,12 +1,13 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/closures-in-loops.rs:8:9
    |
+LL | fn repreated_move(x: String) {
+   |                   - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     for i in 0..10 {
 LL |         || x; //~ ERROR
    |         ^^ - use occurs due to use in closure
    |         |
    |         value moved into closure here, in previous iteration of loop
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/closures-in-loops.rs:15:16
index e29c44760a987ecfe39f154a67c6d146b5cde2e8..54c728e3d2783fdb1e6c53bdb672cf1f8353a58d 100644 (file)
@@ -13,12 +13,12 @@ LL |     d.x = 10;
 error[E0382]: assign of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:43:5
    |
+LL |     let mut d = D { x: 0, s: S{ y: 0, z: 0 } };
+   |         ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait
 LL |     drop(d);
    |          - value moved here
 LL |     d.x = 10;
    |     ^^^^^^^^ value assigned here after move
-   |
-   = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait
 
 error[E0381]: assign to part of possibly uninitialized variable: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:49:5
@@ -35,12 +35,12 @@ LL |     d.s.y = 20;
 error[E0382]: assign to part of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:62:5
    |
+LL |     let mut d = D { x: 0, s: S{ y: 0, z: 0} };
+   |         ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait
 LL |     drop(d);
    |          - value moved here
 LL |     d.s.y = 20;
    |     ^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait
 
 error: aborting due to 6 previous errors
 
index aec7f676fcebd6688b2d912f52e398f5f416a1d6..23da533252cb9c6e64a4a7416410162c6f5c6f99 100644 (file)
@@ -14,21 +14,21 @@ error[E0382]: assign to part of moved value: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:113:5
    |
 LL |     let mut s: S<B> = S::new(); drop(s);
-   |                                      - value moved here
+   |         -----                        - value moved here
+   |         |
+   |         move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
 LL |     s.x = 10; s.y = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:120:5
    |
 LL |     let mut t: T = (0, Box::new(0)); drop(t);
-   |                                           - value moved here
+   |         -----                             - value moved here
+   |         |
+   |         move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
 LL |     t.0 = 10; t.1 = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
 
 error[E0381]: assign to part of possibly uninitialized variable: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:127:5
@@ -46,21 +46,21 @@ error[E0382]: assign to part of moved value: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:141:5
    |
 LL |     let mut s: S<B> = S::new(); drop(s);
-   |                                      - value moved here
+   |         -----                        - value moved here
+   |         |
+   |         move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
 LL |     s.x = 10;
    |     ^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:148:5
    |
 LL |     let mut t: T = (0, Box::new(0)); drop(t);
-   |                                           - value moved here
+   |         -----                             - value moved here
+   |         |
+   |         move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
 LL |     t.0 = 10;
    |     ^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
 
 error[E0381]: assign to part of possibly uninitialized variable: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:155:5
@@ -153,22 +153,24 @@ LL |     q.r.f.0 = 10;
 error[E0382]: assign to part of moved value: `c`
   --> $DIR/issue-21232-partial-init-and-use.rs:259:13
    |
+LL |     let mut c = (1, "".to_owned());
+   |         ----- move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait
+LL |     match c {
 LL |         c2 => {
    |         -- value moved here
 LL |             c.0 = 2; //~ ERROR assign to part of moved value
    |             ^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `c`
   --> $DIR/issue-21232-partial-init-and-use.rs:269:13
    |
+LL |     let mut c = (1, (1, "".to_owned()));
+   |         ----- move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait
+LL |     match c {
 LL |         c2 => {
    |         -- value moved here
 LL |             (c.1).0 = 2; //~ ERROR assign to part of moved value
    |             ^^^^^^^^^^^ value partially assigned here after move
-   |
-   = note: move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `c.1`
   --> $DIR/issue-21232-partial-init-and-use.rs:277:13
index 4717935e4b9f9fd3cdfb0dc9cf14168a34fb5f32..a84a236ca77722995b7c5760985dc6f51d0d1236 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `range`
   --> $DIR/issue-51512.rs:7:13
    |
+LL |     let range = 0..1;
+   |         ----- move occurs because `range` has type `std::ops::Range<i32>`, which does not implement the `Copy` trait
 LL |     let r = range;
    |             ----- value moved here
 LL |     let x = range.start;
    |             ^^^^^^^^^^^ value used here after move
-   |
-   = note: move occurs because `range` has type `std::ops::Range<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index e1fb76c6bc24209f1eb5744de06089ef02da4a81..f51768c3859e4f3244ed795bdb74e56f9153d309 100644 (file)
@@ -1,12 +1,13 @@
 error[E0382]: borrow of moved value: `a.b`
   --> $DIR/issue-52669.rs:15:5
    |
+LL | fn bar(mut a: A) -> B {
+   |        ----- move occurs because `a` has type `A`, which does not implement the `Copy` trait
+LL |     a.b = B;
 LL |     foo(a);
    |         - value moved here
 LL |     a.b.clone()
    |     ^^^ value borrowed here after move
-   |
-   = note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index a3bb56024c4540a1499d721057f3564984a49f04..476b6f75abb46b569595054dc363fae9dd51b168 100644 (file)
@@ -1,6 +1,9 @@
 error[E0382]: borrow of moved value: `arc_v`
   --> $DIR/no-capture-arc.rs:14:18
    |
+LL |     let arc_v = Arc::new(v);
+   |         ----- move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+LL | 
 LL |     thread::spawn(move|| {
    |                   ------ value moved into closure here
 LL |         assert_eq!((*arc_v)[3], 4);
@@ -8,8 +11,6 @@ LL |         assert_eq!((*arc_v)[3], 4);
 ...
 LL |     assert_eq!((*arc_v)[2], 3);
    |                  ^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index e24edc5e8e3cafadb01a430759d9198b1943596f..0b14f65a770733b8894a9fcefbe21bfc0fca7876 100644 (file)
@@ -1,6 +1,9 @@
 error[E0382]: borrow of moved value: `arc_v`
   --> $DIR/no-reuse-move-arc.rs:12:18
    |
+LL |     let arc_v = Arc::new(v);
+   |         ----- move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+LL | 
 LL |     thread::spawn(move|| {
    |                   ------ value moved into closure here
 LL |         assert_eq!((*arc_v)[3], 4);
@@ -8,8 +11,6 @@ LL |         assert_eq!((*arc_v)[3], 4);
 ...
 LL |     assert_eq!((*arc_v)[2], 3); //~ ERROR use of moved value: `arc_v`
    |                  ^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 3a32e13e0aa6cf298c1edbb58954a9af11156313..7b45d848c97b7a3e1406f287154084728cd879e1 100644 (file)
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied
+error[E0277]: the type `[i32]` cannot be indexed by `i32`
   --> $DIR/slice-index.rs:11:5
    |
 LL |     x[1i32]; //~ ERROR E0277
@@ -7,7 +7,7 @@ LL |     x[1i32]; //~ ERROR E0277
    = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
    = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[i32]`
 
-error[E0277]: the trait bound `std::ops::RangeTo<i32>: std::slice::SliceIndex<[i32]>` is not satisfied
+error[E0277]: the type `[i32]` cannot be indexed by `std::ops::RangeTo<i32>`
   --> $DIR/slice-index.rs:12:5
    |
 LL |     x[..1i32]; //~ ERROR E0277
diff --git a/src/test/ui/once-cant-call-twice-on-heap.nll.stderr b/src/test/ui/once-cant-call-twice-on-heap.nll.stderr
new file mode 100644 (file)
index 0000000..ea53abc
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `blk`
+  --> $DIR/once-cant-call-twice-on-heap.rs:9:5
+   |
+LL | fn foo<F:FnOnce()>(blk: F) {
+   |        -           --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     blk();
+   |     --- value moved here
+LL |     blk(); //~ ERROR use of moved value
+   |     ^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/parenthesised-deref-suggestion.rs b/src/test/ui/parenthesised-deref-suggestion.rs
deleted file mode 100644 (file)
index 0b4ccdd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-struct Session {
-    opts: u8,
-}
-
-fn main() {
-    let sess: &Session = &Session { opts: 0 };
-    (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
-
-    let x = [0u32];
-    (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
-}
diff --git a/src/test/ui/parenthesised-deref-suggestion.stderr b/src/test/ui/parenthesised-deref-suggestion.stderr
deleted file mode 100644 (file)
index 71a2bf6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0609]: no field `opts` on type `*const Session`
-  --> $DIR/parenthesised-deref-suggestion.rs:7:30
-   |
-LL |     (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
-   |                              ^^^^
-help: `(sess as *const Session)` is a raw pointer; try dereferencing it
-   |
-LL |     (*(sess as *const Session)).opts; //~ ERROR no field `opts` on type `*const Session`
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0609]: no field `0` on type `[u32; 1]`
-  --> $DIR/parenthesised-deref-suggestion.rs:10:21
-   |
-LL |     (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
-   |     ----------------^
-   |     |
-   |     help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/parenthesized-deref-suggestion.rs b/src/test/ui/parenthesized-deref-suggestion.rs
new file mode 100644 (file)
index 0000000..0b4ccdd
--- /dev/null
@@ -0,0 +1,11 @@
+struct Session {
+    opts: u8,
+}
+
+fn main() {
+    let sess: &Session = &Session { opts: 0 };
+    (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
+
+    let x = [0u32];
+    (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
+}
diff --git a/src/test/ui/parenthesized-deref-suggestion.stderr b/src/test/ui/parenthesized-deref-suggestion.stderr
new file mode 100644 (file)
index 0000000..fd9b0e8
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0609]: no field `opts` on type `*const Session`
+  --> $DIR/parenthesized-deref-suggestion.rs:7:30
+   |
+LL |     (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
+   |                              ^^^^
+help: `(sess as *const Session)` is a raw pointer; try dereferencing it
+   |
+LL |     (*(sess as *const Session)).opts; //~ ERROR no field `opts` on type `*const Session`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0609]: no field `0` on type `[u32; 1]`
+  --> $DIR/parenthesized-deref-suggestion.rs:10:21
+   |
+LL |     (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
+   |     ----------------^
+   |     |
+   |     help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
index b764e9f7ae1024546228b80cb5b4e2526e9776e0..5809d64e8067843dd0f6e31621d1d59ca9d5b2d5 100644 (file)
@@ -2,7 +2,7 @@ error: expected item after doc comment
   --> $DIR/doc-before-eof.rs:3:1
    |
 LL | /// hi //~ERROR expected item after doc comment
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything
 
 error: aborting due to previous error
 
index 47fab7b40f4cd0166ada76a6d4bdeb0d50d95fae..8cc9c916a7afd6b3531399f9102277e1a0825f34 100644 (file)
@@ -2,7 +2,7 @@ error: expected item after doc comment
   --> $DIR/doc-before-extern-rbrace.rs:2:5
    |
 LL |     /// hi
-   |     ^^^^^^
+   |     ^^^^^^ this doc comment doesn't document anything
 
 error: aborting due to previous error
 
index 41c1d706b3a7eecf0ac07de17b3e428b05762aa2..4eaf351f676c8963906faec647d7db7c6fc49a81 100644 (file)
@@ -2,7 +2,7 @@ error: expected item after doc comment
   --> $DIR/doc-before-mod-rbrace.rs:4:5
    |
 LL |     /// document
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ this doc comment doesn't document anything
 
 error: aborting due to previous error
 
index 4e74516d6b6fbd67320e83a8b874831d02765cbf..795a8c7631d9a84d28b78bffd908933ba79e7d43 100644 (file)
@@ -1,6 +1,6 @@
 const
 mut //~ ERROR: const globals cannot be mutable
-//~^ HELP did you mean to declare a static?
+//~^^ HELP you might want to declare a static instead
 FOO: usize = 3;
 
 fn main() {
index 29a65ebe418891af89d65fdb2ef64d974e059716..19f9fe19ef5abaf88a018db5e5d6ec003e2c1cbe 100644 (file)
@@ -1,10 +1,10 @@
 error: const globals cannot be mutable
   --> $DIR/issue-17718-const-mut.rs:2:1
    |
+LL | const
+   | ----- help: you might want to declare a static instead: `static`
 LL | mut //~ ERROR: const globals cannot be mutable
-   | ^^^
-   |
-   = help: did you mean to declare a static?
+   | ^^^ cannot be mutable
 
 error: aborting due to previous error
 
index 7f859995218d97ace50c598043114643cd2e7d17..1e180f87fc186ef1719ee47e0b9e71560bdd25d5 100644 (file)
@@ -1,4 +1,4 @@
 // This test needs to the last one appearing in this file as it kills the parser
 static c: char =
-    'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
+    'nope' //~ ERROR: character literal may only contain one codepoint
 ;
index a7075b71878121a4ed4ca3d72c539bf19808457b..7eadb8ebfe06d6021636c9038a18e480c89a49c5 100644 (file)
@@ -1,8 +1,13 @@
-error: character literal may only contain one codepoint: 'nope'
+error: character literal may only contain one codepoint
   --> $DIR/lex-bad-char-literals-2.rs:3:5
    |
-LL |     'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
+LL |     'nope' //~ ERROR: character literal may only contain one codepoint
    |     ^^^^^^
 
-error: aborting due to previous error
+error[E0601]: `main` function not found in crate `lex_bad_char_literals_2`
+   |
+   = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs`
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0601`.
index f8749708f77210831552c1f0bd06351f397d05e6..5194ff4d9354f2dc744cf22b1f57f7c040a9c1d1 100644 (file)
@@ -1,7 +1,7 @@
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
-    '●●' //~ ERROR: character literal may only contain one codepoint
-         //~| ERROR: mismatched types
-;
+static c: char = '●●';
+//~^ ERROR: character literal may only contain one codepoint
 
-fn main() {}
+fn main() {
+    let ch: &str = '●●';
+    //~^ ERROR: character literal may only contain one codepoint
+}
index 89f18e3e2aa4dcbeb18aa6c3531f42b04f16225c..6462a3c0e57ba53606c88d6c48cd160f9c4aa96f 100644 (file)
@@ -1,22 +1,22 @@
 error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-3.rs:3:5
+  --> $DIR/lex-bad-char-literals-3.rs:1:18
    |
-LL |     '●●' //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^
+LL | static c: char = '●●';
+   |                  ^^^^
 help: if you meant to write a `str` literal, use double quotes
    |
-LL |     "●●" //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^
+LL | static c: char = "●●";
+   |                  ^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/lex-bad-char-literals-3.rs:3:5
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-3.rs:5:20
    |
-LL |     '●●' //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^ expected char, found reference
+LL |     let ch: &str = '●●';
+   |                    ^^^^
+help: if you meant to write a `str` literal, use double quotes
    |
-   = note: expected type `char`
-              found type `&'static str`
+LL |     let ch: &str = "●●";
+   |                    ^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
index 966e2bb949688589686328c2f35e7adfdff8b06d..e13f11f36df489e0b23972e514d0bdd11675cddb 100644 (file)
@@ -1,5 +1,5 @@
 //
 // This test needs to the last one appearing in this file as it kills the parser
 static c: char =
-    '●  //~ ERROR: character literal may only contain one codepoint: '●
+    '●  //~ ERROR: character literal may only contain one codepoint
 ;
index 550cb5449df19cac43fe6d2d2434f99c1360bf20..881e3d5276bb1bf564710cf63acfdacf8ae549f9 100644 (file)
@@ -1,7 +1,7 @@
 error: character literal may only contain one codepoint: '●
   --> $DIR/lex-bad-char-literals-4.rs:4:5
    |
-LL |     '●  //~ ERROR: character literal may only contain one codepoint: '●
+LL |     '●  //~ ERROR: character literal may only contain one codepoint
    |     ^^
 
 error: aborting due to previous error
index 247289ea4d54b45fb1cce0e52ebb4d96f7efec50..0c4339edc4fa7f9d17dea6da00e97f56d0b941ed 100644 (file)
@@ -1,8 +1,7 @@
-//
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
-    '\x10\x10'  //~ ERROR: character literal may only contain one codepoint
-                //~| ERROR: mismatched types
-;
+static c: char = '\x10\x10';
+//~^ ERROR: character literal may only contain one codepoint
 
-fn main() {}
+fn main() {
+    let ch: &str = '\x10\x10';
+    //~^ ERROR: character literal may only contain one codepoint
+}
index 523d71ff49d2b360c58541a1f53478ceccbf877f..ef0297331015339b70445ad36d83dffdbe7b0213 100644 (file)
@@ -1,22 +1,22 @@
 error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-5.rs:4:5
+  --> $DIR/lex-bad-char-literals-5.rs:1:18
    |
-LL |     '/x10/x10'  //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^^^^^^^
+LL | static c: char = '/x10/x10';
+   |                  ^^^^^^^^^^
 help: if you meant to write a `str` literal, use double quotes
    |
-LL |     "/x10/x10"  //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^^^^^^^
+LL | static c: char = "/x10/x10";
+   |                  ^^^^^^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/lex-bad-char-literals-5.rs:4:5
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-5.rs:5:20
    |
-LL |     '/x10/x10'  //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^^^^^^^ expected char, found reference
+LL |     let ch: &str = '/x10/x10';
+   |                    ^^^^^^^^^^
+help: if you meant to write a `str` literal, use double quotes
    |
-   = note: expected type `char`
-              found type `&'static str`
+LL |     let ch: &str = "/x10/x10";
+   |                    ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.rs b/src/test/ui/parser/lex-bad-char-literals-6.rs
new file mode 100644 (file)
index 0000000..4379b4f
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {
+    let x: &str = 'ab';
+    //~^ ERROR: character literal may only contain one codepoint
+    let y: char = 'cd';
+    //~^ ERROR: character literal may only contain one codepoint
+    let z = 'ef';
+    //~^ ERROR: character literal may only contain one codepoint
+
+    if x == y {}
+    //~^ ERROR: can't compare `&str` with `char`
+    if y == z {}  // no error here
+    if x == z {}
+    //~^ ERROR: can't compare `&str` with `char`
+
+    let a: usize = "";
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr
new file mode 100644 (file)
index 0000000..df99726
--- /dev/null
@@ -0,0 +1,47 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:2:19
+   |
+LL |     let x: &str = 'ab';
+   |                   ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:4:19
+   |
+LL |     let y: char = 'cd';
+   |                   ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:6:13
+   |
+LL |     let z = 'ef';
+   |             ^^^^
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:9:10
+   |
+LL |     if x == y {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/lex-bad-char-literals-6.rs:15:20
+   |
+LL |     let a: usize = "";
+   |                    ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:12:10
+   |
+LL |     if x == z {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
index 57cbe8d5be655c735e3aed2d772b8feb495859b0..2c1e152dcee750ceb10b086d0428453405c048e1 100644 (file)
@@ -5,7 +5,6 @@ struct S {
     }
 
     let a = S { foo: (), bar: () };
-    let b = S { foo: () with a };
+    let b = S { foo: () with a, bar: () };
     //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
-    //~| ERROR missing field `bar` in initializer of `main::S`
 }
index 77ed4fcea517cca12e5611905c5d5fdae09392e3..a157873916a649779a6bf94b8ee84ebc692bb4d9 100644 (file)
@@ -1,15 +1,10 @@
 error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
   --> $DIR/removed-syntax-with-1.rs:8:25
    |
-LL |     let b = S { foo: () with a };
-   |                         ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+LL |     let b = S { foo: () with a, bar: () };
+   |             -           ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+   |             |
+   |             while parsing this struct
 
-error[E0063]: missing field `bar` in initializer of `main::S`
-  --> $DIR/removed-syntax-with-1.rs:8:13
-   |
-LL |     let b = S { foo: () with a };
-   |             ^ missing `bar`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0063`.
index 11db391c5489a711591e1620398ba35172eff57b..f666da49696ba6499a352052288992918b6d225b 100644 (file)
@@ -7,6 +7,5 @@ struct S {
     let a = S { foo: (), bar: () };
     let b = S { foo: (), with a };
     //~^ ERROR expected one of `,` or `}`, found `a`
-    //~| ERROR cannot find value `with` in this scope
-    //~| ERROR struct `main::S` has no field named `with`
+    //~| ERROR missing field `bar` in initializer of `main::S`
 }
index 5642d2f45ffce7a6ba73b7330f625147cb852163..7717b49d3a2c7d443c98770a5a28208776a80018 100644 (file)
@@ -2,23 +2,16 @@ error: expected one of `,` or `}`, found `a`
   --> $DIR/removed-syntax-with-2.rs:8:31
    |
 LL |     let b = S { foo: (), with a };
-   |                               ^ expected one of `,` or `}` here
+   |             -                 ^ expected one of `,` or `}` here
+   |             |
+   |             while parsing this struct
 
-error[E0425]: cannot find value `with` in this scope
-  --> $DIR/removed-syntax-with-2.rs:8:26
+error[E0063]: missing field `bar` in initializer of `main::S`
+  --> $DIR/removed-syntax-with-2.rs:8:13
    |
 LL |     let b = S { foo: (), with a };
-   |                          ^^^^ not found in this scope
+   |             ^ missing `bar`
 
-error[E0560]: struct `main::S` has no field named `with`
-  --> $DIR/removed-syntax-with-2.rs:8:26
-   |
-LL |     let b = S { foo: (), with a };
-   |                          ^^^^ `main::S` does not have this field
-   |
-   = note: available fields are: `foo`, `bar`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0425, E0560.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0063`.
index 914588f51e1e384bbd35f62a89ba546d6b78db14..58c40b3d96a4973af4ccf42bccd710f69345900a 100644 (file)
@@ -1,6 +1,9 @@
 struct Rgb(u8, u8, u8);
 
 fn main() {
-    let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
-                             //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
+    let _ = Rgb { 0, 1, 2 };
+    //~^ ERROR expected identifier, found `0`
+    //~| ERROR expected identifier, found `1`
+    //~| ERROR expected identifier, found `2`
+    //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
 }
index f5dc226934ec68f1a748aab792cf1a3199aba28d..cfb1f8201475469697bf279cf7b945673ec5cfb1 100644 (file)
@@ -1,17 +1,33 @@
 error: expected identifier, found `0`
   --> $DIR/struct-field-numeric-shorthand.rs:4:19
    |
-LL |     let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
+LL |     let _ = Rgb { 0, 1, 2 };
    |             ---   ^ expected identifier
    |             |
    |             while parsing this struct
 
+error: expected identifier, found `1`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:22
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---      ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `2`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:25
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---         ^ expected identifier
+   |             |
+   |             while parsing this struct
+
 error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
   --> $DIR/struct-field-numeric-shorthand.rs:4:13
    |
-LL |     let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
+LL |     let _ = Rgb { 0, 1, 2 };
    |             ^^^ missing `0`, `1`, `2`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0063`.
index e68e1f3204ade3ddda417895a08fec1c109de476..2183c74da0acbf43c92ff13a7d0be5f3a9300ea2 100644 (file)
@@ -1,20 +1,20 @@
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:13:8
+  --> $DIR/type-parameters-in-field-exprs.rs:13:10
    |
 LL |     f.x::<isize>;
-   |        ^^^^^^^^^
+   |          ^^^^^^^
 
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:15:8
+  --> $DIR/type-parameters-in-field-exprs.rs:15:10
    |
 LL |     f.x::<>;
-   |        ^^^^
+   |          ^^
 
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:17:8
+  --> $DIR/type-parameters-in-field-exprs.rs:17:10
    |
 LL |     f.x::();
-   |        ^^^^
+   |          ^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
new file mode 100644 (file)
index 0000000..50f1fe8
--- /dev/null
@@ -0,0 +1,17 @@
+fn unrelated() -> Result<(), std::string::ParseError> {  // #57664
+    let x = 0;
+
+    match x {
+        1 => {
+            let property_value_as_string = "a".parse()?;
+        }
+        2 => {
+            let value: &bool = unsafe { &42 };
+            //~^ ERROR mismatched types
+        }
+    };
+
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
new file mode 100644 (file)
index 0000000..edaa60e
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
+   |
+LL |             let value: &bool = unsafe { &42 };
+   |                                         ^^^ expected bool, found integer
+   |
+   = note: expected type `&bool`
+              found type `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
new file mode 100644 (file)
index 0000000..95b4036
--- /dev/null
@@ -0,0 +1,36 @@
+fn foo() -> impl std::fmt::Display {
+    if false {
+        return 0i32;
+    }
+    1u32
+    //~^ ERROR mismatched types
+}
+
+fn bar() -> impl std::fmt::Display {
+    if false {
+        return 0i32;
+    } else {
+        return 1u32;
+        //~^ ERROR mismatched types
+    }
+}
+
+fn baz() -> impl std::fmt::Display {
+    if false {
+    //~^ ERROR mismatched types
+        return 0i32;
+    } else {
+        1u32
+    }
+}
+
+fn qux() -> impl std::fmt::Display {
+    if false {
+        0i32
+    } else {
+        1u32
+        //~^ ERROR if and else have incompatible types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
new file mode 100644 (file)
index 0000000..5ebe00e
--- /dev/null
@@ -0,0 +1,66 @@
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
+   |
+LL | fn foo() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
+LL |         return 0i32;
+   |                ---- ...is found to be `i32` here
+LL |     }
+LL |     1u32
+   |     ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
+   |
+LL | fn bar() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
+LL |         return 0i32;
+   |                ---- ...is found to be `i32` here
+LL |     } else {
+LL |         return 1u32;
+   |                ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
+   |
+LL |   fn baz() -> impl std::fmt::Display {
+   |               ---------------------- expected because this return type...
+LL | /     if false {
+LL | |     //~^ ERROR mismatched types
+LL | |         return 0i32;
+   | |                ---- ...is found to be `i32` here
+LL | |     } else {
+LL | |         1u32
+LL | |     }
+   | |_____^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
+   |
+LL | /     if false {
+LL | |         0i32
+   | |         ---- expected because of this
+LL | |     } else {
+LL | |         1u32
+   | |         ^^^^ expected i32, found u32
+LL | |         //~^ ERROR if and else have incompatible types
+LL | |     }
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index c6e86ed64ae7311d3ab67981d4a06a599c11cc7d..81d23959fd4adc4256aef2b7fe7ab3e273c7ea8e 100644 (file)
@@ -1,7 +1,7 @@
 // Private types and traits are not allowed in interfaces of associated types.
 // This test also ensures that the checks are performed even inside private modules.
 
-#![feature(associated_type_defaults)]
+#![feature(associated_type_defaults, existential_type)]
 
 mod m {
     struct Priv;
@@ -23,10 +23,17 @@ pub trait PubTr {
 
         type Alias4 = Priv;
         //~^ ERROR private type `m::Priv` in public interface
+
+        type Exist;
+        fn infer_exist() -> Self::Exist;
     }
     impl PubTr for u8 {
         type Alias1 = Priv;
         //~^ ERROR private type `m::Priv` in public interface
+
+        existential type Exist: PrivTr;
+        //~^ ERROR private trait `m::PrivTr` in public interface
+        fn infer_exist() -> Self::Exist { Priv }
     }
 }
 
index 6740277c9a7c1091da1cfa25babac5ab24975f8c..0e5dab1a08c37083024ea26fc8b286c04730a7df 100644 (file)
@@ -6,7 +6,7 @@ LL | |         //~^ WARN private trait `m::PrivTr` in public interface
 LL | |         //~| WARN this was previously accepted
 LL | |         //~| WARN private type `m::Priv` in public interface
 ...  |
-LL | |         //~^ ERROR private type `m::Priv` in public interface
+LL | |         fn infer_exist() -> Self::Exist;
 LL | |     }
    | |_____^
    |
@@ -22,7 +22,7 @@ LL | |         //~^ WARN private trait `m::PrivTr` in public interface
 LL | |         //~| WARN this was previously accepted
 LL | |         //~| WARN private type `m::Priv` in public interface
 ...  |
-LL | |         //~^ ERROR private type `m::Priv` in public interface
+LL | |         fn infer_exist() -> Self::Exist;
 LL | |     }
    | |_____^
    |
@@ -39,7 +39,7 @@ LL |         type Alias4 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:28:9
+  --> $DIR/private-in-public-assoc-ty.rs:31:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -47,6 +47,16 @@ LL |     struct Priv;
 LL |         type Alias1 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
-error: aborting due to 2 previous errors
+error[E0445]: private trait `m::PrivTr` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
+   |
+LL |     trait PrivTr {}
+   |     - `m::PrivTr` declared as private
+...
+LL |         existential type Exist: PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0446`.
+Some errors occurred: E0445, E0446.
+For more information about an error, try `rustc --explain E0445`.
index 95658f45df6f5509db8f1f3f10a7362762670388..61c6130e47019550cdba73b0dc163f41073446d4 100644 (file)
@@ -12,4 +12,14 @@ fn check() -> Pub {
     Priv
 }
 
+pub trait Trait {
+    type Pub: Default;
+    fn method() -> Self::Pub;
+}
+
+impl Trait for u8 {
+    existential type Pub: Default;
+    fn method() -> Self::Pub { Priv }
+}
+
 fn main() {}
index 1f9103a6d2ee8d7a6234f4e09cd6919715850539..db524907b656f4760625c69c1cd1583bf8b52757 100644 (file)
@@ -15,6 +15,9 @@ LL |     let x: usize = "hello";;;;; //~ ERROR mismatched types
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:19:29
    |
+LL | fn b(x: Option<isize>) -> usize {
+   |                           ----- expected `usize` because of return type
+LL |     match x {
 LL |         Some(x) => { return x }, //~ ERROR mismatched types
    |                             ^ expected usize, found isize
 
diff --git a/src/test/ui/quote-with-interpolated.rs b/src/test/ui/quote-with-interpolated.rs
deleted file mode 100644 (file)
index b948226..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(quote)]
-fn main() {
-    macro_rules! foo {
-        ($bar:expr)  => {
-            quote_expr!(cx, $bar)
-            //~^ ERROR quote! with interpolated token
-            //~| ERROR failed to resolve: maybe a missing `extern crate syntax;`?
-            //~| ERROR failed to resolve: maybe a missing `extern crate syntax;`?
-            //~| ERROR cannot find value `cx` in this scope
-            //~| ERROR cannot find function `new_parser_from_tts` in this scope
-        }
-    }
-    foo!(bar);
-}
diff --git a/src/test/ui/quote-with-interpolated.stderr b/src/test/ui/quote-with-interpolated.stderr
deleted file mode 100644 (file)
index 96feff9..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-error: quote! with interpolated token
-  --> $DIR/quote-with-interpolated.rs:5:29
-   |
-LL |             quote_expr!(cx, $bar)
-   |                             ^^^^
-...
-LL |     foo!(bar);
-   |     ---------- in this macro invocation
-
-error[E0433]: failed to resolve: maybe a missing `extern crate syntax;`?
-  --> $DIR/quote-with-interpolated.rs:5:13
-   |
-LL |             quote_expr!(cx, $bar)
-   |             ^^^^^^^^^^^^^^^^^^^^^ maybe a missing `extern crate syntax;`?
-
-error[E0433]: failed to resolve: maybe a missing `extern crate syntax;`?
-  --> $DIR/quote-with-interpolated.rs:5:29
-   |
-LL |             quote_expr!(cx, $bar)
-   |                             ^^^^ maybe a missing `extern crate syntax;`?
-
-error[E0425]: cannot find value `cx` in this scope
-  --> $DIR/quote-with-interpolated.rs:5:25
-   |
-LL |             quote_expr!(cx, $bar)
-   |                         ^^ not found in this scope
-...
-LL |     foo!(bar);
-   |     ---------- in this macro invocation
-
-error[E0425]: cannot find function `new_parser_from_tts` in this scope
-  --> $DIR/quote-with-interpolated.rs:5:13
-   |
-LL |             quote_expr!(cx, $bar)
-   |             ^^^^^^^^^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to 5 previous errors
-
-Some errors occurred: E0425, E0433.
-For more information about an error, try `rustc --explain E0425`.
index 7c00461c900a2aca2d2454be412ff80c0c44739a..bef8dcca921e61a2b20b9cfe3c62af8e46bde921 100644 (file)
@@ -1,22 +1,22 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/ref-suggestion.rs:4:5
    |
+LL |     let x = vec![1];
+   |         - move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 LL |     let y = x;
    |             - value moved here
 LL |     x; //~ ERROR use of moved value
    |     ^ value used here after move
-   |
-   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `x`
   --> $DIR/ref-suggestion.rs:8:5
    |
+LL |     let x = vec![1];
+   |         - move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 LL |     let mut y = x;
    |                 - value moved here
 LL |     x; //~ ERROR use of moved value
    |     ^ value used here after move
-   |
-   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `x`
   --> $DIR/ref-suggestion.rs:16:5
index c84dd1953a07bc8561cfb24f9b4b3e53505c94d2..2862ae641df15b3341c6700cfd3f786e08a6a687 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/return-from-diverging.rs:4:12
    |
+LL | fn fail() -> ! {
+   |              - expected `!` because of return type
 LL |     return "wow"; //~ ERROR mismatched types
    |            ^^^^^ expected !, found reference
    |
index 0b3f59fd7e452fb569dc4db4276fe6554550dbc0..5a730ad2be42c67bd8d8994949990bd5f2686baf 100644 (file)
@@ -1,12 +1,13 @@
 error[E0382]: use of moved value: `a`
   --> $DIR/dbg-macro-move-semantics.rs:9:18
    |
+LL |     let a = NoCopy(0);
+   |         - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
 LL |     let _ = dbg!(a);
    |             ------- value moved here
 LL |     let _ = dbg!(a); //~ ERROR use of moved value
    |                  ^ value used here after move
    |
-   = note: move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
new file mode 100644 (file)
index 0000000..931ee9d
--- /dev/null
@@ -0,0 +1,90 @@
+// Test that the simd_bitmask intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x2(pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x8(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x16(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x32(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x64(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+fn main() {
+    let m2 = u32x2(0, 0);
+    let m4 = u32x4(0, 0, 0, 0);
+    let m8 = u8x8(0, 0, 0, 0, 0, 0, 0, 0);
+    let m16 = u8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    let m32 = u8x32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    let m64 = u8x64(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+    unsafe {
+        let _: u8 = simd_bitmask(m2);
+        let _: u8 = simd_bitmask(m4);
+        let _: u8 = simd_bitmask(m8);
+        let _: u16 = simd_bitmask(m16);
+        let _: u32 = simd_bitmask(m32);
+        let _: u64 = simd_bitmask(m64);
+
+        let _: u16 = simd_bitmask(m2);
+        //~^ ERROR bitmask `u16`, expected `u8`
+
+        let _: u16 = simd_bitmask(m8);
+        //~^ ERROR bitmask `u16`, expected `u8`
+
+        let _: u32 = simd_bitmask(m16);
+        //~^ ERROR bitmask `u32`, expected `u16`
+
+        let _: u64 = simd_bitmask(m32);
+        //~^ ERROR bitmask `u64`, expected `u32`
+
+        let _: u128 = simd_bitmask(m64);
+        //~^ ERROR bitmask `u128`, expected `u64`
+
+   }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
new file mode 100644 (file)
index 0000000..d016838
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:74:22
+   |
+LL |         let _: u16 = simd_bitmask(m2);
+   |                      ^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:77:22
+   |
+LL |         let _: u16 = simd_bitmask(m8);
+   |                      ^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:80:22
+   |
+LL |         let _: u32 = simd_bitmask(m16);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:83:22
+   |
+LL |         let _: u64 = simd_bitmask(m32);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:86:23
+   |
+LL |         let _: u128 = simd_bitmask(m64);
+   |                       ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
index 23fdde06e8f9dd473a79e25b9c908f8c4edafbf1..965ca7000be80f7d9e805b2838dbb7e7051951f6 100644 (file)
@@ -1,14 +1,14 @@
 error: generic arguments in macro path
-  --> $DIR/macro-ty-params.rs:10:8
+  --> $DIR/macro-ty-params.rs:10:10
    |
 LL |     foo::<T>!(); //~ ERROR generic arguments in macro path
-   |        ^^^^^
+   |          ^^^
 
 error: generic arguments in macro path
-  --> $DIR/macro-ty-params.rs:11:8
+  --> $DIR/macro-ty-params.rs:11:10
    |
 LL |     foo::<>!(); //~ ERROR generic arguments in macro path
-   |        ^^^^
+   |          ^^
 
 error: unexpected generic arguments in path
   --> $DIR/macro-ty-params.rs:12:8
index 9d4297b55c81643537d88de6b7fd110343244c0e..accead5c850cca8906988432f19a83c12ceebd2e 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
 fn main() {
-    println!("●●");
-    //~^ ERROR character literal may only contain one codepoint
+    println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint
+    //~^ ERROR format argument must be a string literal
 }
index 710fa74a32a1cc46ea9e5bdb6369021025ccd962..fb179ec7245d2db4e48909399b9141c83eb61dca 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
 fn main() {
-    println!('●●');
-    //~^ ERROR character literal may only contain one codepoint
+    println!('●●'); //~ ERROR character literal may only contain one codepoint
+    //~^ ERROR format argument must be a string literal
 }
index 540a1b55376ff393a8f298775d433ba393a23ca8..4ca430a4cde9b0ddc15b6f4883e6692875a29f49 100644 (file)
@@ -1,12 +1,22 @@
 error: character literal may only contain one codepoint
   --> $DIR/str-as-char.rs:4:14
    |
-LL |     println!('●●');
+LL |     println!('●●'); //~ ERROR character literal may only contain one codepoint
    |              ^^^^
 help: if you meant to write a `str` literal, use double quotes
    |
-LL |     println!("●●");
+LL |     println!("●●"); //~ ERROR character literal may only contain one codepoint
    |              ^^^^
 
-error: aborting due to previous error
+error: format argument must be a string literal
+  --> $DIR/str-as-char.rs:4:14
+   |
+LL |     println!('●●'); //~ ERROR character literal may only contain one codepoint
+   |              ^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{}", '●●'); //~ ERROR character literal may only contain one codepoint
+   |              ^^^^^
+
+error: aborting due to 2 previous errors
 
index 2ea80494e03cbadb4b0d940edd27f59617804aac..1b32ed5533d35279bb086b1851e65477c3610a98 100644 (file)
@@ -1,4 +1,7 @@
 pub fn main() {
     let s: &str = "hello";
-    let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
 }
index 71b1747492329a8ecf060f98e744bb5a0ef8f5c2..99df85d92fd9662085e4d7d76bd2e2e340ae849e 100644 (file)
@@ -1,13 +1,43 @@
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:3:17
    |
-LL |     let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
-   |                 ^^^^ `str` cannot be indexed by `{integer}`
+LL |     let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |                 ^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `std::ops::Index<{integer}>` is not implemented for `str`
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+   = note: required because of the requirements on the impl of `std::ops::Index<{integer}>` for `str`
 
-error: aborting due to previous error
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:4:15
+   |
+LL |     let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |               ^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:5:15
+   |
+LL |     let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |               ^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-idx.rs:6:17
+   |
+LL |     let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
+   |                 ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index cebbbc3ccbf7dd18f91355f8627fa7cc3307974b..575a9eae859465788d447044a07034685e21434d 100644 (file)
@@ -5,7 +5,13 @@ fn mutate(s: &mut str) {
     //~^ ERROR the size for values of type
     //~| ERROR the size for values of type
     s[1usize] = bot();
-    //~^ ERROR the type `str` cannot be mutably indexed by `usize`
+    //~^ ERROR the type `str` cannot be indexed by `usize`
+    s.get_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s.get_unchecked_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s['c'];
+    //~^ ERROR the type `str` cannot be indexed by `char`
 }
 
 pub fn main() {}
index a1212c5a4fe10c1d7787bf624519515700ffac71..beb227245236343c7e7fcfc0b5c06bf22f48a17c 100644 (file)
@@ -22,16 +22,44 @@ LL |     s[1..2] = bot();
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: the left-hand-side of an assignment must have a statically known size
 
-error[E0277]: the type `str` cannot be mutably indexed by `usize`
+error[E0277]: the type `str` cannot be indexed by `usize`
   --> $DIR/str-mut-idx.rs:7:5
    |
 LL |     s[1usize] = bot();
-   |     ^^^^^^^^^ `str` cannot be mutably indexed by `usize`
+   |     ^^^^^^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `std::ops::IndexMut<usize>` is not implemented for `str`
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `usize`
+   = note: required because of the requirements on the impl of `std::ops::Index<usize>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:9:7
+   |
+LL |     s.get_mut(1);
+   |       ^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
-error: aborting due to 3 previous errors
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:11:7
+   |
+LL |     s.get_unchecked_mut(1);
+   |       ^^^^^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-mut-idx.rs:13:5
+   |
+LL |     s['c'];
+   |     ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/recover-invalid-float.rs b/src/test/ui/suggestions/recover-invalid-float.rs
new file mode 100644 (file)
index 0000000..506ef89
--- /dev/null
@@ -0,0 +1,11 @@
+fn main() {
+    let _: usize = .3;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+    let _: usize = .42f32;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+    let _: usize = .5f64;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/recover-invalid-float.stderr b/src/test/ui/suggestions/recover-invalid-float.stderr
new file mode 100644 (file)
index 0000000..c464676
--- /dev/null
@@ -0,0 +1,42 @@
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:2:20
+   |
+LL |     let _: usize = .3;
+   |                    ^^ help: must have an integer part: `0.3`
+
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:5:20
+   |
+LL |     let _: usize = .42f32;
+   |                    ^^^^^^ help: must have an integer part: `0.42f32`
+
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:8:20
+   |
+LL |     let _: usize = .5f64;
+   |                    ^^^^^ help: must have an integer part: `0.5f64`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:2:20
+   |
+LL |     let _: usize = .3;
+   |                    ^^ expected usize, found floating-point number
+   |
+   = note: expected type `usize`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:5:20
+   |
+LL |     let _: usize = .42f32;
+   |                    ^^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:8:20
+   |
+LL |     let _: usize = .5f64;
+   |                    ^^^^^ expected usize, found f64
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 39d96a943a18afde3686946bd81a3d45d8d07c5b..b7727cf03a4e7e50c3f8414199e8dfec85788453 100644 (file)
@@ -5,25 +5,19 @@ LL | struct Foo;
    | ----------- method `bat` not found for this
 ...
 LL |     f.bat(1.0); //~ ERROR no method named
-   |       ^^^
-   |
-   = help: did you mean `bar`?
+   |       ^^^ help: did you mean: `bar`
 
 error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy(); //~ ERROR no method named
-   |               ^^^^^^^^
-   |
-   = help: did you mean `is_empty`?
+   |               ^^^^^^^^ help: did you mean: `is_empty`
 
 error[E0599]: no method named `count_eos` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:25:19
    |
 LL |     let _ = 63u32.count_eos(); //~ ERROR no method named
-   |                   ^^^^^^^^^
-   |
-   = help: did you mean `count_zeros`?
+   |                   ^^^^^^^^^ help: did you mean: `count_zeros`
 
 error[E0599]: no method named `count_o` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:28:19
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
new file mode 100644 (file)
index 0000000..2ce1222
--- /dev/null
@@ -0,0 +1,9 @@
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+    let (r, g, c): (f32, f32, f32) = (0., 0., 0.);
+    let _ = RGB { r, g, c };
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR struct `RGB` has no field named `c`
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
new file mode 100644 (file)
index 0000000..d0f9e1f
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
+   |
+LL |     let _ = RGB { r, g, c };
+   |                   ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r: r.into(), g, c };
+   |                   ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
+   |
+LL |     let _ = RGB { r, g, c };
+   |                      ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r, g: g.into(), c };
+   |                      ^^^^^^^^^^^
+
+error[E0560]: struct `RGB` has no field named `c`
+  --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
+   |
+LL |     let _ = RGB { r, g, c };
+   |                         ^ help: a field with a similar name exists: `b`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0560.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
new file mode 100644 (file)
index 0000000..91758c0
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+    let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+    let _ = RGB { r: r.into(), g: g.into(), b: b.into() };
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs
new file mode 100644 (file)
index 0000000..9d3a17a
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+    let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+    let _ = RGB { r, g, b };
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
new file mode 100644 (file)
index 0000000..6bc16ba
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
+   |
+LL |     let _ = RGB { r, g, b };
+   |                   ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r: r.into(), g, b };
+   |                   ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
+   |
+LL |     let _ = RGB { r, g, b };
+   |                      ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r, g: g.into(), b };
+   |                      ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
+   |
+LL |     let _ = RGB { r, g, b };
+   |                         ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r, g, b: b.into() };
+   |                         ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index eadf3d6d3350e35a6be3a07365ebb5cd8cd2ad05..1170f5c17c18ab648658a716562dec311259ef48 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/tail-typeck.rs:3:26
    |
 LL | fn f() -> isize { return g(); }
-   |                          ^^^ expected isize, found usize
+   |           -----          ^^^ expected isize, found usize
+   |           |
+   |           expected `isize` because of return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/auxiliary/trait_alias.rs
new file mode 100644 (file)
index 0000000..9e56b87
--- /dev/null
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SendSync = Send + Sync;
diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias-cross-crate.rs
new file mode 100644 (file)
index 0000000..259fc4f
--- /dev/null
@@ -0,0 +1,17 @@
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+use std::rc::Rc;
+use trait_alias::SendSync;
+
+fn use_alias<T: SendSync>() {}
+
+fn main() {
+    use_alias::<u32>();
+    use_alias::<Rc<u32>>();
+    //~^ ERROR `std::rc::Rc<u32>` cannot be sent between threads safely [E0277]
+    //~^^ ERROR `std::rc::Rc<u32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias-cross-crate.stderr
new file mode 100644 (file)
index 0000000..972d213
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0277]: `std::rc::Rc<u32>` cannot be sent between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<u32>` cannot be shared between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 523211fea9368e16ede7265d85f822fa4b389051..6254157e25da3eb960bfbbae82f677d0546a7fbb 100644 (file)
@@ -1,5 +1,4 @@
 // compile-pass
-#![feature(get_type_id)]
 #![allow(dead_code)]
 mod foo {
     pub use self::bar::T;
@@ -18,7 +17,7 @@ fn g() {
 
 fn f() {
     let error = ::std::thread::spawn(|| {}).join().unwrap_err();
-    error.get_type_id(); // Regression test for #21670
+    error.type_id(); // Regression test for #21670
 }
 
 
index 5bb0b099b977bacb0f67ea3f4338a7e93e26cf9f..b1b925d694ff9ba8e1acc6115425978cb989543f 100644 (file)
@@ -25,13 +25,14 @@ LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
 error[E0382]: use of moved value: `k`
   --> $DIR/try-block-bad-lifetime.rs:31:26
    |
+LL |         let k = &mut i;
+   |             - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
+LL |         let mut j: Result<(), &mut i32> = try {
 LL |             Err(k) ?;
    |                 - value moved here
 ...
 LL |         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
    |                          ^ value used here after move
-   |
-   = note: move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
 
 error[E0506]: cannot assign to `i` because it is borrowed
   --> $DIR/try-block-bad-lifetime.rs:32:9
index 202885e383ece1dbf94b4605c3b7473f2844a979..df8e646280c9a5d8e0092ff03bdee0401fe9339f 100644 (file)
@@ -6,10 +6,10 @@ LL |         Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>`
    |
    = help: the following implementations were found:
              <i32 as std::convert::From<bool>>
+             <i32 as std::convert::From<core::num::NonZeroI32>>
              <i32 as std::convert::From<i16>>
              <i32 as std::convert::From<i8>>
-             <i32 as std::convert::From<u16>>
-             <i32 as std::convert::From<u8>>
+           and 2 others
    = note: required by `std::convert::From::from`
 
 error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == &str`
index f96c7146d18d07d3292b53780891e595cdb53f8d..dafbde6a5150bb461bcd861f1356e8acb958a802 100644 (file)
@@ -13,13 +13,14 @@ LL |         do_something_with(x);
 error[E0382]: borrow of moved value: `x`
   --> $DIR/try-block-maybe-bad-lifetime.rs:28:24
    |
+LL |         let x = String::new();
+   |             - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
 LL |             ::std::mem::drop(x);
    |                              - value moved here
 LL |         };
 LL |         println!("{}", x); //~ ERROR borrow of moved value: `x`
    |                        ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0506]: cannot assign to `i` because it is borrowed
   --> $DIR/try-block-maybe-bad-lifetime.rs:40:9
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs
new file mode 100644 (file)
index 0000000..0a4e7da
--- /dev/null
@@ -0,0 +1,7 @@
+//extern crate has_assoc_type;
+
+//fn ice(x: Box<dyn has_assoc_type::Foo<Assoc=()>>) {
+fn ice(x: Box<dyn Iterator<Item=()>>) {
+    *x //~ ERROR mismatched types [E0308]
+}
+fn main() {}
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
new file mode 100644 (file)
index 0000000..bb63917
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5
+   |
+LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
+   |                                       - possibly return type missing here?
+LL |     *x //~ ERROR mismatched types [E0308]
+   |     ^^ expected (), found trait std::iter::Iterator
+   |
+   = note: expected type `()`
+              found type `(dyn std::iter::Iterator<Item=()> + 'static)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index 5387dcb218cb92e5cf90af8b21a968b75fb89676..c96a6fa8b6c91b2942840cc765e3d0e3635c6132 100644 (file)
@@ -6,7 +6,8 @@ struct Bar<A> {
 
 fn bar() {
     let x: Box<Bar()> = panic!();
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| ERROR wrong number of type arguments: expected 1, found 0
 }
 
 fn main() { }
index 3f1b37c282b7c53f7ddc339b2d58d01ac4a78280..fa52e66fb03495495e075d746e03fbf6f9c6ea4f 100644 (file)
@@ -1,9 +1,16 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:19
    |
 LL |     let x: Box<Bar()> = panic!();
-   |                   ^^ only traits may use parentheses
+   |                   ^^ only `Fn` traits may use parentheses
 
-error: aborting due to previous error
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16
+   |
+LL |     let x: Box<Bar()> = panic!();
+   |                ^^^^^ expected 1 type argument
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0214`.
+Some errors occurred: E0107, E0214.
+For more information about an error, try `rustc --explain E0107`.
index 3cada322b1ef2618feb4ac062260b7782214c3b5..79ced1ecfb1a04734b4825a2afa6f79356cf76d5 100644 (file)
@@ -12,7 +12,7 @@ fn bar() {
     let b = Bar::<isize, usize>::new(); // OK
 
     let b = Bar::(isize, usize)::new(); // OK too (for the parser)
-    //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
 }
 
 fn main() {}
index 395f6596cfd838987fb9757950c3b2a511876864..7d05ca55ffdb0bec1d39d2a0a88ead18b691dc2a 100644 (file)
@@ -1,8 +1,11 @@
-error[E0214]: parenthesized parameters may only be used with a trait
-  --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:16
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:18
    |
 LL |     let b = Bar::(isize, usize)::new(); // OK too (for the parser)
-   |                ^^^^^^^^^^^^^^^^ only traits may use parentheses
+   |                  ^^^^^^^^^^^^^^
+   |                  |
+   |                  only `Fn` traits may use parentheses
+   |                  help: use angle brackets instead: `<isize, usize>`
 
 error: aborting due to previous error
 
index e795650447cc40b643ecd9a997d997de47df2858..1af7f55674c6aa9c388533563b60ddac19084443 100644 (file)
@@ -5,8 +5,8 @@ struct Bar<A> {
 }
 
 fn foo(b: Box<Bar()>) {
-    //~^ ERROR parenthesized parameters may only be used with a trait
-    //~| ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| ERROR wrong number of type arguments: expected 1, found 0
 }
 
 fn main() { }
index d0267092030d8dc99721e9abf60ab34bdb362ecc..b34237937ee1cb0f28dbacebac9274770aa585d4 100644 (file)
@@ -1,16 +1,16 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:18
    |
 LL | fn foo(b: Box<Bar()>) {
-   |                  ^^ only traits may use parentheses
+   |                  ^^ only `Fn` traits may use parentheses
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15
    |
 LL | fn foo(b: Box<Bar()>) {
-   |               ^^^^^ not allowed in type signatures
+   |               ^^^^^ expected 1 type argument
 
 error: aborting due to 2 previous errors
 
-Some errors occurred: E0121, E0214.
-For more information about an error, try `rustc --explain E0121`.
+Some errors occurred: E0107, E0214.
+For more information about an error, try `rustc --explain E0107`.
index 848c3d9bdb017caf607aea607654a35ab57199be..29d161fe150e74b1fa856b6e8652161207327d53 100644 (file)
@@ -13,12 +13,12 @@ LL |     use_borrow(a);
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:22:13
    |
+LL |     let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
 LL |     let a = u.x.0;
    |             ----- value moved here
 LL |     let b = u.y; //~ ERROR use of moved value: `u.y`
    |             ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
   --> $DIR/union-borrow-move-parent-sibling.rs:28:13
@@ -35,12 +35,12 @@ LL |     use_borrow(a);
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:35:13
    |
+LL |     let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
 LL |     let a = (u.x.0).0;
    |             --------- value moved here
 LL |     let b = u.y; //~ ERROR use of moved value: `u.y`
    |             ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`)
   --> $DIR/union-borrow-move-parent-sibling.rs:41:13
@@ -57,12 +57,12 @@ LL |     use_borrow(a);
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:48:13
    |
+LL |     let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
 LL |     let a = *u.y;
    |             ---- value moved here
 LL |     let b = u.x; //~ ERROR use of moved value: `u.x`
    |             ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
 
 error: aborting due to 6 previous errors
 
index 333a4734a4e5f8924bf849efe4ba52051adda5d9..58953d55b1fbae40d7e1c903540c81f573843f4a 100644 (file)
@@ -1,13 +1,15 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/unop-move-semantics.rs:8:5
    |
+LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
+   |                     -                         - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                     |
+   |                     consider adding a `Copy` constraint to this type argument
 LL |     !x;
    |      - value moved here
 LL | 
 LL |     x.clone();  //~ ERROR: use of moved value
    |     ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait
 
 error[E0505]: cannot move out of `x` because it is borrowed
   --> $DIR/unop-move-semantics.rs:15:6
index 18cba2047356a18040dd5578278b489135e0e95f..0e6a6f6369a15f091dd93b15a782bf0ceb4f4ab3 100644 (file)
@@ -12,13 +12,13 @@ LL |         println!("{}", &x);
 error[E0382]: borrow of moved value: `y`
   --> $DIR/borrow-after-move.rs:22:24
    |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
 LL |         drop_unsized(y);
    |                      - value moved here
 ...
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
-   |
-   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/borrow-after-move.rs:30:24
@@ -34,13 +34,13 @@ LL |         println!("{}", &x);
 error[E0382]: borrow of moved value: `y`
   --> $DIR/borrow-after-move.rs:32:24
    |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
 LL |         y.foo();
    |         - value moved here
 ...
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
-   |
-   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/borrow-after-move.rs:39:24
index bbe6da70fb112aae7b26e345ead0d4136c43a0e7..e40289af5ad3d7487f5dc53f7105f4b6be83efdc 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `y`
   --> $DIR/double-move.rs:20:22
    |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
 LL |         drop_unsized(y);
    |                      - value moved here
 LL |         drop_unsized(y); //~ERROR use of moved value
    |                      ^ value used here after move
-   |
-   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `x`
   --> $DIR/double-move.rs:26:22
@@ -21,22 +21,22 @@ LL |         drop_unsized(x); //~ERROR use of moved value
 error[E0382]: use of moved value: `*x`
   --> $DIR/double-move.rs:32:18
    |
+LL |         let x = "hello".to_owned().into_boxed_str();
+   |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
 LL |         drop_unsized(x);
    |                      - value moved here
 LL |         let _y = *x; //~ERROR use of moved value
    |                  ^^ value used here after move
-   |
-   = note: move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `y`
   --> $DIR/double-move.rs:39:9
    |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
 LL |         y.foo();
    |         - value moved here
 LL |         y.foo(); //~ERROR use of moved value
    |         ^ value used here after move
-   |
-   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `*x`
   --> $DIR/double-move.rs:45:9
index 6f5b23b20133386201115404d2139fd690492cdd..8160ada9d62ea41d54136cb95d83d97a1a72a122 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: borrow of moved value: `x`
   --> $DIR/use-after-move-based-on-type.rs:4:20
    |
+LL |     let x = "Hello!".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 LL |     let _y = x;
    |              - value moved here
 LL |     println!("{}", x); //~ ERROR use of moved value
    |                    ^ value borrowed here after move
-   |
-   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 308134774efb39235080d3b3481544b8099a768b..e16bca380679f5e982b409844d063f86f766dec7 100644 (file)
@@ -1,12 +1,13 @@
 error[E0382]: borrow of moved value: `n`
   --> $DIR/use-after-move-implicity-coerced-object.rs:28:13
    |
+LL |     let n: Box<_> = box Number { n: 42 };
+   |         - move occurs because `n` has type `std::boxed::Box<Number>`, which does not implement the `Copy` trait
+LL |     let mut l: Box<_> = box List { list: Vec::new() };
 LL |     l.push(n);
    |            - value moved here
 LL |     let x = n.to_string();
    |             ^ value borrowed here after move
-   |
-   = note: move occurs because `n` has type `std::boxed::Box<Number>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index d7f7c3c30f6cd6206d7174a6ff754e2794b64674..4119741d805cd43b24f66975a099fdb8508ba6ee 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `self`
   --> $DIR/use-after-move-self-based-on-type.rs:12:16
    |
+LL |     pub fn foo(self) -> isize {
+   |                ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
 LL |         self.bar();
    |         ---- value moved here
 LL |         return self.x;  //~ ERROR use of moved value: `self.x`
    |                ^^^^^^ value used here after move
-   |
-   = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 3e11e94e993f5e8796b030b32a7ac418c05b174d..e2ce3690cb9046c89b0898fdfff7f4bdb6eb7e35 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `self`
   --> $DIR/use-after-move-self.rs:10:16
    |
+LL |     pub fn foo(self) -> isize {
+   |                ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
 LL |         self.bar();
    |         ---- value moved here
 LL |         return *self.x;  //~ ERROR use of moved value: `*self.x`
    |                ^^^^^^^ value used here after move
-   |
-   = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 22ad3b1e2f2e74ac90f8cc0a295648c4bd8ed523..2263747607b9c94243df3279e3e056992e64d697 100644 (file)
@@ -1,12 +1,12 @@
 error[E0382]: borrow of moved value: `start`
   --> $DIR/walk-struct-literal-with.rs:16:20
    |
+LL |     let start = Mine{test:"Foo".to_string(), other_val:0};
+   |         ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
 LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
    |                                   ----- value moved here
 LL |     println!("{}", start.test); //~ ERROR use of moved value: `start.test`
    |                    ^^^^^^^^^^ value borrowed here after move
-   |
-   = note: move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 221806f731f60ef4d1337acd6b614cd17de7c706..cf59f42683d721647c54a17bfcf7165d6730b5f0 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/wrong-ret-type.rs:2:49
    |
 LL | fn mk_int() -> usize { let i: isize = 3; return i; }
-   |                                                 ^ expected usize, found isize
+   |                -----                            ^ expected usize, found isize
+   |                |
+   |                expected `usize` because of return type
 
 error: aborting due to previous error
 
index 8c1baa55bcdcae2f6e57e480e57649791d87c151..4ca285b9b1db1fe6acc5f200184dee32c353ebd9 100644 (file)
@@ -95,6 +95,7 @@
     "wasm32-unknown-unknown",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
+    "x86_64-fortanix-unknown-sgx",
     "x86_64-fuchsia",
     "x86_64-linux-android",
     "x86_64-pc-windows-gnu",
index 2b4a5f1f0bb6e13759e88ea9512527b0beba154f..907c0febe7045fa02dff2a35c5e36d3bd59ea50d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2b4a5f1f0bb6e13759e88ea9512527b0beba154f
+Subproject commit 907c0febe7045fa02dff2a35c5e36d3bd59ea50d
index 1b89724b4889aef631b40d52c0943bdc28e04d1d..f1753522d8f3bb2d218266b4760f7a99f027f5ca 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 1b89724b4889aef631b40d52c0943bdc28e04d1d
+Subproject commit f1753522d8f3bb2d218266b4760f7a99f027f5ca
index 97f4cff8e904c268569d37922a27835209deff5d..1cd85d2a2767b37f9869b719a74e3da99087c31a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 97f4cff8e904c268569d37922a27835209deff5d
+Subproject commit 1cd85d2a2767b37f9869b719a74e3da99087c31a
index ae0d89a08d091ba1563b571739768a09d4cd3d69..c9d25b667af766e8fe6d3b6168a5f99a0e4d722a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ae0d89a08d091ba1563b571739768a09d4cd3d69
+Subproject commit c9d25b667af766e8fe6d3b6168a5f99a0e4d722a
index c4499ef95ad8e205fead99248059ac0329bc70a3..f5eeddda036fd3f5c8d61b1846e32845f68dd063 100644 (file)
@@ -45,6 +45,7 @@ features = [
   "sspi",
   "synchapi",
   "sysinfoapi",
+  "threadpoollegacyapiset",
   "timezoneapi",
   "userenv",
   "winbase",