]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #65838 - estebank:resilient-recovery, r=Centril
authorbors <bors@rust-lang.org>
Mon, 4 Nov 2019 02:30:45 +0000 (02:30 +0000)
committerbors <bors@rust-lang.org>
Mon, 4 Nov 2019 02:30:45 +0000 (02:30 +0000)
Reduce amount of errors given unclosed delimiter

When in a file with a non-terminated item, catch the error and consume
the block instead of trying to recover it on a more granular way in order to
reduce the amount of unrelated errors that would be fixed after adding
the missing closing brace. Also point out the possible location of the
missing closing brace.

Fix #63690.

318 files changed:
.gitmodules
Cargo.lock
src/bootstrap/configure.py
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/tool.rs
src/ci/azure-pipelines/auto.yml
src/ci/azure-pipelines/pr.yml
src/ci/azure-pipelines/steps/run.yml
src/ci/docker/dist-various-1/Dockerfile
src/ci/docker/run.sh
src/ci/docker/x86_64-gnu-tools/Dockerfile
src/ci/docker/x86_64-gnu-tools/checktools.sh
src/ci/scripts/install-msys2-packages.sh
src/ci/scripts/install-msys2.sh
src/ci/scripts/should-skip-this.sh [new file with mode: 0755]
src/ci/scripts/upload-artifacts.sh [new file with mode: 0755]
src/ci/shared.sh
src/doc/book
src/doc/reference
src/doc/rust-by-example
src/doc/rustdoc/src/documentation-tests.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/language-features/lang-items.md
src/liballoc/collections/binary_heap.rs
src/liballoc/tests/binary_heap.rs
src/liballoc/tests/lib.rs
src/libcore/ffi.rs
src/libcore/intrinsics.rs
src/libcore/iter/mod.rs
src/libcore/lib.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/ops/try.rs
src/libcore/ptr/mod.rs
src/libpanic_unwind/dwarf/eh.rs
src/libpanic_unwind/emcc.rs
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/seh.rs
src/libpanic_unwind/seh64_gnu.rs [deleted file]
src/libpanic_unwind/windows.rs [deleted file]
src/libproc_macro/bridge/client.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
src/librustc/infer/error_reporting/nice_region_error/mod.rs
src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs [new file with mode: 0644]
src/librustc/middle/cstore.rs
src/librustc/middle/lang_items.rs
src/librustc/query/mod.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/ty/context.rs
src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
src/librustc_codegen_llvm/debuginfo/mod.rs
src/librustc_codegen_llvm/debuginfo/source_loc.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/back/symbol_export.rs
src/librustc_codegen_ssa/debuginfo/mod.rs
src/librustc_codegen_ssa/mir/analyze.rs
src/librustc_codegen_ssa/mir/debuginfo.rs [new file with mode: 0644]
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/mir/place.rs
src/librustc_codegen_ssa/mir/statement.rs
src/librustc_codegen_ssa/traits/debuginfo.rs
src/librustc_data_structures/owning_ref/mod.rs
src/librustc_data_structures/sync.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/persist/fs.rs
src/librustc_incremental/persist/save.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check/prefixes.rs
src/librustc_mir/error_codes.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/util/graphviz.rs
src/librustc_mir/util/pretty.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/error_codes.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_target/spec/wasm32_unknown_emscripten.rs
src/librustc_typeck/check/intrinsic.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/static/main.js
src/librustdoc/passes/collect_intra_doc_links.rs
src/libstd/collections/hash/map.rs
src/libstd/ffi/mod.rs
src/libstd/fs.rs
src/libstd/sys/vxworks/ext/io.rs
src/libstd/sys/vxworks/ext/mod.rs
src/libstd/sys/vxworks/ext/net.rs [deleted file]
src/libsyntax/error_codes.rs
src/libsyntax/feature_gate/accepted.rs
src/libsyntax/feature_gate/active.rs
src/libsyntax/feature_gate/builtin_attrs.rs
src/libsyntax/feature_gate/check.rs
src/libsyntax/parse/parser/ty.rs
src/libsyntax_pos/symbol.rs
src/libtest/helpers/concurrency.rs
src/libtest/helpers/isatty.rs
src/libtest/lib.rs
src/libunwind/build.rs
src/libunwind/libunwind.rs
src/test/codegen/c-variadic.rs
src/test/codegen/drop.rs
src/test/codegen/optimize-attr-1.rs
src/test/codegen/personality_lifetimes.rs
src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
src/test/codegen/unwind-extern-exports.rs
src/test/codegen/unwind-extern-imports.rs
src/test/incremental/change_crate_dep_kind.rs
src/test/mir-opt/box_expr.rs
src/test/mir-opt/generator-storage-dead-unwind.rs
src/test/mir-opt/graphviz.rs
src/test/mir-opt/issue-41110.rs
src/test/mir-opt/issue-62289.rs
src/test/mir-opt/no-spurious-drop-after-call.rs
src/test/mir-opt/packed-struct-drop-aligned.rs
src/test/mir-opt/remove_fake_borrows.rs
src/test/mir-opt/retag.rs
src/test/run-make-fulldeps/foreign-exceptions/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/foreign-exceptions/foo.cpp [new file with mode: 0644]
src/test/run-make-fulldeps/foreign-exceptions/foo.rs [new file with mode: 0644]
src/test/run-make-fulldeps/issue-36710/Makefile
src/test/run-make-fulldeps/issue-36710/foo.rs
src/test/run-make-fulldeps/issue-64319/Makefile [deleted file]
src/test/run-make-fulldeps/issue-64319/bar.rs [deleted file]
src/test/run-make-fulldeps/issue-64319/foo.rs [deleted file]
src/test/run-make-fulldeps/symbol-visibility/Makefile
src/test/run-make-fulldeps/tools.mk
src/test/rustdoc-ui/cfg-test.rs
src/test/rustdoc-ui/cfg-test.stdout
src/test/rustdoc/cfg-doctest.rs
src/test/rustdoc/issue-55364.rs [new file with mode: 0644]
src/test/ui-fulldeps/lint-group-plugin.rs
src/test/ui-fulldeps/lint-plugin.rs
src/test/ui/abi/statics/static-mut-foreign.rs
src/test/ui/alignment-gep-tup-like-1.rs
src/test/ui/as-precedence.rs
src/test/ui/associated-type-bounds/type-alias.stderr
src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr
src/test/ui/associated-types/associated-types-eq-3.rs
src/test/ui/associated-types/associated-types-eq-3.stderr
src/test/ui/associated-types/associated-types-eq-hr.stderr
src/test/ui/associated-types/associated-types-issue-20346.stderr
src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr
src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
src/test/ui/async-await/try-on-option-in-async.rs [new file with mode: 0644]
src/test/ui/async-await/try-on-option-in-async.stderr [new file with mode: 0644]
src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
src/test/ui/builtin-clone-unwind.rs
src/test/ui/catch-unwind-bang.rs
src/test/ui/close-over-big-then-small-data.rs
src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
src/test/ui/const-generics/const-param-in-trait-ungated.stderr
src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
src/test/ui/const-generics/issues/issue-60263.stderr
src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs
src/test/ui/consts/offset_from.rs [new file with mode: 0644]
src/test/ui/consts/offset_from_ub.rs [new file with mode: 0644]
src/test/ui/consts/offset_from_ub.stderr [new file with mode: 0644]
src/test/ui/continue-after-missing-main.nll.stderr
src/test/ui/continue-after-missing-main.rs
src/test/ui/continue-after-missing-main.stderr
src/test/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs [new file with mode: 0644]
src/test/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs [new file with mode: 0644]
src/test/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs [new file with mode: 0644]
src/test/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs [new file with mode: 0644]
src/test/ui/cross-crate/issue-64872/issue-64872.rs [new file with mode: 0644]
src/test/ui/derive-uninhabited-enum-38885.rs
src/test/ui/drop/dynamic-drop-async.rs
src/test/ui/drop/dynamic-drop.rs
src/test/ui/error-codes/E0271.stderr
src/test/ui/feature-gate/feature-gate-cfg_doctest.rs [deleted file]
src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr [deleted file]
src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
src/test/ui/feature-gates/feature-gate-box_patterns.rs
src/test/ui/feature-gates/feature-gate-box_patterns.stderr
src/test/ui/feature-gates/feature-gate-box_syntax.rs
src/test/ui/feature-gates/feature-gate-box_syntax.stderr
src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
src/test/ui/feature-gates/feature-gate-const_generics.rs
src/test/ui/feature-gates/feature-gate-const_generics.stderr
src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs
src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
src/test/ui/feature-gates/feature-gate-decl_macro.rs
src/test/ui/feature-gates/feature-gate-decl_macro.stderr
src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
src/test/ui/feature-gates/feature-gate-label_break_value.rs
src/test/ui/feature-gates/feature-gate-label_break_value.stderr
src/test/ui/feature-gates/feature-gate-trait-alias.rs
src/test/ui/feature-gates/feature-gate-trait-alias.stderr
src/test/ui/feature-gates/feature-gate-try_blocks.rs
src/test/ui/feature-gates/feature-gate-try_blocks.stderr
src/test/ui/feature-gates/feature-gate-type_ascription.rs
src/test/ui/feature-gates/feature-gate-type_ascription.stderr
src/test/ui/feature-gates/feature-gate-unwind-attributes.rs
src/test/ui/functions-closures/closure-to-fn-coercion.rs
src/test/ui/generator/panic-drops.rs
src/test/ui/generator/panic-safe.rs
src/test/ui/generator/resume-after-return.rs
src/test/ui/huge-struct.rs
src/test/ui/if/if-let.rs
src/test/ui/if/if-let.stderr
src/test/ui/imports/reexports.rs
src/test/ui/imports/reexports.stderr
src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
src/test/ui/invalid/invalid-variadic-function.stderr
src/test/ui/issues/issue-14875.rs
src/test/ui/issues/issue-24204.stderr
src/test/ui/issues/issue-29948.rs
src/test/ui/issues/issue-43853.rs
src/test/ui/issues/issue-46519.rs
src/test/ui/issues/issue-54943-3.rs
src/test/ui/iterators/iter-count-overflow-debug.rs
src/test/ui/iterators/iter-position-overflow-debug.rs
src/test/ui/iterators/iter-step-overflow-debug.rs
src/test/ui/iterators/iter-sum-overflow-debug.rs
src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs [new file with mode: 0644]
src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr [new file with mode: 0644]
src/test/ui/lint/lint-unnecessary-parens.rs
src/test/ui/lint/lint-unnecessary-parens.stderr
src/test/ui/lint/reasons.rs
src/test/ui/lint/type-overflow.rs
src/test/ui/lint/use-redundant.rs
src/test/ui/macros/macro-comma-behavior-rpass.rs
src/test/ui/malformed/malformed-regressions.rs
src/test/ui/malformed/malformed-regressions.stderr
src/test/ui/mir/mir_calls_to_shims.rs
src/test/ui/mir/mir_drop_order.rs
src/test/ui/never_type/adjust_never.rs
src/test/ui/never_type/call-fn-never-arg.rs
src/test/ui/never_type/cast-never.rs
src/test/ui/never_type/never-associated-type.rs
src/test/ui/never_type/never-type-arg.rs
src/test/ui/never_type/panic-uninitialized-zeroed.rs
src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
src/test/ui/offset_from.rs [new file with mode: 0644]
src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
src/test/ui/panic-runtime/transitive-link-a-bunch.rs
src/test/ui/panic-runtime/want-unwind-got-abort.rs
src/test/ui/panic-runtime/want-unwind-got-abort2.rs
src/test/ui/parser/pat-tuple-4.rs
src/test/ui/parser/pat-tuple-4.stderr
src/test/ui/parser/pat-tuple-5.stderr
src/test/ui/parser/variadic-ffi-3.stderr
src/test/ui/parser/variadic-ffi-4.stderr
src/test/ui/pattern/rest-pat-syntactic.rs
src/test/ui/pattern/usefulness/issue-43253.rs
src/test/ui/privacy/private-in-public-warn.stderr
src/test/ui/privacy/restricted/relative-2018.stderr
src/test/ui/privacy/restricted/test.stderr
src/test/ui/proc-macro/expand-with-a-macro.rs
src/test/ui/proc-macro/issue-50493.stderr
src/test/ui/pub/pub-restricted.stderr
src/test/ui/reachable-unnameable-items.rs
src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
src/test/ui/reject-specialized-drops-8142.rs
src/test/ui/resolve/resolve-bad-visibility.stderr
src/test/ui/resolve/visibility-indeterminate.stderr
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
src/test/ui/rfcs/rfc1857-drop-order.rs
src/test/ui/save-analysis/issue-65590.rs [new file with mode: 0644]
src/test/ui/simd/simd-intrinsic-float-minmax.rs
src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
src/test/ui/span/visibility-ty-params.stderr
src/test/ui/test-attrs/test-allow-fail-attr.rs
src/test/ui/test-attrs/test-should-fail-good-message.rs
src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr
src/test/ui/try-on-option-diagnostics.rs [new file with mode: 0644]
src/test/ui/try-on-option-diagnostics.stderr [new file with mode: 0644]
src/test/ui/type/type-alias-bounds.stderr
src/test/ui/while-let.rs
src/test/ui/while-let.stderr
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rls
src/tools/rustbook/Cargo.toml
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/tidy/src/error_codes_check.rs

index 1dcf9ed319f149ee1054dbc761f47ad9dc2702e7..31db0772cfb6b3f789fde5073b823f3c74908998 100644 (file)
@@ -3,13 +3,13 @@
        url = https://github.com/rust-lang/rust-installer.git
 [submodule "src/doc/nomicon"]
        path = src/doc/nomicon
-       url = https://github.com/rust-lang-nursery/nomicon.git
+       url = https://github.com/rust-lang/nomicon.git
 [submodule "src/tools/cargo"]
        path = src/tools/cargo
        url = https://github.com/rust-lang/cargo.git
 [submodule "src/doc/reference"]
        path = src/doc/reference
-       url = https://github.com/rust-lang-nursery/reference.git
+       url = https://github.com/rust-lang/reference.git
 [submodule "src/doc/book"]
        path = src/doc/book
        url = https://github.com/rust-lang/book.git
@@ -36,7 +36,7 @@
        url = https://github.com/rust-lang/rustc-guide.git
 [submodule "src/doc/edition-guide"]
        path = src/doc/edition-guide
-       url = https://github.com/rust-lang-nursery/edition-guide.git
+       url = https://github.com/rust-lang/edition-guide.git
 [submodule "src/llvm-project"]
        path = src/llvm-project
        url = https://github.com/rust-lang/llvm-project.git
index 2c161e4d27a9d12856ade58c422152172fb22bec..46480aeb4476d840c412833f39e34e9663c3c5da 100644 (file)
@@ -27,16 +27,16 @@ dependencies = [
 
 [[package]]
 name = "ammonia"
-version = "2.1.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "384d704f242a0a9faf793fff775a0be6ab9aa27edabffa097331d73779142520"
+checksum = "9e266e1f4be5ffa05309f650e2586fe1d3ae6034eb24025a7ae1dfecc330823a"
 dependencies = [
  "html5ever",
  "lazy_static 1.3.0",
  "maplit",
  "matches",
  "tendril",
- "url 1.7.2",
+ "url 2.1.0",
 ]
 
 [[package]]
@@ -285,7 +285,7 @@ dependencies = [
  "crypto-hash",
  "curl",
  "curl-sys",
- "env_logger 0.7.0",
+ "env_logger 0.7.1",
  "failure",
  "filetime",
  "flate2",
@@ -552,7 +552,7 @@ name = "compiletest"
 version = "0.0.0"
 dependencies = [
  "diff",
- "env_logger 0.7.0",
+ "env_logger 0.7.1",
  "getopts",
  "lazy_static 1.3.0",
  "libc",
@@ -974,9 +974,9 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39ecdb7dd54465526f0a56d666e3b2dd5f3a218665a030b6e4ad9e70fa95d8fa"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
 dependencies = [
  "atty",
  "humantime",
@@ -1363,16 +1363,16 @@ dependencies = [
 
 [[package]]
 name = "html5ever"
-version = "0.23.0"
+version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce65ac8028cf5a287a7dbf6c4e0a6cf2dcf022ed5b167a81bae66ebf599a8b7"
+checksum = "025483b0a1e4577bb28578318c886ee5f817dda6eb62473269349044406644cb"
 dependencies = [
  "log",
  "mac",
  "markup5ever",
- "proc-macro2 0.4.30",
- "quote 0.6.12",
- "syn 0.15.35",
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
+ "syn 1.0.5",
 ]
 
 [[package]]
@@ -1631,9 +1631,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core"
-version = "13.1.0"
+version = "13.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd42951eb35079520ee29b7efbac654d85821b397ef88c8151600ef7e2d00217"
+checksum = "91d767c183a7e58618a609499d359ce3820700b3ebb4823a18c343b4a2a41a0d"
 dependencies = [
  "futures",
  "log",
@@ -1902,9 +1902,9 @@ checksum = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 
 [[package]]
 name = "markup5ever"
-version = "0.8.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1af46a727284117e09780d05038b1ce6fc9c76cc6df183c3dae5a8955a25e21"
+checksum = "65381d9d47506b8592b97c4efd936afcf673b09b059f2bef39c7211ee78b9d03"
 dependencies = [
  "log",
  "phf",
@@ -1925,9 +1925,9 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 
 [[package]]
 name = "mdbook"
-version = "0.3.1"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "949bb2acb2cff9fa5c375cf9c43e70b3dba0a974d9fe01c31285d7a84d2a0fa2"
+checksum = "9a070268274c566082efb6b2ace7743e43ba91a70d5c6982981e96d3c05ac81c"
 dependencies = [
  "ammonia",
  "chrono",
@@ -2147,13 +2147,13 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "byteorder",
- "cargo_metadata 0.8.0",
+ "cargo_metadata 0.9.0",
  "colored",
  "compiletest_rs",
  "directories",
- "env_logger 0.6.2",
+ "env_logger 0.7.1",
  "getrandom",
- "hex 0.3.2",
+ "hex 0.4.0",
  "log",
  "num-traits",
  "rand 0.7.0",
@@ -2974,14 +2974,14 @@ checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
 
 [[package]]
 name = "rls"
-version = "1.39.0"
+version = "1.40.0"
 dependencies = [
  "cargo",
  "cargo_metadata 0.8.0",
  "clippy_lints",
  "crossbeam-channel",
  "difference",
- "env_logger 0.6.2",
+ "env_logger 0.7.1",
  "failure",
  "futures",
  "heck",
@@ -2995,7 +2995,7 @@ dependencies = [
  "num_cpus",
  "ordslice",
  "racer",
- "rand 0.6.1",
+ "rand 0.7.0",
  "rayon",
  "regex",
  "rls-analysis",
@@ -3004,7 +3004,6 @@ dependencies = [
  "rls-rustc",
  "rls-span",
  "rls-vfs",
- "rustc-serialize",
  "rustc-workspace-hack",
  "rustc_tools_util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustfmt-nightly",
@@ -3065,11 +3064,11 @@ name = "rls-rustc"
 version = "0.6.0"
 dependencies = [
  "clippy_lints",
- "env_logger 0.6.2",
+ "env_logger 0.7.1",
  "failure",
  "futures",
  "log",
- "rand 0.6.1",
+ "rand 0.7.0",
  "rls-data",
  "rls-ipc",
  "serde",
@@ -3103,6 +3102,7 @@ dependencies = [
  "failure",
  "mdbook",
  "mdbook-linkcheck",
+ "rustc-workspace-hack",
 ]
 
 [[package]]
@@ -3364,12 +3364,6 @@ dependencies = [
  "num_cpus",
 ]
 
-[[package]]
-name = "rustc-serialize"
-version = "0.3.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-
 [[package]]
 name = "rustc-std-workspace-alloc"
 version = "1.99.0"
@@ -3399,6 +3393,7 @@ dependencies = [
  "serde",
  "serde_json",
  "smallvec",
+ "syn 0.15.35",
  "url 2.1.0",
  "winapi 0.3.6",
 ]
@@ -3496,7 +3491,7 @@ dependencies = [
 name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
- "env_logger 0.7.0",
+ "env_logger 0.7.1",
  "graphviz",
  "lazy_static 1.3.0",
  "log",
index 76509134f7ccdf3c3517a449fa5c380e58e6f372..bb6041d7f31960c7b53d3cc31bbba0e852008bc7 100755 (executable)
@@ -133,6 +133,10 @@ v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root",
   "mips-unknown-linux-musl install directory")
 v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root",
   "mipsel-unknown-linux-musl install directory")
+v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root",
+  "mips64-unknown-linux-muslabi64 install directory")
+v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root",
+  "mips64el-unknown-linux-muslabi64 install directory")
 v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
   "rootfs in qemu testing, you probably don't want to use this")
 v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
index cbdb174c02d97cbcccf09ac9a5c50f1b42b69a47..39d7ea922bceda50770772869345adc83364b440 100644 (file)
@@ -1080,6 +1080,10 @@ fn unstable_features(&self) -> bool {
     /// done. The file is updated immediately after this function completes.
     pub fn save_toolstate(&self, tool: &str, state: ToolState) {
         if let Some(ref path) = self.config.save_toolstates {
+            if let Some(parent) = path.parent() {
+                // Ensure the parent directory always exists
+                t!(std::fs::create_dir_all(parent));
+            }
             let mut file = t!(fs::OpenOptions::new()
                 .create(true)
                 .read(true)
index 97cdd25680162869758a0349269360f112e4c1d2..e76604e45bdeb3c60570e88e633a7d5039490a1f 100644 (file)
@@ -534,6 +534,10 @@ fn run(self, builder: &Builder<'_>) {
         builder.info("Building test helpers");
         t!(fs::create_dir_all(&dst));
         let mut cfg = cc::Build::new();
+        // FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013
+        if target.contains("emscripten") {
+            cfg.pic(false);
+        }
 
         // We may have found various cross-compilers a little differently due to our
         // extra configuration, so inform gcc of these compilers. Note, though, that
index f1baeafe26afb72fbaeb011ddb9ec5dd62c965b1..815498047fd5d160ac9afef8dfcc2060558c7743 100644 (file)
@@ -244,6 +244,7 @@ pub fn prepare_tool_cargo(
             path.ends_with("rls") ||
             path.ends_with("clippy") ||
             path.ends_with("miri") ||
+            path.ends_with("rustbook") ||
             path.ends_with("rustfmt")
         {
             cargo.env("LIBZ_SYS_STATIC", "1");
index 24b07a1b7c950111eae85bc9822b2d2725592854..271c32585449ec295495a2882fb480de246af258 100644 (file)
@@ -140,6 +140,7 @@ jobs:
         IMAGE: x86_64-gnu-aux
       x86_64-gnu-tools:
         IMAGE: x86_64-gnu-tools
+        DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
       x86_64-gnu-debug:
         IMAGE: x86_64-gnu-debug
       x86_64-gnu-nopt:
@@ -262,8 +263,9 @@ jobs:
       # MSVC tools tests
       x86_64-msvc-tools:
         MSYS_BITS: 64
-        SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
-        RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json
+        SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows
+        RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json
+        DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
 
       # 32/64-bit MinGW builds.
       #
index 62e23efe1ef168f951c8ac3d901ef451a7d92d43..566e654fdb3f0f8ffb62fa70415f57af8070f367 100644 (file)
@@ -22,14 +22,6 @@ jobs:
         IMAGE: x86_64-gnu-llvm-6.0
       mingw-check:
         IMAGE: mingw-check
-
-- job: LinuxTools
-  timeoutInMinutes: 600
-  pool:
-    vmImage: ubuntu-16.04
-  steps:
-    - template: steps/run.yml
-      parameters:
-        only_on_updated_submodules: 'yes'
-  variables:
-    IMAGE: x86_64-gnu-tools
+      x86_64-gnu-tools:
+        IMAGE: x86_64-gnu-tools
+        CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
index 01858cca50b1cc7820446359bff8fed279857bb6..cef2d235602f19c32325bedea47b3cf23eb8aab0 100644 (file)
@@ -6,11 +6,6 @@
 #
 # Check travis config for `gdb --batch` command to print all crash logs
 
-parameters:
-  # When this parameter is set to anything other than an empty string the tests
-  # will only be executed when the commit updates submodules
-  only_on_updated_submodules: ''
-
 steps:
 
 # Disable automatic line ending conversion, which is enabled by default on
@@ -26,21 +21,8 @@ steps:
 - checkout: self
   fetchDepth: 2
 
-# Set the SKIP_JOB environment variable if this job is supposed to only run
-# when submodules are updated and they were not. The following time consuming
-# tasks will be skipped when the environment variable is present.
-- ${{ if parameters.only_on_updated_submodules }}:
-  - bash: |
-      set -e
-      # Submodules pseudo-files inside git have the 160000 permissions, so when
-      # those files are present in the diff a submodule was updated.
-      if git diff HEAD^ | grep "^index .* 160000" >/dev/null 2>&1; then
-          echo "Executing the job since submodules are updated"
-      else
-          echo "Not executing this job since no submodules were updated"
-          echo "##vso[task.setvariable variable=SKIP_JOB;]1"
-      fi
-    displayName: Decide whether to run this job
+- bash: src/ci/scripts/should-skip-this.sh
+  displayName: Decide whether to run this job
 
 # Spawn a background process to collect CPU usage statistics which we'll upload
 # at the end of the build. See the comments in the script here for more
@@ -201,37 +183,21 @@ steps:
   condition: and(succeeded(), not(variables.SKIP_JOB))
   displayName: Run build
 
-# If we're a deploy builder, use the `aws` command to publish everything to our
-# bucket.
-- bash: |
-    set -e
-    source src/ci/shared.sh
-    if [ "$AGENT_OS" = "Linux" ]; then
-        rm -rf obj/build/dist/doc
-        upload_dir=obj/build/dist
-    else
-        rm -rf build/dist/doc
-        upload_dir=build/dist
-    fi
-    ls -la $upload_dir
-    deploy_dir=rustc-builds
-    if [ "$DEPLOY_ALT" == "1" ]; then
-        deploy_dir=rustc-builds-alt
-    fi
-    retry aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION
+- bash: src/ci/scripts/upload-artifacts.sh
   env:
     AWS_ACCESS_KEY_ID: $(UPLOAD_AWS_ACCESS_KEY_ID)
     AWS_SECRET_ACCESS_KEY: $(UPLOAD_AWS_SECRET_ACCESS_KEY)
-  condition: and(succeeded(), not(variables.SKIP_JOB), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1')))
   displayName: Upload artifacts
-
-# Upload CPU usage statistics that we've been gathering this whole time. Always
-# execute this step in case we want to inspect failed builds, but don't let
-# errors here ever fail the build since this is just informational.
-- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$CI_JOB_NAME.csv
-  env:
-    AWS_ACCESS_KEY_ID: $(UPLOAD_AWS_ACCESS_KEY_ID)
-    AWS_SECRET_ACCESS_KEY: $(UPLOAD_AWS_SECRET_ACCESS_KEY)
-  condition: variables['UPLOAD_AWS_SECRET_ACCESS_KEY']
-  continueOnError: true
-  displayName: Upload CPU usage statistics
+  # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy
+  # builders *should* have the AWS credentials available. Still, explicitly
+  # adding the condition is helpful as this way CI will not silently skip
+  # deploying artifacts from a dist builder if the variables are misconfigured,
+  # erroring about invalid credentials instead.
+  condition: |
+    and(
+      succeeded(), not(variables.SKIP_JOB),
+      or(
+        variables.UPLOAD_AWS_SECRET_ACCESS_KEY,
+        eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1')
+      )
+    )
index fab3824a20ae3723968d0f018a6c161b7245bfc7..816bdb34a7bfe216e91b438e9b4f13bf313ab1d7 100644 (file)
@@ -15,6 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   g++-arm-linux-gnueabi \
   g++-arm-linux-gnueabihf \
   g++-aarch64-linux-gnu \
+  g++-mips64-linux-gnuabi64 \
+  g++-mips64el-linux-gnuabi64 \
   gcc-sparc64-linux-gnu \
   libc6-dev-sparc64-cross \
   bzip2 \
@@ -77,6 +79,14 @@ RUN env \
     CC=mipsel-openwrt-linux-gcc \
     CXX=mipsel-openwrt-linux-g++ \
     bash musl.sh mipsel && \
+    env \
+    CC=mips64-linux-gnuabi64-gcc \
+    CXX=mips64-linux-gnuabi64-g++ \
+    bash musl.sh mips64 && \
+    env \
+    CC=mips64el-linux-gnuabi64-gcc \
+    CXX=mips64el-linux-gnuabi64-g++ \
+    bash musl.sh mips64el && \
     rm -rf /build/*
 
 # FIXME(mozilla/sccache#235) this shouldn't be necessary but is currently
@@ -97,6 +107,8 @@ ENV TARGETS=$TARGETS,wasm32-unknown-emscripten
 ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd
 ENV TARGETS=$TARGETS,mips-unknown-linux-musl
 ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl
+ENV TARGETS=$TARGETS,mips64-unknown-linux-muslabi64
+ENV TARGETS=$TARGETS,mips64el-unknown-linux-muslabi64
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi
@@ -125,6 +137,8 @@ ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf
 
 ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
+    CC_mips64el_unknown_linux_muslabi64=mips64el-linux-gnuabi64-gcc \
+    CC_mips64_unknown_linux_muslabi64=mips64-linux-gnuabi64-gcc \
     CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
     CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
     CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \
@@ -139,6 +153,8 @@ ENV RUST_CONFIGURE_ARGS \
       --musl-root-aarch64=/musl-aarch64 \
       --musl-root-mips=/musl-mips \
       --musl-root-mipsel=/musl-mipsel \
+      --musl-root-mips64=/musl-mips64 \
+      --musl-root-mips64el=/musl-mips64el \
       --disable-docs
 
 ENV SCRIPT \
index 415d6b63eb8dc1152de7a0c191c0ce0cc4da250a..cdafcbadc9ec768bc9c044cfc2369c7ac51f3a82 100755 (executable)
@@ -106,6 +106,7 @@ fi
 mkdir -p $HOME/.cargo
 mkdir -p $objdir/tmp
 mkdir -p $objdir/cores
+mkdir -p /tmp/toolstate
 
 args=
 if [ "$SCCACHE_BUCKET" != "" ]; then
@@ -156,6 +157,7 @@ else
   args="$args --volume $objdir:/checkout/obj"
   args="$args --volume $HOME/.cargo:/cargo"
   args="$args --volume $HOME/rustsrc:$HOME/rustsrc"
+  args="$args --volume /tmp/toolstate:/tmp/toolstate"
   args="$args --env LOCAL_USER_ID=`id -u`"
 fi
 
index 8035195c6ed0ae5cdee52296fa294ed6fde3c2d5..7687a6ca23e180fb386ac2446fd169d239c21a45 100644 (file)
@@ -26,5 +26,5 @@ ENV CHECK_LINKS 1
 
 ENV RUST_CONFIGURE_ARGS \
   --build=x86_64-unknown-linux-gnu \
-  --save-toolstates=/tmp/toolstates.json
-ENV SCRIPT /tmp/checktools.sh ../x.py /tmp/toolstates.json linux
+  --save-toolstates=/tmp/toolstate/toolstates.json
+ENV SCRIPT /tmp/checktools.sh ../x.py /tmp/toolstate/toolstates.json linux
index 4243effdf9b4b22074af2022a0e49feb53d62580..ebb8c0bda53ee2ae3654a1d9e28388b2eeafcb07 100755 (executable)
@@ -3,7 +3,7 @@
 set -eu
 
 X_PY="$1"
-TOOLSTATE_FILE="$(realpath $2)"
+TOOLSTATE_FILE="$(realpath -m $2)"
 OS="$3"
 COMMIT="$(git rev-parse HEAD)"
 CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
@@ -13,6 +13,7 @@ SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))"
 #   The Wednesday after this has value 0.
 #   We track this value to prevent regressing tools in the last week of the 6-week cycle.
 
+mkdir -p "$(dirname $TOOLSTATE_FILE)"
 touch "$TOOLSTATE_FILE"
 
 # Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
index 375f13f30b3ed3b34e324c2c3c13c0d76de0c0a2..36d9202f7a2d30e61fb7f8c8afd6d6538d9fc8cb 100755 (executable)
@@ -8,14 +8,6 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 if isWindows; then
     pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar
 
-    # FIXME(#65767): workaround msys bug, step 2
-    arch=i686
-    if [ "$MSYS_BITS" = "64" ]; then
-      arch=x86_64
-    fi
-    pacman -U --noconfirm --noprogressbar mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz
-    rm mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz
-
     # Make sure we use the native python interpreter instead of some msys equivalent
     # one way or another. The msys interpreters seem to have weird path conversions
     # baked in which break LLVM's build system one way or another, so let's use the
index 8b631192ea2b44b96d96688de57fd333327c8e9c..ce37c3b146977dafa2fcb3e08a79cdebf89a3f5f 100755 (executable)
@@ -1,5 +1,4 @@
 #!/bin/bash
-# ignore-tidy-linelength
 # Download and install MSYS2, needed primarily for the test suite (run-make) but
 # also used by the MinGW toolchain for assembling things.
 #
@@ -13,13 +12,6 @@ IFS=$'\n\t'
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 if isWindows; then
-    # FIXME(#65767): workaround msys bug, step 1
-    arch=i686
-    if [ "$MSYS_BITS" = "64" ]; then
-      arch=x86_64
-    fi
-    curl -O "${MIRRORS_BASE}/msys2-repo/mingw/$arch/mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz"
-
     choco install msys2 --params="/InstallDir:${SYSTEM_WORKFOLDER}/msys2 /NoPath" -y --no-progress
     mkdir -p "${SYSTEM_WORKFOLDER}/msys2/home/${USERNAME}"
 
diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh
new file mode 100755 (executable)
index 0000000..f945db0
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Set the SKIP_JOB environment variable if this job is supposed to only run
+# when submodules are updated and they were not. The following time consuming
+# tasks will be skipped when the environment variable is present.
+
+set -euo pipefail
+IFS=$'\n\t'
+
+source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
+
+if [[ -z "${CI_ONLY_WHEN_SUBMODULES_CHANGED+x}" ]]; then
+    echo "Executing the job since there is no skip rule in effect"
+elif git diff HEAD^ | grep --quiet "^index .* 160000"; then
+    # Submodules pseudo-files inside git have the 160000 permissions, so when
+    # those files are present in the diff a submodule was updated.
+    echo "Executing the job since submodules are updated"
+else
+    echo "Not executing this job since no submodules were updated"
+    ciCommandSetEnv SKIP_JOB 1
+fi
diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh
new file mode 100755 (executable)
index 0000000..312ec9d
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Upload all the artifacts to our S3 bucket. All the files inside ${upload_dir}
+# will be uploaded to the deploy bucket and eventually signed and released in
+# static.rust-lang.org.
+
+set -euo pipefail
+IFS=$'\n\t'
+
+source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
+
+upload_dir="$(mktemp -d)"
+
+# Release tarballs produced by a dist builder.
+if [[ "${DEPLOY-0}" -eq "1" ]] || [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then
+    dist_dir=build/dist
+    if isLinux; then
+        dist_dir=obj/build/dist
+    fi
+    rm -rf "${dist_dir}/doc"
+    cp -r "${dist_dir}"/* "${upload_dir}"
+fi
+
+# CPU usage statistics.
+cp cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv"
+
+# Toolstate data.
+if [[ -n "${DEPLOY_TOOLSTATES_JSON+x}" ]]; then
+    cp /tmp/toolstate/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}"
+fi
+
+echo "Files that will be uploaded:"
+ls -lah "${upload_dir}"
+echo
+
+deploy_dir="rustc-builds"
+if [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then
+    deploy_dir="rustc-builds-alt"
+fi
+deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)"
+
+retry aws s3 cp --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}"
index 37e45b5639dc9ae538253f27b0d291b6f87c6916..718a5379ae558c44aac11ac160163b71eb19225a 100644 (file)
@@ -46,6 +46,10 @@ function getCIBranch {
   echo "$BUILD_SOURCEBRANCHNAME"
 }
 
+function ciCommit {
+  echo "${BUILD_SOURCEVERSION}"
+}
+
 function ciCommandAddPath {
     if [[ $# -ne 1 ]]; then
         echo "usage: $0 <path>"
index 9bb8b161963fcebc9d9ccd732ba26f42108016d5..28fa3d15b0bc67ea5e79eeff2198e4277fc61baf 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9bb8b161963fcebc9d9ccd732ba26f42108016d5
+Subproject commit 28fa3d15b0bc67ea5e79eeff2198e4277fc61baf
index 5b9d2fcefadfc32fceafacfc0dd9441d9b57dd94..4b21b646669e0af49fae7cae301898dc4bfaa1f0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5b9d2fcefadfc32fceafacfc0dd9441d9b57dd94
+Subproject commit 4b21b646669e0af49fae7cae301898dc4bfaa1f0
index 0b111eaae36cc4b4997684be853882a59e2c7ca7..f3197ddf2abab9abdbc029def8164f4a748b0d91 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0b111eaae36cc4b4997684be853882a59e2c7ca7
+Subproject commit f3197ddf2abab9abdbc029def8164f4a748b0d91
index c9acd3c307b54690851393d1e5304d78cbcee2ad..bc1da5ff15a8c2de2557c5ce49720c006adab2a8 100644 (file)
@@ -379,3 +379,49 @@ However, it's preferable to use fenced code blocks over indented code blocks.
 Not only are fenced code blocks considered more idiomatic for Rust code,
 but there is no way to use directives such as `ignore` or `should_panic` with
 indented code blocks.
+
+### Include items only when collecting doctests
+
+Rustdoc's documentation tests can do some things that regular unit tests can't, so it can
+sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in
+documentation. To this end, Rustdoc allows you to have certain items only appear when it's
+collecting doctests, so you can utilize doctest functionality without forcing the test to appear in
+docs, or to find an arbitrary private item to include it on.
+
+When compiling a crate for use in doctests (with `--test` option), rustdoc will set `cfg(doctest)`.
+Note that they will still link against only the public items of your crate; if you need to test
+private items, you need to write a unit test.
+
+In this example, we're adding doctests that we know won't compile, to verify that our struct can
+only take in valid data:
+
+```rust
+/// We have a struct here. Remember it doesn't accept negative numbers!
+pub struct MyStruct(pub usize);
+
+/// ```compile_fail
+/// let x = my_crate::MyStruct(-5);
+/// ```
+#[cfg(doctest)]
+pub struct MyStructOnlyTakesUsize;
+```
+
+Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate
+API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while rustdoc is
+collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc,
+but is hidden from the public documentation.
+
+Another possible use of `cfg(doctest)` is to test doctests that are included in your README file
+without including it in your main documentation. For example, you could write this into your
+`lib.rs` to test your README as part of your doctests:
+
+```rust,ignore
+#![feature(extern_doc)]
+
+#[doc(include="../README.md")]
+#[cfg(doctest)]
+pub struct ReadmeDoctests;
+```
+
+This will include your README as documentation on the hidden struct `ReadmeDoctests`, which will
+then be tested alongside the rest of your doctests.
index 49d05b5038df74dd8ff7bd53545adc7fdfc123d9..3c3e72aa3795912e5cedfa08930e439ef3dd24c8 100644 (file)
@@ -211,36 +211,6 @@ pub struct BigX;
 Then, when looking for it through the `rustdoc` search, if you enter "x" or
 "big", search will show the `BigX` struct first.
 
-### Include items only when collecting doctests
-
-Rustdoc's [documentation tests] can do some things that regular unit tests can't, so it can
-sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in
-documentation. To this end, Rustdoc allows you to have certain items only appear when it's
-collecting doctests, so you can utilize doctest functionality without forcing the test to appear in
-docs, or to find an arbitrary private item to include it on.
-
-If you add `#![feature(cfg_doctest)]` to your crate, Rustdoc will set `cfg(doctest)` when collecting
-doctests. Note that they will still link against only the public items of your crate; if you need to
-test private items, unit tests are still the way to go.
-
-In this example, we're adding doctests that we know won't compile, to verify that our struct can
-only take in valid data:
-
-```rust
-#![feature(cfg_doctest)]
-
-/// We have a struct here. Remember it doesn't accept negative numbers!
-pub struct MyStruct(usize);
-
-/// ```compile_fail
-/// let x = my_crate::MyStruct(-5);
-/// ```
-#[cfg(doctest)]
-pub struct MyStructOnlyTakesUsize;
-```
-
-[documentation tests]: documentation-tests.html
-
 ## Unstable command-line arguments
 
 These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
index 3ee024c6b588361e8f10a3f593aebf1f60b6333d..d4ad65e84b7b4935a8a88b919eab8ad20f50f09d 100644 (file)
@@ -249,11 +249,11 @@ the source code.
 - Runtime
   - `start`: `libstd/rt.rs`
   - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
-  - `eh_personality`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU)
+  - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
   - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
-  - `eh_unwind_resume`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU)
   - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC)
-  - `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH)
+  - `eh_catch_typeinfo`: `libpanic_unwind/seh.rs` (SEH)
+  - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
   - `panic`: `libcore/panicking.rs`
   - `panic_bounds_check`: `libcore/panicking.rs`
   - `panic_impl`: `libcore/panicking.rs`
index 3d04f30e7bde54bf2c8e832bcd4cedb40688fbb8..fda6f090fd7795c4a19d831e29f1a6723ea2847f 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use core::ops::{Deref, DerefMut};
-use core::iter::{FromIterator, FusedIterator};
+use core::iter::{FromIterator, FusedIterator, TrustedLen};
 use core::mem::{swap, size_of, ManuallyDrop};
 use core::ptr;
 use core::fmt;
@@ -648,6 +648,36 @@ fn better_to_rebuild(len1: usize, len2: usize) -> bool {
             self.extend(other.drain());
         }
     }
+
+    /// Returns an iterator which retrieves elements in heap order.
+    /// The retrieved elements are removed from the original heap.
+    /// The remaining elements will be removed on drop in heap order.
+    ///
+    /// Note:
+    /// * `.drain_sorted()` is O(n lg n); much slower than `.drain()`.
+    ///   You should use the latter for most cases.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(binary_heap_drain_sorted)]
+    /// use std::collections::BinaryHeap;
+    ///
+    /// let mut heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]);
+    /// assert_eq!(heap.len(), 5);
+    ///
+    /// drop(heap.drain_sorted()); // removes all elements in heap order
+    /// assert_eq!(heap.len(), 0);
+    /// ```
+    #[inline]
+    #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+    pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> {
+        DrainSorted {
+            inner: self,
+        }
+    }
 }
 
 impl<T> BinaryHeap<T> {
@@ -672,6 +702,27 @@ pub fn iter(&self) -> Iter<'_, T> {
         Iter { iter: self.data.iter() }
     }
 
+    /// Returns an iterator which retrieves elements in heap order.
+    /// This method consumes the original heap.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(binary_heap_into_iter_sorted)]
+    /// use std::collections::BinaryHeap;
+    /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]);
+    ///
+    /// assert_eq!(heap.into_iter_sorted().take(2).collect::<Vec<_>>(), vec![5, 4]);
+    /// ```
+    #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+    pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
+        IntoIterSorted {
+            inner: self,
+        }
+    }
+
     /// Returns the greatest item in the binary heap, or `None` if it is empty.
     ///
     /// # Examples
@@ -1115,6 +1166,37 @@ fn is_empty(&self) -> bool {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T> FusedIterator for IntoIter<T> {}
 
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+#[derive(Clone, Debug)]
+pub struct IntoIterSorted<T> {
+    inner: BinaryHeap<T>,
+}
+
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+impl<T: Ord> Iterator for IntoIterSorted<T> {
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        self.inner.pop()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let exact = self.inner.len();
+        (exact, Some(exact))
+    }
+}
+
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {}
+
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+impl<T: Ord> FusedIterator for IntoIterSorted<T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {}
+
 /// A draining iterator over the elements of a `BinaryHeap`.
 ///
 /// This `struct` is created by the [`drain`] method on [`BinaryHeap`]. See its
@@ -1161,6 +1243,52 @@ fn is_empty(&self) -> bool {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T> FusedIterator for Drain<'_, T> {}
 
+/// A draining iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by the [`drain_sorted`] method on [`BinaryHeap`]. See its
+/// documentation for more.
+///
+/// [`drain_sorted`]: struct.BinaryHeap.html#method.drain_sorted
+/// [`BinaryHeap`]: struct.BinaryHeap.html
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+#[derive(Debug)]
+pub struct DrainSorted<'a, T: Ord> {
+    inner: &'a mut BinaryHeap<T>,
+}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<'a, T: Ord> Drop for DrainSorted<'a, T> {
+    /// Removes heap elements in heap order.
+    fn drop(&mut self) {
+        while let Some(_) = self.inner.pop() {}
+    }
+}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<T: Ord> Iterator for DrainSorted<'_, T> {
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        self.inner.pop()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let exact = self.inner.len();
+        (exact, Some(exact))
+    }
+}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> { }
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T: Ord> TrustedLen for DrainSorted<'_, T> {}
+
 #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
     /// Converts a `Vec<T>` into a `BinaryHeap<T>`.
index b8c720264d0abce13e893dc35b461f3e9d685520..a44cf1eaf6df0310471d4e6d8e67050c6c9aca95 100644 (file)
@@ -1,5 +1,6 @@
 use std::collections::BinaryHeap;
 use std::collections::binary_heap::{Drain, PeekMut};
+use std::iter::TrustedLen;
 
 #[test]
 fn test_iterator() {
@@ -14,7 +15,7 @@ fn test_iterator() {
 }
 
 #[test]
-fn test_iterator_reverse() {
+fn test_iter_rev_cloned_collect() {
     let data = vec![5, 9, 3];
     let iterout = vec![3, 5, 9];
     let pq = BinaryHeap::from(data);
@@ -24,7 +25,7 @@ fn test_iterator_reverse() {
 }
 
 #[test]
-fn test_move_iter() {
+fn test_into_iter_collect() {
     let data = vec![5, 9, 3];
     let iterout = vec![9, 5, 3];
     let pq = BinaryHeap::from(data);
@@ -34,7 +35,7 @@ fn test_move_iter() {
 }
 
 #[test]
-fn test_move_iter_size_hint() {
+fn test_into_iter_size_hint() {
     let data = vec![5, 9];
     let pq = BinaryHeap::from(data);
 
@@ -51,7 +52,7 @@ fn test_move_iter_size_hint() {
 }
 
 #[test]
-fn test_move_iter_reverse() {
+fn test_into_iter_rev_collect() {
     let data = vec![5, 9, 3];
     let iterout = vec![3, 5, 9];
     let pq = BinaryHeap::from(data);
@@ -60,6 +61,65 @@ fn test_move_iter_reverse() {
     assert_eq!(v, iterout);
 }
 
+#[test]
+fn test_into_iter_sorted_collect() {
+    let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
+    let it = heap.into_iter_sorted();
+    let sorted = it.collect::<Vec<_>>();
+    assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]);
+}
+
+#[test]
+fn test_drain_sorted_collect() {
+    let mut heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
+    let it = heap.drain_sorted();
+    let sorted = it.collect::<Vec<_>>();
+    assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]);
+}
+
+fn check_exact_size_iterator<I: ExactSizeIterator>(len: usize, it: I) {
+    let mut it = it;
+
+    for i in 0..it.len() {
+        let (lower, upper) = it.size_hint();
+        assert_eq!(Some(lower), upper);
+        assert_eq!(lower, len - i);
+        assert_eq!(it.len(), len - i);
+        it.next();
+    }
+    assert_eq!(it.len(), 0);
+    assert!(it.is_empty());
+}
+
+#[test]
+fn test_exact_size_iterator() {
+    let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
+    check_exact_size_iterator(heap.len(), heap.iter());
+    check_exact_size_iterator(heap.len(), heap.clone().into_iter());
+    check_exact_size_iterator(heap.len(), heap.clone().into_iter_sorted());
+    check_exact_size_iterator(heap.len(), heap.clone().drain());
+    check_exact_size_iterator(heap.len(), heap.clone().drain_sorted());
+}
+
+fn check_trusted_len<I: TrustedLen>(len: usize, it: I) {
+    let mut it = it;
+    for i in 0..len {
+        let (lower, upper) = it.size_hint();
+        if upper.is_some() {
+            assert_eq!(Some(lower), upper);
+            assert_eq!(lower, len - i);
+        }
+        it.next();
+    }
+}
+
+#[test]
+fn test_trusted_len() {
+    let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
+    check_trusted_len(heap.len(), heap.clone().into_iter_sorted());
+    check_trusted_len(heap.len(), heap.clone().drain_sorted());
+}
+
 #[test]
 fn test_peek_and_pop() {
     let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
@@ -206,6 +266,15 @@ fn test_drain() {
     assert!(q.is_empty());
 }
 
+#[test]
+fn test_drain_sorted() {
+    let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect();
+
+    assert_eq!(q.drain_sorted().take(5).collect::<Vec<_>>(), vec![9, 8, 7, 6, 5]);
+
+    assert!(q.is_empty());
+}
+
 #[test]
 fn test_extend_ref() {
     let mut a = BinaryHeap::new();
index 79e5ba340b78475e89ce58b72b91396d0b302bcf..3273feb7b5dd4b291e1250386f4b1acce1427dba 100644 (file)
@@ -8,6 +8,8 @@
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(associated_type_bounds)]
+#![feature(binary_heap_into_iter_sorted)]
+#![feature(binary_heap_drain_sorted)]
 
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
index 0ea4187ccd4829b414daed1dd0ac1ebb75445039..569c667ac0a54b534064d8a4c590edcbf482f58d 100644 (file)
 /// stabilized, it is recommended to use a newtype wrapper around an empty
 /// byte array. See the [Nomicon] for details.
 ///
+/// One could use `std::os::raw::c_void` if they want to support old Rust
+/// compiler down to 1.1.0. After Rust 1.30.0, it was re-exported by
+/// this definition. For more information, please read [RFC 2521].
+///
 /// [pointer]: ../../std/primitive.pointer.html
 /// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
+/// [RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
 // N.B., for LLVM to recognize the void pointer type and by extension
 //     functions like malloc(), we need to have it represented as i8* in
 //     LLVM bitcode. The enum used here ensures this and prevents misuse
@@ -29,7 +34,7 @@
 //     would be uninhabited and at least dereferencing such pointers would
 //     be UB.
 #[repr(u8)]
-#[stable(feature = "raw_os", since = "1.1.0")]
+#[stable(feature = "core_c_void", since = "1.30.0")]
 pub enum c_void {
     #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
                issue = "0")]
index 4e0f18b88fe0a45e256638704c64e7d135ef2d35..3db85d05d7a986b0da42dc2f00cab35947678f7a 100644 (file)
@@ -1344,6 +1344,10 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// Emits a `!nontemporal` store according to LLVM (see their docs).
     /// Probably will never become stable.
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
+
+    /// See documentation of `<*const T>::offset_from` for details.
+    #[cfg(not(bootstrap))]
+    pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 }
 
 // Some functions are defined here because they accidentally got made
index aba8e84d58be553566165846b39eb2990f2da84b..fac6ff0f06b6d86c750d2f680fa83e2fee29476a 100644 (file)
 //!
 //! let mut counter = Counter::new();
 //!
-//! let x = counter.next().unwrap();
-//! println!("{}", x);
-//!
-//! let x = counter.next().unwrap();
-//! println!("{}", x);
-//!
-//! let x = counter.next().unwrap();
-//! println!("{}", x);
-//!
-//! let x = counter.next().unwrap();
-//! println!("{}", x);
-//!
-//! let x = counter.next().unwrap();
-//! println!("{}", x);
+//! assert_eq!(counter.next(), Some(1));
+//! assert_eq!(counter.next(), Some(2));
+//! assert_eq!(counter.next(), Some(3));
+//! assert_eq!(counter.next(), Some(4));
+//! assert_eq!(counter.next(), Some(5));
+//! assert_eq!(counter.next(), None);
 //! ```
 //!
-//! This will print `1` through `5`, each on their own line.
-//!
-//! Calling `next()` this way gets repetitive. Rust has a construct which can
-//! call `next()` on your iterator, until it reaches `None`. Let's go over that
+//! Calling [`next`] this way gets repetitive. Rust has a construct which can
+//! call [`next`] on your iterator, until it reaches `None`. Let's go over that
 //! next.
 //!
 //! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold`
 //! ```
 //!
 //! The idiomatic way to write a [`map`] for its side effects is to use a
-//! `for` loop instead:
+//! `for` loop or call the [`for_each`] method:
 //!
 //! ```
 //! let v = vec![1, 2, 3, 4, 5];
 //!
+//! v.iter().for_each(|x| println!("{}", x));
+//! // or
 //! for x in &v {
 //!     println!("{}", x);
 //! }
 //! ```
 //!
 //! [`map`]: trait.Iterator.html#method.map
+//! [`for_each`]: trait.Iterator.html#method.for_each
 //!
-//! The two most common ways to evaluate an iterator are to use a `for` loop
-//! like this, or using the [`collect`] method to produce a new collection.
+//! Another common way to evaluate an iterator is to use the [`collect`]
+//! method to produce a new collection.
 //!
 //! [`collect`]: trait.Iterator.html#method.collect
 //!
index 0819969b9336088b700d32aa800430e3d5a9ab89..1b67b05c73021de024b6f38612dffc6f088cb470 100644 (file)
 #[allow(unused)]
 use prelude::v1::*;
 
+#[cfg(not(test))] // See #65860
 #[macro_use]
 mod macros;
 
 
 /* Core language traits */
 
+#[cfg(not(test))] // See #65860
 pub mod marker;
 pub mod ops;
+#[cfg(not(test))] // See #65860
 pub mod cmp;
+#[cfg(not(test))] // See #65860
 pub mod clone;
+#[cfg(not(test))] // See #65860
 pub mod default;
 pub mod convert;
 pub mod borrow;
 /* Core types and methods on primitives */
 
 pub mod any;
+#[cfg(not(test))] // See #65860
 pub mod array;
 pub mod ascii;
 pub mod sync;
 pub mod char;
 pub mod panic;
 pub mod panicking;
+#[cfg(not(test))] // See #65860
 pub mod pin;
+#[cfg(not(test))] // See #65860
 pub mod iter;
 pub mod option;
 pub mod raw;
 pub mod ffi;
 
 pub mod slice;
+#[cfg(not(test))] // See #65860
 pub mod str;
+#[cfg(not(test))] // See #65860
 pub mod hash;
+#[cfg(not(test))] // See #65860
 pub mod fmt;
 pub mod time;
 
 pub mod unicode;
 
 /* Async */
+#[cfg(not(test))] // See #65860
 pub mod future;
 pub mod task;
 
index 22e7573eca65b28c5693df365dc17af90fa5ed32..5730088c4d9a95a9f21f48609074c677138385f6 100644 (file)
@@ -466,11 +466,10 @@ pub fn from_bits(v: u32) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let bytes = 12.5f32.to_be_bytes();
     /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn to_be_bytes(self) -> [u8; 4] {
         self.to_bits().to_be_bytes()
@@ -482,11 +481,10 @@ pub fn from_bits(v: u32) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let bytes = 12.5f32.to_le_bytes();
     /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn to_le_bytes(self) -> [u8; 4] {
         self.to_bits().to_le_bytes()
@@ -504,7 +502,6 @@ pub fn from_bits(v: u32) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let bytes = 12.5f32.to_ne_bytes();
     /// assert_eq!(
     ///     bytes,
@@ -515,7 +512,7 @@ pub fn from_bits(v: u32) -> Self {
     ///     }
     /// );
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn to_ne_bytes(self) -> [u8; 4] {
         self.to_bits().to_ne_bytes()
@@ -526,11 +523,10 @@ pub fn from_bits(v: u32) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let value = f32::from_be_bytes([0x41, 0x48, 0x00, 0x00]);
     /// assert_eq!(value, 12.5);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn from_be_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_be_bytes(bytes))
@@ -541,11 +537,10 @@ pub fn from_bits(v: u32) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let value = f32::from_le_bytes([0x00, 0x00, 0x48, 0x41]);
     /// assert_eq!(value, 12.5);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn from_le_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_le_bytes(bytes))
@@ -563,7 +558,6 @@ pub fn from_bits(v: u32) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let value = f32::from_ne_bytes(if cfg!(target_endian = "big") {
     ///     [0x41, 0x48, 0x00, 0x00]
     /// } else {
@@ -571,7 +565,7 @@ pub fn from_bits(v: u32) -> Self {
     /// });
     /// assert_eq!(value, 12.5);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn from_ne_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_ne_bytes(bytes))
index bbe1d040780602df44831bab76ff835a01da7898..2bdeda340dce01c19d7d60c2aaa08c1c5a6baaea 100644 (file)
@@ -479,11 +479,10 @@ pub fn from_bits(v: u64) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let bytes = 12.5f64.to_be_bytes();
     /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn to_be_bytes(self) -> [u8; 8] {
         self.to_bits().to_be_bytes()
@@ -495,11 +494,10 @@ pub fn from_bits(v: u64) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let bytes = 12.5f64.to_le_bytes();
     /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn to_le_bytes(self) -> [u8; 8] {
         self.to_bits().to_le_bytes()
@@ -517,7 +515,6 @@ pub fn from_bits(v: u64) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let bytes = 12.5f64.to_ne_bytes();
     /// assert_eq!(
     ///     bytes,
@@ -528,7 +525,7 @@ pub fn from_bits(v: u64) -> Self {
     ///     }
     /// );
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn to_ne_bytes(self) -> [u8; 8] {
         self.to_bits().to_ne_bytes()
@@ -539,11 +536,10 @@ pub fn from_bits(v: u64) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
     /// assert_eq!(value, 12.5);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn from_be_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_be_bytes(bytes))
@@ -554,11 +550,10 @@ pub fn from_bits(v: u64) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
     /// assert_eq!(value, 12.5);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn from_le_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_le_bytes(bytes))
@@ -576,7 +571,6 @@ pub fn from_bits(v: u64) -> Self {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_to_from_bytes)]
     /// let value = f64::from_ne_bytes(if cfg!(target_endian = "big") {
     ///     [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
     /// } else {
@@ -584,7 +578,7 @@ pub fn from_bits(v: u64) -> Self {
     /// });
     /// assert_eq!(value, 12.5);
     /// ```
-    #[unstable(feature = "float_to_from_bytes", issue = "60446")]
+    #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
     #[inline]
     pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_ne_bytes(bytes))
index 76fec1020f1eff572d8c8c5890efeffce81bc207..e8f35f8cf245025925decf4771c869b8213923d6 100644 (file)
@@ -5,7 +5,7 @@
 /// extracting those success or failure values from an existing instance and
 /// creating a new instance from a success or failure value.
 #[unstable(feature = "try_trait", issue = "42327")]
-#[rustc_on_unimplemented(
+#[cfg_attr(bootstrap, rustc_on_unimplemented(
    on(all(
        any(from_method="from_error", from_method="from_ok"),
        from_desugaring="QuestionMark"),
       message="the `?` operator can only be applied to values \
                that implement `{Try}`",
       label="the `?` operator cannot be applied to type `{Self}`")
-)]
+))]
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
+on(all(
+any(from_method="from_error", from_method="from_ok"),
+from_desugaring="QuestionMark"),
+message="the `?` operator can only be used in {ItemContext} \
+               that returns `Result` or `Option` \
+               (or another type that implements `{Try}`)",
+label="cannot use the `?` operator in {ItemContext} that returns `{Self}`"),
+on(all(from_method="into_result", from_desugaring="QuestionMark"),
+message="the `?` operator can only be applied to values \
+               that implement `{Try}`",
+label="the `?` operator cannot be applied to type `{Self}`")
+))]
 #[doc(alias = "?")]
 pub trait Try {
     /// The type of this value when viewed as successful.
index 3cc0a1cd75e88f393dafa92680dcb0b807e048f3..1355ce1aa43b736272b5f51b3eb260ce6be44d3d 100644 (file)
@@ -1286,7 +1286,22 @@ pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
     /// }
     /// ```
     #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    #[cfg(not(bootstrap))]
+    #[rustc_const_unstable(feature = "const_ptr_offset_from")]
     #[inline]
+    pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
+        let pointee_size = mem::size_of::<T>();
+        let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize;
+        // assert that the pointee size is valid in a const eval compatible way
+        // FIXME: do this with a real assert at some point
+        [()][(!ok) as usize];
+        intrinsics::ptr_offset_from(self, origin)
+    }
+
+    #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    #[inline]
+    #[cfg(bootstrap)]
+    /// bootstrap
     pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
         let pointee_size = mem::size_of::<T>();
         assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
@@ -2013,8 +2028,9 @@ pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
     /// }
     /// ```
     #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    #[rustc_const_unstable(feature = "const_ptr_offset_from")]
     #[inline]
-    pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
+    pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
         (self as *const T).offset_from(origin)
     }
 
index 07fa2971847f65d5d49df89a547e3b6c8ca86d75..1e9e7e4b8359ce393f72d5e7ac32e61708e4d93c 100644 (file)
@@ -51,7 +51,7 @@ pub enum EHAction {
 
 pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));
 
-pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>)
+pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>, foreign_exception: bool)
     -> Result<EHAction, ()>
 {
     if lsda.is_null() {
@@ -96,7 +96,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>)
                     return Ok(EHAction::None)
                 } else {
                     let lpad = lpad_base + cs_lpad;
-                    return Ok(interpret_cs_action(cs_action, lpad))
+                    return Ok(interpret_cs_action(cs_action, lpad, foreign_exception))
                 }
             }
         }
@@ -121,16 +121,23 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>)
                 // Can never have null landing pad for sjlj -- that would have
                 // been indicated by a -1 call site index.
                 let lpad = (cs_lpad + 1) as usize;
-                return Ok(interpret_cs_action(cs_action, lpad))
+                return Ok(interpret_cs_action(cs_action, lpad, foreign_exception))
             }
         }
     }
 }
 
-fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
+fn interpret_cs_action(cs_action: u64, lpad: usize, foreign_exception: bool) -> EHAction {
     if cs_action == 0 {
+        // If cs_action is 0 then this is a cleanup (Drop::drop). We run these
+        // for both Rust panics and foriegn exceptions.
         EHAction::Cleanup(lpad)
+    } else if foreign_exception {
+        // catch_unwind should not catch foreign exceptions, only Rust panics.
+        // Instead just continue unwinding.
+        EHAction::None
     } else {
+        // Stop unwinding Rust panics at catch_unwind.
         EHAction::Catch(lpad)
     }
 }
index 18e9006468ef3500c6b7f4de3d79d2a440673013..3d0d5a4151eed925b1716bf0e8a9a22b86f559a1 100644 (file)
 use libc::{self, c_int};
 use unwind as uw;
 
+// This matches the layout of std::type_info in C++
+#[repr(C)]
+struct TypeInfo {
+    vtable: *const usize,
+    name: *const u8,
+}
+unsafe impl Sync for TypeInfo {}
+
+extern "C" {
+    // The leading `\x01` byte here is actually a magical signal to LLVM to
+    // *not* apply any other mangling like prefixing with a `_` character.
+    //
+    // This symbol is the vtable used by C++'s `std::type_info`. Objects of type
+    // `std::type_info`, type descriptors, have a pointer to this table. Type
+    // descriptors are referenced by the C++ EH structures defined above and
+    // that we construct below.
+    //
+    // Note that the real size is larger than 3 usize, but we only need our
+    // vtable to point to the third element.
+    #[link_name = "\x01_ZTVN10__cxxabiv117__class_type_infoE"]
+    static CLASS_TYPE_INFO_VTABLE: [usize; 3];
+}
+
+// std::type_info for a rust_panic class
+#[lang = "eh_catch_typeinfo"]
+static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo {
+    // Normally we would use .as_ptr().add(2) but this doesn't work in a const context.
+    vtable: unsafe { &CLASS_TYPE_INFO_VTABLE[2] },
+    // This intentionally doesn't use the normal name mangling scheme because
+    // we don't want C++ to be able to produce or catch Rust panics.
+    name: b"rust_panic\0".as_ptr(),
+};
+
 pub fn payload() -> *mut u8 {
     ptr::null_mut()
 }
 
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     assert!(!ptr.is_null());
-    let ex = ptr::read(ptr as *mut _);
-    __cxa_free_exception(ptr as *mut _);
+    let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void);
+    let ex = ptr::read(adjusted_ptr as *mut _);
+    __cxa_end_catch();
     ex
 }
 
@@ -32,11 +66,8 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     if exception == ptr::null_mut() {
         return uw::_URC_FATAL_PHASE1_ERROR as u32;
     }
-    let exception = exception as *mut Box<dyn Any + Send>;
-    ptr::write(exception, data);
-    __cxa_throw(exception as *mut _, ptr::null_mut(), ptr::null_mut());
-
-    unreachable!()
+    ptr::write(exception as *mut _, data);
+    __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, ptr::null_mut());
 }
 
 #[lang = "eh_personality"]
@@ -52,10 +83,11 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
 
 extern "C" {
     fn __cxa_allocate_exception(thrown_size: libc::size_t) -> *mut libc::c_void;
-    fn __cxa_free_exception(thrown_exception: *mut libc::c_void);
+    fn __cxa_begin_catch(thrown_exception: *mut libc::c_void) -> *mut libc::c_void;
+    fn __cxa_end_catch();
     fn __cxa_throw(thrown_exception: *mut libc::c_void,
-                   tinfo: *mut libc::c_void,
-                   dest: *mut libc::c_void);
+                   tinfo: *const TypeInfo,
+                   dest: *mut libc::c_void) -> !;
     fn __gxx_personality_v0(version: c_int,
                             actions: uw::_Unwind_Action,
                             exception_class: uw::_Unwind_Exception_Class,
index a35847c85fc206476f78174e406781cca340c90b..4f572fe21b30baeb36ded4232fba107fdc38465e 100644 (file)
@@ -133,133 +133,176 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
 // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
 
-// The personality routine for most of our targets, except ARM, which has a slightly different ABI
-// (however, iOS goes here as it uses SjLj unwinding).  Also, the 64-bit Windows implementation
-// lives in seh64_gnu.rs
-#[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm"))))]
-#[lang = "eh_personality"]
-#[no_mangle]
-#[allow(unused)]
-unsafe extern "C" fn rust_eh_personality(version: c_int,
-                                         actions: uw::_Unwind_Action,
-                                         exception_class: uw::_Unwind_Exception_Class,
-                                         exception_object: *mut uw::_Unwind_Exception,
-                                         context: *mut uw::_Unwind_Context)
-                                         -> uw::_Unwind_Reason_Code {
-    if version != 1 {
-        return uw::_URC_FATAL_PHASE1_ERROR;
-    }
-    let eh_action = match find_eh_action(context) {
-        Ok(action) => action,
-        Err(_) => return uw::_URC_FATAL_PHASE1_ERROR,
-    };
-    if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
-        match eh_action {
-            EHAction::None |
-            EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
-            EHAction::Catch(_) => uw::_URC_HANDLER_FOUND,
-            EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR,
-        }
-    } else {
-        match eh_action {
-            EHAction::None => uw::_URC_CONTINUE_UNWIND,
-            EHAction::Cleanup(lpad) |
-            EHAction::Catch(lpad) => {
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
-                uw::_Unwind_SetIP(context, lpad);
-                uw::_URC_INSTALL_CONTEXT
-            }
-            EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
-        }
-    }
-}
+cfg_if::cfg_if! {
+    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))] {
+        // ARM EHABI personality routine.
+        // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
+        //
+        // iOS uses the default routine instead since it uses SjLj unwinding.
+        #[lang = "eh_personality"]
+        #[no_mangle]
+        unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
+                                                 exception_object: *mut uw::_Unwind_Exception,
+                                                 context: *mut uw::_Unwind_Context)
+                                                 -> uw::_Unwind_Reason_Code {
+            let state = state as c_int;
+            let action = state & uw::_US_ACTION_MASK as c_int;
+            let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
+                // Backtraces on ARM will call the personality routine with
+                // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
+                // we want to continue unwinding the stack, otherwise all our backtraces
+                // would end at __rust_try
+                if state & uw::_US_FORCE_UNWIND as c_int != 0 {
+                    return continue_unwind(exception_object, context);
+                }
+                true
+            } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
+                false
+            } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
+                return continue_unwind(exception_object, context);
+            } else {
+                return uw::_URC_FAILURE;
+            };
 
-// ARM EHABI personality routine.
-// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
-#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))]
-#[lang = "eh_personality"]
-#[no_mangle]
-unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
-                                         exception_object: *mut uw::_Unwind_Exception,
-                                         context: *mut uw::_Unwind_Context)
-                                         -> uw::_Unwind_Reason_Code {
-    let state = state as c_int;
-    let action = state & uw::_US_ACTION_MASK as c_int;
-    let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
-        // Backtraces on ARM will call the personality routine with
-        // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
-        // we want to continue unwinding the stack, otherwise all our backtraces
-        // would end at __rust_try
-        if state & uw::_US_FORCE_UNWIND as c_int != 0 {
-            return continue_unwind(exception_object, context);
-        }
-        true
-    } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
-        false
-    } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
-        return continue_unwind(exception_object, context);
-    } else {
-        return uw::_URC_FAILURE;
-    };
+            // The DWARF unwinder assumes that _Unwind_Context holds things like the function
+            // and LSDA pointers, however ARM EHABI places them into the exception object.
+            // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
+            // take only the context pointer, GCC personality routines stash a pointer to
+            // exception_object in the context, using location reserved for ARM's
+            // "scratch register" (r12).
+            uw::_Unwind_SetGR(context,
+                              uw::UNWIND_POINTER_REG,
+                              exception_object as uw::_Unwind_Ptr);
+            // ...A more principled approach would be to provide the full definition of ARM's
+            // _Unwind_Context in our libunwind bindings and fetch the required data from there
+            // directly, bypassing DWARF compatibility functions.
 
-    // The DWARF unwinder assumes that _Unwind_Context holds things like the function
-    // and LSDA pointers, however ARM EHABI places them into the exception object.
-    // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
-    // take only the context pointer, GCC personality routines stash a pointer to exception_object
-    // in the context, using location reserved for ARM's "scratch register" (r12).
-    uw::_Unwind_SetGR(context,
-                      uw::UNWIND_POINTER_REG,
-                      exception_object as uw::_Unwind_Ptr);
-    // ...A more principled approach would be to provide the full definition of ARM's
-    // _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
-    // bypassing DWARF compatibility functions.
+            let exception_class = (*exception_object).exception_class;
+            let foreign_exception = exception_class != rust_exception_class();
+            let eh_action = match find_eh_action(context, foreign_exception) {
+                Ok(action) => action,
+                Err(_) => return uw::_URC_FAILURE,
+            };
+            if search_phase {
+                match eh_action {
+                    EHAction::None |
+                    EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
+                    EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+                    EHAction::Terminate => return uw::_URC_FAILURE,
+                }
+            } else {
+                match eh_action {
+                    EHAction::None => return continue_unwind(exception_object, context),
+                    EHAction::Cleanup(lpad) |
+                    EHAction::Catch(lpad) => {
+                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0,
+                                          exception_object as uintptr_t);
+                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                        uw::_Unwind_SetIP(context, lpad);
+                        return uw::_URC_INSTALL_CONTEXT;
+                    }
+                    EHAction::Terminate => return uw::_URC_FAILURE,
+                }
+            }
 
-    let eh_action = match find_eh_action(context) {
-        Ok(action) => action,
-        Err(_) => return uw::_URC_FAILURE,
-    };
-    if search_phase {
-        match eh_action {
-            EHAction::None |
-            EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
-            EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
-            EHAction::Terminate => return uw::_URC_FAILURE,
+            // On ARM EHABI the personality routine is responsible for actually
+            // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
+            unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
+                                      context: *mut uw::_Unwind_Context)
+                                      -> uw::_Unwind_Reason_Code {
+                if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
+                    uw::_URC_CONTINUE_UNWIND
+                } else {
+                    uw::_URC_FAILURE
+                }
+            }
+            // defined in libgcc
+            extern "C" {
+                fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
+                                      context: *mut uw::_Unwind_Context)
+                                      -> uw::_Unwind_Reason_Code;
+            }
         }
     } else {
-        match eh_action {
-            EHAction::None => return continue_unwind(exception_object, context),
-            EHAction::Cleanup(lpad) |
-            EHAction::Catch(lpad) => {
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
-                uw::_Unwind_SetIP(context, lpad);
-                return uw::_URC_INSTALL_CONTEXT;
+        // Default personality routine, which is used directly on most targets
+        // and indirectly on Windows x86_64 via SEH.
+        unsafe extern "C" fn rust_eh_personality_impl(version: c_int,
+                                                      actions: uw::_Unwind_Action,
+                                                      exception_class: uw::_Unwind_Exception_Class,
+                                                      exception_object: *mut uw::_Unwind_Exception,
+                                                      context: *mut uw::_Unwind_Context)
+                                                      -> uw::_Unwind_Reason_Code {
+            if version != 1 {
+                return uw::_URC_FATAL_PHASE1_ERROR;
+            }
+            let foreign_exception = exception_class != rust_exception_class();
+            let eh_action = match find_eh_action(context, foreign_exception) {
+                Ok(action) => action,
+                Err(_) => return uw::_URC_FATAL_PHASE1_ERROR,
+            };
+            if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
+                match eh_action {
+                    EHAction::None |
+                    EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
+                    EHAction::Catch(_) => uw::_URC_HANDLER_FOUND,
+                    EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR,
+                }
+            } else {
+                match eh_action {
+                    EHAction::None => uw::_URC_CONTINUE_UNWIND,
+                    EHAction::Cleanup(lpad) |
+                    EHAction::Catch(lpad) => {
+                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0,
+                            exception_object as uintptr_t);
+                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                        uw::_Unwind_SetIP(context, lpad);
+                        uw::_URC_INSTALL_CONTEXT
+                    }
+                    EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
+                }
             }
-            EHAction::Terminate => return uw::_URC_FAILURE,
         }
-    }
 
-    // On ARM EHABI the personality routine is responsible for actually
-    // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
-    unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
-                              context: *mut uw::_Unwind_Context)
-                              -> uw::_Unwind_Reason_Code {
-        if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
-            uw::_URC_CONTINUE_UNWIND
-        } else {
-            uw::_URC_FAILURE
+        cfg_if::cfg_if! {
+            if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
+                // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind
+                // handler data (aka LSDA) uses GCC-compatible encoding.
+                #[lang = "eh_personality"]
+                #[no_mangle]
+                #[allow(nonstandard_style)]
+                unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut uw::EXCEPTION_RECORD,
+                        establisherFrame: uw::LPVOID,
+                        contextRecord: *mut uw::CONTEXT,
+                        dispatcherContext: *mut uw::DISPATCHER_CONTEXT)
+                        -> uw::EXCEPTION_DISPOSITION {
+                    uw::_GCC_specific_handler(exceptionRecord,
+                                             establisherFrame,
+                                             contextRecord,
+                                             dispatcherContext,
+                                             rust_eh_personality_impl)
+                }
+            } else {
+                // The personality routine for most of our targets.
+                #[lang = "eh_personality"]
+                #[no_mangle]
+                unsafe extern "C" fn rust_eh_personality(version: c_int,
+                        actions: uw::_Unwind_Action,
+                        exception_class: uw::_Unwind_Exception_Class,
+                        exception_object: *mut uw::_Unwind_Exception,
+                        context: *mut uw::_Unwind_Context)
+                        -> uw::_Unwind_Reason_Code {
+                    rust_eh_personality_impl(version,
+                                             actions,
+                                             exception_class,
+                                             exception_object,
+                                             context)
+                }
+            }
         }
     }
-    // defined in libgcc
-    extern "C" {
-        fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
-                              context: *mut uw::_Unwind_Context)
-                              -> uw::_Unwind_Reason_Code;
-    }
 }
 
-unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
+unsafe fn find_eh_action(context: *mut uw::_Unwind_Context, foreign_exception: bool)
     -> Result<EHAction, ()>
 {
     let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
@@ -273,11 +316,11 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
         get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
         get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
     };
-    eh::find_eh_action(lsda, &eh_context)
+    eh::find_eh_action(lsda, &eh_context, foreign_exception)
 }
 
 // See docs in the `unwind` module.
-#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
+#[cfg(all(target_os="windows", any(target_arch = "x86", target_arch = "x86_64"), target_env="gnu"))]
 #[lang = "eh_unwind_resume"]
 #[unwind(allowed)]
 unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
index 2089a02083c59a4d1855950d6d0e531231a21614..d2a0ef7b1dde1cce1e738918638c68266305e0cd 100644 (file)
@@ -5,9 +5,8 @@
 //! essentially gets categorized into three buckets currently:
 //!
 //! 1. MSVC targets use SEH in the `seh.rs` file.
-//! 2. The 64-bit MinGW target half-uses SEH and half-use gcc-like information
-//!    in the `seh64_gnu.rs` module.
-//! 3. All other targets use libunwind/libgcc in the `gcc/mod.rs` module.
+//! 2. Emscripten uses C++ exceptions in the `emcc.rs` file.
+//! 3. All other targets use libunwind/libgcc in the `gcc.rs` file.
 //!
 //! More documentation about each implementation can be found in the respective
 //! module.
@@ -52,9 +51,6 @@
     } else if #[cfg(target_env = "msvc")] {
         #[path = "seh.rs"]
         mod imp;
-    } else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
-        #[path = "seh64_gnu.rs"]
-        mod imp;
     } else {
         // Rust runtime's startup objects depend on these symbols, so make them public.
         #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
@@ -65,7 +61,6 @@
 }
 
 mod dwarf;
-mod windows;
 
 // Entry point for catching an exception, implemented using the `try` intrinsic
 // in the compiler.
index 809e4619812dec41c90575e81069f039e62e53d4..621813a2fee9550bccf5e8124ac7d5c9f04514c4 100644 (file)
@@ -51,9 +51,7 @@
 use core::any::Any;
 use core::mem;
 use core::raw;
-
-use crate::windows as c;
-use libc::{c_int, c_uint};
+use libc::{c_int, c_uint, c_void};
 
 // First up, a whole bunch of type definitions. There's a few platform-specific
 // oddities here, and a lot that's just blatantly copied from LLVM. The purpose
 // sort of operation. For example, if you compile this C++ code on MSVC and emit
 // the LLVM IR:
 //
-//      #include <stdin.h>
+//      #include <stdint.h>
+//
+//      struct rust_panic {
+//          uint64_t x[2];
+//      }
 //
 //      void foo() {
-//          uint64_t a[2] = {0, 1};
+//          rust_panic a = {0, 1};
 //          throw a;
 //      }
 //
 // That's essentially what we're trying to emulate. Most of the constant values
-// below were just copied from LLVM, I'm at least not 100% sure what's going on
-// everywhere. For example the `.PA_K\0` and `.PEA_K\0` strings below (stuck in
-// the names of a few of these) I'm not actually sure what they do, but it seems
-// to mirror what LLVM does!
+// below were just copied from LLVM,
 //
 // In any case, these structures are all constructed in a similar manner, and
 // it's just somewhat verbose for us.
 #[macro_use]
 mod imp {
     pub type ptr_t = *mut u8;
-    pub const OFFSET: i32 = 4;
 
+    #[cfg(bootstrap)]
     pub const NAME1: [u8; 7] = [b'.', b'P', b'A', b'_', b'K', 0, 0];
-    pub const NAME2: [u8; 7] = [b'.', b'P', b'A', b'X', 0, 0, 0];
 
     macro_rules! ptr {
         (0) => (core::ptr::null_mut());
@@ -113,10 +111,9 @@ macro_rules! ptr {
 #[macro_use]
 mod imp {
     pub type ptr_t = u32;
-    pub const OFFSET: i32 = 8;
 
+    #[cfg(bootstrap)]
     pub const NAME1: [u8; 7] = [b'.', b'P', b'E', b'A', b'_', b'K', 0];
-    pub const NAME2: [u8; 7] = [b'.', b'P', b'E', b'A', b'X', 0, 0];
 
     extern "C" {
         pub static __ImageBase: u8;
@@ -141,7 +138,7 @@ pub struct _ThrowInfo {
 #[repr(C)]
 pub struct _CatchableTypeArray {
     pub nCatchableTypes: c_int,
-    pub arrayOfCatchableTypes: [imp::ptr_t; 2],
+    pub arrayOfCatchableTypes: [imp::ptr_t; 1],
 }
 
 #[repr(C)]
@@ -164,9 +161,19 @@ pub struct _PMD {
 pub struct _TypeDescriptor {
     pub pVFTable: *const u8,
     pub spare: *mut u8,
+    #[cfg(bootstrap)]
     pub name: [u8; 7],
+    #[cfg(not(bootstrap))]
+    pub name: [u8; 11],
 }
 
+// Note that we intentionally ignore name mangling rules here: we don't want C++
+// to be able to catch Rust panics by simply declaring a `struct rust_panic`.
+#[cfg(bootstrap)]
+use imp::NAME1 as TYPE_NAME;
+#[cfg(not(bootstrap))]
+const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
+
 static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
     attributes: 0,
     pnfnUnwind: ptr!(0),
@@ -175,31 +182,22 @@ pub struct _TypeDescriptor {
 };
 
 static mut CATCHABLE_TYPE_ARRAY: _CatchableTypeArray = _CatchableTypeArray {
-    nCatchableTypes: 2,
-    arrayOfCatchableTypes: [ptr!(0), ptr!(0)],
+    nCatchableTypes: 1,
+    arrayOfCatchableTypes: [ptr!(0)],
 };
 
-static mut CATCHABLE_TYPE1: _CatchableType = _CatchableType {
-    properties: 1,
+static mut CATCHABLE_TYPE: _CatchableType = _CatchableType {
+    properties: 0,
     pType: ptr!(0),
     thisDisplacement: _PMD {
         mdisp: 0,
         pdisp: -1,
         vdisp: 0,
     },
-    sizeOrOffset: imp::OFFSET,
-    copy_function: ptr!(0),
-};
-
-static mut CATCHABLE_TYPE2: _CatchableType = _CatchableType {
-    properties: 1,
-    pType: ptr!(0),
-    thisDisplacement: _PMD {
-        mdisp: 0,
-        pdisp: -1,
-        vdisp: 0,
-    },
-    sizeOrOffset: imp::OFFSET,
+    #[cfg(bootstrap)]
+    sizeOrOffset: mem::size_of::<*mut u64>() as c_int,
+    #[cfg(not(bootstrap))]
+    sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int,
     copy_function: ptr!(0),
 };
 
@@ -215,22 +213,17 @@ pub struct _TypeDescriptor {
     static TYPE_INFO_VTABLE: *const u8;
 }
 
-// We use #[lang = "msvc_try_filter"] here as this is the type descriptor which
+// We use #[lang = "eh_catch_typeinfo"] here as this is the type descriptor which
 // we'll use in LLVM's `catchpad` instruction which ends up also being passed as
 // an argument to the C++ personality function.
 //
 // Again, I'm not entirely sure what this is describing, it just seems to work.
-#[cfg_attr(not(test), lang = "msvc_try_filter")]
-static mut TYPE_DESCRIPTOR1: _TypeDescriptor = _TypeDescriptor {
+#[cfg_attr(bootstrap, lang = "msvc_try_filter")]
+#[cfg_attr(not(any(test, bootstrap)), lang = "eh_catch_typeinfo")]
+static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
     pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
     spare: core::ptr::null_mut(),
-    name: imp::NAME1,
-};
-
-static mut TYPE_DESCRIPTOR2: _TypeDescriptor = _TypeDescriptor {
-    pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
-    spare: core::ptr::null_mut(),
-    name: imp::NAME2,
+    name: TYPE_NAME,
 };
 
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
@@ -246,6 +239,11 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     let ptrs = mem::transmute::<_, raw::TraitObject>(data);
     let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64];
     let mut ptrs_ptr = ptrs.as_mut_ptr();
+    let throw_ptr = if cfg!(bootstrap) {
+        &mut ptrs_ptr as *mut _ as *mut _
+    } else {
+        ptrs_ptr as *mut _
+    };
 
     // This... may seems surprising, and justifiably so. On 32-bit MSVC the
     // pointers between these structure are just that, pointers. On 64-bit MSVC,
@@ -270,17 +268,17 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     atomic_store(&mut THROW_INFO.pCatchableTypeArray as *mut _ as *mut u32,
                  ptr!(&CATCHABLE_TYPE_ARRAY as *const _) as u32);
     atomic_store(&mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0] as *mut _ as *mut u32,
-                 ptr!(&CATCHABLE_TYPE1 as *const _) as u32);
-    atomic_store(&mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[1] as *mut _ as *mut u32,
-                 ptr!(&CATCHABLE_TYPE2 as *const _) as u32);
-    atomic_store(&mut CATCHABLE_TYPE1.pType as *mut _ as *mut u32,
-                 ptr!(&TYPE_DESCRIPTOR1 as *const _) as u32);
-    atomic_store(&mut CATCHABLE_TYPE2.pType as *mut _ as *mut u32,
-                 ptr!(&TYPE_DESCRIPTOR2 as *const _) as u32);
+                 ptr!(&CATCHABLE_TYPE as *const _) as u32);
+    atomic_store(&mut CATCHABLE_TYPE.pType as *mut _ as *mut u32,
+                 ptr!(&TYPE_DESCRIPTOR as *const _) as u32);
+
+    extern "system" {
+        #[unwind(allowed)]
+        pub fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8) -> !;
+    }
 
-    c::_CxxThrowException(&mut ptrs_ptr as *mut _ as *mut _,
-                          &mut THROW_INFO as *mut _ as *mut _);
-    u32::max_value()
+    _CxxThrowException(throw_ptr,
+                       &mut THROW_INFO as *mut _ as *mut _);
 }
 
 pub fn payload() -> [u64; 2] {
diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs
deleted file mode 100644 (file)
index 16b699a..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-//! Unwinding implementation of top of native Win64 SEH,
-//! however the unwind handler data (aka LSDA) uses GCC-compatible encoding.
-
-#![allow(nonstandard_style)]
-#![allow(private_no_mangle_fns)]
-
-use alloc::boxed::Box;
-
-use core::any::Any;
-use core::intrinsics;
-use core::ptr;
-use crate::dwarf::eh::{EHContext, EHAction, find_eh_action};
-use crate::windows as c;
-
-// Define our exception codes:
-// according to http://msdn.microsoft.com/en-us/library/het71c37(v=VS.80).aspx,
-//    [31:30] = 3 (error), 2 (warning), 1 (info), 0 (success)
-//    [29]    = 1 (user-defined)
-//    [28]    = 0 (reserved)
-// we define bits:
-//    [24:27] = type
-//    [0:23]  = magic
-const ETYPE: c::DWORD = 0b1110_u32 << 28;
-const MAGIC: c::DWORD = 0x525354; // "RST"
-
-const RUST_PANIC: c::DWORD = ETYPE | (1 << 24) | MAGIC;
-
-#[repr(C)]
-struct PanicData {
-    data: Box<dyn Any + Send>,
-}
-
-pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
-    let panic_ctx = Box::new(PanicData { data });
-    let params = [Box::into_raw(panic_ctx) as c::ULONG_PTR];
-    c::RaiseException(RUST_PANIC,
-                      c::EXCEPTION_NONCONTINUABLE,
-                      params.len() as c::DWORD,
-                      &params as *const c::ULONG_PTR);
-    u32::max_value()
-}
-
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
-
-pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
-    let panic_ctx = Box::from_raw(ptr as *mut PanicData);
-    panic_ctx.data
-}
-
-// SEH doesn't support resuming unwinds after calling a landing pad like
-// libunwind does. For this reason, MSVC compiler outlines landing pads into
-// separate functions that can be called directly from the personality function
-// but are nevertheless able to find and modify stack frame of the "parent"
-// function.
-//
-// Since this cannot be done with libdwarf-style landing pads,
-// rust_eh_personality instead catches RUST_PANICs, runs the landing pad, then
-// reraises the exception.
-//
-// Note that it makes certain assumptions about the exception:
-//
-// 1. That RUST_PANIC is non-continuable, so no lower stack frame may choose to
-//    resume execution.
-// 2. That the first parameter of the exception is a pointer to an extra data
-//    area (PanicData).
-// Since these assumptions do not generally hold true for foreign exceptions
-// (system faults, C++ exceptions, etc), we make no attempt to invoke our
-// landing pads (and, thus, destructors!) for anything other than RUST_PANICs.
-// This is considered acceptable, because the behavior of throwing exceptions
-// through a C ABI boundary is undefined.
-
-#[lang = "eh_personality"]
-#[cfg(not(test))]
-unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut c::EXCEPTION_RECORD,
-                                         establisherFrame: c::LPVOID,
-                                         contextRecord: *mut c::CONTEXT,
-                                         dispatcherContext: *mut c::DISPATCHER_CONTEXT)
-                                         -> c::EXCEPTION_DISPOSITION {
-    let er = &*exceptionRecord;
-    let dc = &*dispatcherContext;
-
-    if er.ExceptionFlags & c::EXCEPTION_UNWIND == 0 {
-        // we are in the dispatch phase
-        if er.ExceptionCode == RUST_PANIC {
-            if let Some(lpad) = find_landing_pad(dc) {
-                c::RtlUnwindEx(establisherFrame,
-                               lpad as c::LPVOID,
-                               exceptionRecord,
-                               er.ExceptionInformation[0] as c::LPVOID, // pointer to PanicData
-                               contextRecord,
-                               dc.HistoryTable);
-            }
-        }
-    }
-    c::ExceptionContinueSearch
-}
-
-#[lang = "eh_unwind_resume"]
-#[unwind(allowed)]
-unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: c::LPVOID) -> ! {
-    let params = [panic_ctx as c::ULONG_PTR];
-    c::RaiseException(RUST_PANIC,
-                      c::EXCEPTION_NONCONTINUABLE,
-                      params.len() as c::DWORD,
-                      &params as *const c::ULONG_PTR);
-    intrinsics::abort();
-}
-
-unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option<usize> {
-    let eh_ctx = EHContext {
-        // The return address points 1 byte past the call instruction,
-        // which could be in the next IP range in LSDA range table.
-        ip: dc.ControlPc as usize - 1,
-        func_start: dc.ImageBase as usize + (*dc.FunctionEntry).BeginAddress as usize,
-        get_text_start: &|| dc.ImageBase as usize,
-        get_data_start: &|| unimplemented!(),
-    };
-    match find_eh_action(dc.HandlerData, &eh_ctx) {
-        Err(_) |
-        Ok(EHAction::None) => None,
-        Ok(EHAction::Cleanup(lpad)) |
-        Ok(EHAction::Catch(lpad)) => Some(lpad),
-        Ok(EHAction::Terminate) => intrinsics::abort(),
-    }
-}
diff --git a/src/libpanic_unwind/windows.rs b/src/libpanic_unwind/windows.rs
deleted file mode 100644 (file)
index 3257a9d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#![allow(nonstandard_style)]
-#![allow(dead_code)]
-#![cfg(windows)]
-
-use libc::{c_long, c_ulong, c_void};
-
-pub type DWORD = c_ulong;
-pub type LONG = c_long;
-pub type ULONG_PTR = usize;
-pub type LPVOID = *mut c_void;
-
-pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
-pub const EXCEPTION_NONCONTINUABLE: DWORD = 0x1;   // Noncontinuable exception
-pub const EXCEPTION_UNWINDING: DWORD = 0x2;        // Unwind is in progress
-pub const EXCEPTION_EXIT_UNWIND: DWORD = 0x4;      // Exit unwind is in progress
-pub const EXCEPTION_TARGET_UNWIND: DWORD = 0x20;   // Target unwind in progress
-pub const EXCEPTION_COLLIDED_UNWIND: DWORD = 0x40; // Collided exception handler call
-pub const EXCEPTION_UNWIND: DWORD = EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND |
-                                    EXCEPTION_TARGET_UNWIND |
-                                    EXCEPTION_COLLIDED_UNWIND;
-
-#[repr(C)]
-pub struct EXCEPTION_RECORD {
-    pub ExceptionCode: DWORD,
-    pub ExceptionFlags: DWORD,
-    pub ExceptionRecord: *mut EXCEPTION_RECORD,
-    pub ExceptionAddress: LPVOID,
-    pub NumberParameters: DWORD,
-    pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS],
-}
-
-#[repr(C)]
-pub struct EXCEPTION_POINTERS {
-    pub ExceptionRecord: *mut EXCEPTION_RECORD,
-    pub ContextRecord: *mut CONTEXT,
-}
-
-pub enum UNWIND_HISTORY_TABLE {}
-
-#[repr(C)]
-pub struct RUNTIME_FUNCTION {
-    pub BeginAddress: DWORD,
-    pub EndAddress: DWORD,
-    pub UnwindData: DWORD,
-}
-
-pub enum CONTEXT {}
-
-#[repr(C)]
-pub struct DISPATCHER_CONTEXT {
-    pub ControlPc: LPVOID,
-    pub ImageBase: LPVOID,
-    pub FunctionEntry: *const RUNTIME_FUNCTION,
-    pub EstablisherFrame: LPVOID,
-    pub TargetIp: LPVOID,
-    pub ContextRecord: *const CONTEXT,
-    pub LanguageHandler: LPVOID,
-    pub HandlerData: *const u8,
-    pub HistoryTable: *const UNWIND_HISTORY_TABLE,
-}
-
-#[repr(C)]
-pub enum EXCEPTION_DISPOSITION {
-    ExceptionContinueExecution,
-    ExceptionContinueSearch,
-    ExceptionNestedException,
-    ExceptionCollidedUnwind,
-}
-pub use self::EXCEPTION_DISPOSITION::*;
-
-extern "system" {
-    #[unwind(allowed)]
-    pub fn RaiseException(dwExceptionCode: DWORD,
-                          dwExceptionFlags: DWORD,
-                          nNumberOfArguments: DWORD,
-                          lpArguments: *const ULONG_PTR);
-    #[unwind(allowed)]
-    pub fn RtlUnwindEx(TargetFrame: LPVOID,
-                       TargetIp: LPVOID,
-                       ExceptionRecord: *const EXCEPTION_RECORD,
-                       ReturnValue: LPVOID,
-                       OriginalContext: *const CONTEXT,
-                       HistoryTable: *const UNWIND_HISTORY_TABLE);
-    #[unwind(allowed)]
-    pub fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8);
-}
index 5c543165bc2b19da1a271b65aa7331da77300b00..9643dba997aa475213b5a4556f077ce72b1582a9 100644 (file)
@@ -15,8 +15,9 @@ pub struct HandleCounters {
         }
 
         impl HandleCounters {
-            // FIXME(#53451) public to work around `Cannot create local mono-item` ICE.
-            pub extern "C" fn get() -> &'static Self {
+            // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of
+            // a wrapper `fn` pointer, once `const fn` can reference `static`s.
+            extern "C" fn get() -> &'static Self {
                 static COUNTERS: HandleCounters = HandleCounters {
                     $($oty: AtomicUsize::new(1),)*
                     $($ity: AtomicUsize::new(1),)*
@@ -333,16 +334,19 @@ fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct Client<F> {
+    // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of
+    // a wrapper `fn` pointer, once `const fn` can reference `static`s.
     pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
     pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>,
     pub(super) f: F,
 }
 
-// FIXME(#53451) public to work around `Cannot create local mono-item` ICE,
-// affecting not only the function itself, but also the `BridgeState` `thread_local!`.
-pub extern "C" fn __run_expand1(
+/// Client-side helper for handling client panics, entering the bridge,
+/// deserializing input and serializing output.
+// FIXME(eddyb) maybe replace `Bridge::enter` with this?
+fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
     mut bridge: Bridge<'_>,
-    f: fn(crate::TokenStream) -> crate::TokenStream,
+    f: impl FnOnce(A) -> R,
 ) -> Buffer<u8> {
     // The initial `cached_buffer` contains the input.
     let mut b = bridge.cached_buffer.take();
@@ -350,12 +354,12 @@ pub extern "C" fn __run_expand1(
     panic::catch_unwind(panic::AssertUnwindSafe(|| {
         bridge.enter(|| {
             let reader = &mut &b[..];
-            let input = TokenStream::decode(reader, &mut ());
+            let input = A::decode(reader, &mut ());
 
             // Put the `cached_buffer` back in the `Bridge`, for requests.
             Bridge::with(|bridge| bridge.cached_buffer = b.take());
 
-            let output = f(crate::TokenStream(input)).0;
+            let output = f(input);
 
             // Take the `cached_buffer` back out, for the output value.
             b = Bridge::with(|bridge| bridge.cached_buffer.take());
@@ -383,65 +387,35 @@ pub extern "C" fn __run_expand1(
 
 impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
     pub const fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
+        extern "C" fn run(
+            bridge: Bridge<'_>,
+            f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
+        ) -> Buffer<u8> {
+            run_client(bridge, |input| f(crate::TokenStream(input)).0)
+        }
         Client {
             get_handle_counters: HandleCounters::get,
-            run: __run_expand1,
+            run,
             f,
         }
     }
 }
 
-// FIXME(#53451) public to work around `Cannot create local mono-item` ICE,
-// affecting not only the function itself, but also the `BridgeState` `thread_local!`.
-pub extern "C" fn __run_expand2(
-    mut bridge: Bridge<'_>,
-    f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
-) -> Buffer<u8> {
-    // The initial `cached_buffer` contains the input.
-    let mut b = bridge.cached_buffer.take();
-
-    panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        bridge.enter(|| {
-            let reader = &mut &b[..];
-            let input = TokenStream::decode(reader, &mut ());
-            let input2 = TokenStream::decode(reader, &mut ());
-
-            // Put the `cached_buffer` back in the `Bridge`, for requests.
-            Bridge::with(|bridge| bridge.cached_buffer = b.take());
-
-            let output = f(crate::TokenStream(input), crate::TokenStream(input2)).0;
-
-            // Take the `cached_buffer` back out, for the output value.
-            b = Bridge::with(|bridge| bridge.cached_buffer.take());
-
-            // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
-            // from encoding a panic (`Err(e: PanicMessage)`) to avoid
-            // having handles outside the `bridge.enter(|| ...)` scope, and
-            // to catch panics that could happen while encoding the success.
-            //
-            // Note that panics should be impossible beyond this point, but
-            // this is defensively trying to avoid any accidental panicking
-            // reaching the `extern "C"` (which should `abort` but may not
-            // at the moment, so this is also potentially preventing UB).
-            b.clear();
-            Ok::<_, ()>(output).encode(&mut b, &mut ());
-        })
-    }))
-    .map_err(PanicMessage::from)
-    .unwrap_or_else(|e| {
-        b.clear();
-        Err::<(), _>(e).encode(&mut b, &mut ());
-    });
-    b
-}
-
 impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
     pub const fn expand2(
         f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream
     ) -> Self {
+        extern "C" fn run(
+            bridge: Bridge<'_>,
+            f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
+        ) -> Buffer<u8> {
+            run_client(bridge, |(input, input2)| {
+                f(crate::TokenStream(input), crate::TokenStream(input2)).0
+            })
+        }
         Client {
             get_handle_counters: HandleCounters::get,
-            run: __run_expand2,
+            run,
             f,
         }
     }
index a50cc86862e57903983608ab6aa4cb5db1958244..498600f1e901d44f88369f08aa39fee089c9c754 100644 (file)
@@ -867,6 +867,9 @@ fn strip_generic_default_params(
     /// Compares two given types, eliding parts that are the same between them and highlighting
     /// relevant differences, and return two representation of those types for highlighted printing.
     fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) {
+        debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind, t2, t2.kind);
+
+        // helper functions
         fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
             match (&a.kind, &b.kind) {
                 (a, b) if *a == *b => true,
@@ -902,6 +905,7 @@ fn push_ty_ref<'tcx>(
             s.push_normal(ty.to_string());
         }
 
+        // process starts here
         match (&t1.kind, &t2.kind) {
             (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
                 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
@@ -1052,12 +1056,47 @@ fn lifetime_display(lifetime: Region<'_>) -> String {
                         return values;
                     }
 
-                    // We couldn't find anything in common, highlight everything.
-                    //     let x: Bar<Qux> = y::<Foo<Zar>>();
-                    (
-                        DiagnosticStyledString::highlighted(t1.to_string()),
-                        DiagnosticStyledString::highlighted(t2.to_string()),
-                    )
+                    // We can't find anything in common, highlight relevant part of type path.
+                    //     let x: foo::bar::Baz<Qux> = y:<foo::bar::Bar<Zar>>();
+                    //     foo::bar::Baz<Qux>
+                    //     foo::bar::Bar<Zar>
+                    //               -------- this part of the path is different
+
+                    let t1_str = t1.to_string();
+                    let t2_str = t2.to_string();
+                    let min_len = t1_str.len().min(t2_str.len());
+
+                    const SEPARATOR: &str = "::";
+                    let separator_len = SEPARATOR.len();
+                    let split_idx: usize =
+                        t1_str.split(SEPARATOR)
+                            .zip(t2_str.split(SEPARATOR))
+                            .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
+                            .map(|(mod_str, _)| mod_str.len() + separator_len)
+                            .sum();
+
+                    debug!("cmp: separator_len={}, split_idx={}, min_len={}",
+                        separator_len, split_idx, min_len
+                    );
+
+                    if split_idx >= min_len {
+                        // paths are identical, highlight everything
+                        (
+                            DiagnosticStyledString::highlighted(t1_str),
+                            DiagnosticStyledString::highlighted(t2_str)
+                        )
+                    } else {
+                        let (common, uniq1) = t1_str.split_at(split_idx);
+                        let (_, uniq2) = t2_str.split_at(split_idx);
+                        debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
+
+                        values.0.push_normal(common);
+                        values.0.push_highlighted(uniq1);
+                        values.1.push_normal(common);
+                        values.1.push_highlighted(uniq2);
+
+                        values
+                    }
                 }
             }
 
@@ -1120,6 +1159,7 @@ pub fn note_type_err(
             _ => {}
         }
 
+        debug!("note_type_err(diag={:?})", diag);
         let (expected_found, exp_found, is_simple_error) = match values {
             None => (None, None, false),
             Some(values) => {
@@ -1180,6 +1220,10 @@ pub fn note_type_err(
                     diag.note_unsuccessfull_coercion(found, expected);
                 }
                 (_, false, _) => {
+                    debug!(
+                        "note_type_err: exp_found={:?}, expected={:?} found={:?}",
+                        exp_found, expected, found
+                    );
                     if let Some(exp_found) = exp_found {
                         self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
                     }
index 9c362a5e20791973fa3d360b6d26b6211fe7c63f..f4751e591bf3ce65984531014a7df239a0a133eb 100644 (file)
@@ -62,7 +62,7 @@ fn find_component_for_bound_region(
         &self,
         arg: &'tcx hir::Ty,
         br: &ty::BoundRegion,
-    ) -> Option<(&'tcx hir::Ty)> {
+    ) -> Option<&'tcx hir::Ty> {
         let mut nested_visitor = FindNestedTypeVisitor {
             tcx: self.tcx(),
             bound_region: *br,
index 1edb1c601bf1aa2d485e463777a384b563c0b799..cd003aa8dab708cc570b9e6800de28146af9f3f4 100644 (file)
@@ -12,6 +12,7 @@
 mod placeholder_error;
 mod outlives_closure;
 mod static_impl_trait;
+mod trait_impl_difference;
 mod util;
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
@@ -73,6 +74,7 @@ pub fn try_report(&self) -> Option<ErrorReported> {
             .or_else(|| self.try_report_anon_anon_conflict())
             .or_else(|| self.try_report_outlives_closure())
             .or_else(|| self.try_report_static_impl_trait())
+            .or_else(|| self.try_report_impl_not_conforming_to_trait())
     }
 
     pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs
new file mode 100644 (file)
index 0000000..0194300
--- /dev/null
@@ -0,0 +1,59 @@
+//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
+
+use syntax_pos::Span;
+use crate::ty::Ty;
+use crate::infer::{ValuePairs, Subtype};
+use crate::infer::error_reporting::nice_region_error::NiceRegionError;
+use crate::infer::lexical_region_resolve::RegionResolutionError;
+use crate::util::common::ErrorReported;
+use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
+
+impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
+    /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
+    pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
+        if let Some(ref error) = self.error {
+            debug!("try_report_impl_not_conforming_to_trait {:?}", error);
+            if let RegionResolutionError::SubSupConflict(
+                _,
+                var_origin,
+                sub_origin,
+                _sub,
+                sup_origin,
+                _sup,
+            ) = error.clone() {
+                match (&sup_origin, &sub_origin) {
+                    (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) => {
+                        if let (
+                            ValuePairs::Types(sub_expected_found),
+                            ValuePairs::Types(sup_expected_found),
+                            CompareImplMethodObligation { trait_item_def_id, .. },
+                        ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) {
+                            if sup_expected_found == sub_expected_found {
+                                self.emit_err(
+                                    var_origin.span(),
+                                    sub_expected_found.expected,
+                                    sub_expected_found.found,
+                                    self.tcx().def_span(*trait_item_def_id),
+                                );
+                                return Some(ErrorReported);
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
+        None
+    }
+
+    fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Span) {
+        let mut err = self.tcx().sess.struct_span_err(
+            sp,
+            "`impl` item signature doesn't match `trait` item signature",
+        );
+        err.note(&format!("expected `{:?}`\n   found `{:?}`", expected, found));
+        err.span_label(sp, &format!("found {:?}", found));
+        err.span_label(impl_sp, &format!("expected {:?}", expected));
+        err.emit();
+    }
+}
index d5558db2397e797cd14f4297ebc0bc1a07fa2eb1..1f4086227327e2af7111e594112e3b17a363b43b 100644 (file)
@@ -216,6 +216,7 @@ pub trait CrateStore {
     fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
+    fn crate_host_hash_untracked(&self, cnum: CrateNum) -> Option<Svh>;
     fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
 
index 72fb1fd3561f01b6f92d446ad505fb03902ad087..41f02a876f5977cf13d44d5b684362a8952cb544 100644 (file)
@@ -385,7 +385,7 @@ pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
 
     EhPersonalityLangItem,       "eh_personality",     eh_personality,          Target::Fn;
     EhUnwindResumeLangItem,      "eh_unwind_resume",   eh_unwind_resume,        Target::Fn;
-    MSVCTryFilterLangItem,       "msvc_try_filter",    msvc_try_filter,         Target::Static;
+    EhCatchTypeinfoLangItem,     "eh_catch_typeinfo",  eh_catch_typeinfo,       Target::Static;
 
     OwnedBoxLangItem,            "owned_box",          owned_box,               Target::Struct;
 
index d13b21bb7722b94dd157b6ea6cb8265cd828808f..86ed2419e048b0a5934a95c43b55d97388f0e795 100644 (file)
             eval_always
             desc { "looking up the hash a crate" }
         }
+        query crate_host_hash(_: CrateNum) -> Option<Svh> {
+            eval_always
+            desc { "looking up the hash of a host version of a crate" }
+        }
         query original_crate_name(_: CrateNum) -> Symbol {
             eval_always
             desc { "looking up the original name a crate" }
index 8bf4765111d36cae823d9477b95e50afa7a6fc6b..81f0853201c08b5f5afba7b9b6f5ad9e9115a4f6 100644 (file)
@@ -312,6 +312,9 @@ pub fn err_count(&self) -> usize {
     pub fn has_errors(&self) -> bool {
         self.diagnostic().has_errors()
     }
+    pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
+        self.diagnostic().has_errors_or_delayed_span_bugs()
+    }
     pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
index b55c0f29a70ec0fb6b509f2e95601bc830b6a260..1f7bce1c644c51ab5c0cfed709ed6aff3eda5480 100644 (file)
@@ -226,13 +226,26 @@ fn report_projection_error(
                     0,
                     &mut obligations
                 );
+
+                debug!("report_projection_error obligation.cause={:?} obligation.param_env={:?}",
+                       obligation.cause, obligation.param_env);
+
+                debug!("report_projection_error normalized_ty={:?} data.ty={:?}",
+                       normalized_ty, data.ty);
+
+                let is_normalized_ty_expected = match &obligation.cause.code {
+                    ObligationCauseCode::ItemObligation(_) |
+                    ObligationCauseCode::BindingObligation(_, _) |
+                    ObligationCauseCode::ObjectCastObligation(_) => false,
+                    _ => true,
+                };
+
                 if let Err(error) = self.at(&obligation.cause, obligation.param_env)
-                    .eq(normalized_ty, data.ty)
+                    .eq_exp(is_normalized_ty_expected, normalized_ty, data.ty)
                 {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound {
-                        expected: normalized_ty,
-                        found: data.ty,
-                    }));
+                    values = Some(infer::ValuePairs::Types(
+                        ExpectedFound::new(is_normalized_ty_expected, normalized_ty, data.ty)));
+
                     err_buf = error;
                     err = &err_buf;
                 }
@@ -353,6 +366,52 @@ fn impl_similar_to(&self,
         }
     }
 
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| {
+            match gen_kind {
+                hir::GeneratorKind::Gen => "a generator",
+                hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+                hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+                hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+            }
+        })
+    }
+
+    /// Used to set on_unimplemented's `ItemContext`
+    /// to be the enclosing (async) block/function/closure
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
+        let hir = &self.tcx.hir();
+        let node = hir.find(hir_id)?;
+        if let hir::Node::Item(
+            hir::Item{kind: hir::ItemKind::Fn(_ ,fn_header ,_ , body_id), .. }) = &node {
+            self.describe_generator(*body_id).or_else(||
+                Some(if let hir::FnHeader{ asyncness: hir::IsAsync::Async, .. } = fn_header {
+                    "an async function"
+                } else {
+                    "a function"
+                })
+            )
+        } else if let hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability), .. }) = &node {
+            self.describe_generator(*body_id).or_else(||
+                Some(if gen_movability.is_some() {
+                    "an async closure"
+                } else {
+                    "a closure"
+                })
+            )
+        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
+            let parent_hid = hir.get_parent_node(hir_id);
+            if parent_hid != hir_id {
+                return self.describe_enclosure(parent_hid);
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
     fn on_unimplemented_note(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
@@ -363,6 +422,9 @@ fn on_unimplemented_note(
         let trait_ref = *trait_ref.skip_binder();
 
         let mut flags = vec![];
+        flags.push((sym::item_context,
+            self.describe_enclosure(obligation.cause.body_id).map(|s|s.to_owned())));
+
         match obligation.cause.code {
             ObligationCauseCode::BuiltinDerivedObligation(..) |
             ObligationCauseCode::ImplDerivedObligation(..) => {}
index e42c3a63541ccdea8ccdc4f16360329452e84d3c..8ded1417ee570985e8d32d1cb62c9e70a735dd45 100644 (file)
@@ -520,9 +520,11 @@ fn object_ty_for_trait(self, trait_def_id: DefId, lifetime: ty::Region<'tcx>) ->
     /// a pointer.
     ///
     /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
-    /// in a new check that `Trait` is object safe, creating a cycle. So instead, we fudge a little
-    /// by introducing a new type parameter `U` such that `Self: Unsize<U>` and `U: Trait + ?Sized`,
-    /// and use `U` in place of `dyn Trait`. Written as a chalk-style query:
+    /// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
+    /// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
+    /// Instead, we fudge a little by introducing a new type parameter `U` such that
+    /// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
+    /// Written as a chalk-style query:
     ///
     ///     forall (U: Trait + ?Sized) {
     ///         if (Self: Unsize<U>) {
@@ -556,8 +558,8 @@ fn receiver_is_dispatchable(
 
         // the type `U` in the query
         // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
-        // FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries
-        // are implemented
+        // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
+        // replace this with `dyn Trait`
         let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
             ::std::u32::MAX,
             Symbol::intern("RustaceansAreAwesome"),
index c1c814f9b0371218a0415b78d2b8479cd394cd4e..b39c00a56e349ad13c5933b9f6e55c9f69d1b176 100644 (file)
@@ -248,6 +248,8 @@ fn verify(
                     Position::ArgumentNamed(s) if s == sym::from_method => (),
                     // `{from_desugaring}` is allowed
                     Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
+                    // `{ItemContext}` is allowed
+                    Position::ArgumentNamed(s) if s == sym::item_context => (),
                     // So is `{A}` if A is a type parameter
                     Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
                         param.name == s
@@ -296,6 +298,7 @@ pub fn format(
 
         let s = self.0.as_str();
         let parser = Parser::new(&s, None, vec![], false);
+        let item_context = (options.get(&sym::item_context)).unwrap_or(&empty_string);
         parser.map(|p|
             match p {
                 Piece::String(s) => s,
@@ -311,6 +314,8 @@ pub fn format(
                             } else if s == sym::from_desugaring || s == sym::from_method {
                                 // don't break messages using these two arguments incorrectly
                                 &empty_string
+                            } else if s == sym::item_context {
+                                &item_context
                             } else {
                                 bug!("broken on_unimplemented {:?} for {:?}: \
                                       no argument matching {:?}",
index bdf9b2d7f3f27f435046f9abae4b34f15089c4d7..3d28beefb3413f0dea2b38ed691f6ac822ca92d5 100644 (file)
@@ -1514,8 +1514,14 @@ pub fn local_crate_exports_generics(self) -> bool {
                 CrateType::Executable |
                 CrateType::Staticlib  |
                 CrateType::ProcMacro  |
-                CrateType::Dylib      |
                 CrateType::Cdylib     => false,
+
+                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
+                // We want to block export of generics from dylibs,
+                // but we must fix rust-lang/rust#65890 before we can
+                // do that robustly.
+                CrateType::Dylib      => true,
+
                 CrateType::Rlib       => true,
             }
         })
@@ -3015,6 +3021,10 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         assert_eq!(cnum, LOCAL_CRATE);
         tcx.arena.alloc_slice(&tcx.cstore.crates_untracked())
     };
+    providers.crate_host_hash = |tcx, cnum| {
+        assert_ne!(cnum, LOCAL_CRATE);
+        tcx.cstore.crate_host_hash_untracked(cnum)
+    };
     providers.postorder_cnums = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
         tcx.arena.alloc_slice(&tcx.cstore.postorder_cnums_untracked())
index bdb7467a1010c1b5e4c760f84f35cec3c6e906fc..6ee76b71fced68f3855833f6f6b352f058d3daa5 100644 (file)
@@ -1,4 +1,4 @@
-use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, FunctionDebugContextData, MirDebugScope};
+use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope};
 use super::metadata::file_metadata;
 use super::utils::{DIB, span_start};
 
 use syntax_pos::Pos;
 
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
-
-use syntax_pos::BytePos;
+use rustc_index::vec::Idx;
 
 /// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
-/// If debuginfo is disabled, the returned vector is empty.
-pub fn create_mir_scopes(
+pub fn compute_mir_scopes(
     cx: &CodegenCx<'ll, '_>,
     mir: &Body<'_>,
-    debug_context: &FunctionDebugContext<&'ll DISubprogram>,
-) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
-    let null_scope = MirDebugScope {
-        scope_metadata: None,
-        file_start_pos: BytePos(0),
-        file_end_pos: BytePos(0)
-    };
-    let mut scopes = IndexVec::from_elem(null_scope, &mir.source_scopes);
-
-    let debug_context = match *debug_context {
-        FunctionDebugContext::RegularContext(ref data) => data,
-        FunctionDebugContext::DebugInfoDisabled |
-        FunctionDebugContext::FunctionWithoutDebugInfo => {
-            return scopes;
-        }
-    };
-
+    fn_metadata: &'ll DISubprogram,
+    debug_context: &mut FunctionDebugContext<&'ll DIScope>,
+) {
     // Find all the scopes with variables defined in them.
     let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
+    // FIXME(eddyb) base this on `decl.name`, or even better, on debuginfo.
+    // FIXME(eddyb) take into account that arguments always have debuginfo,
+    // irrespective of their name (assuming full debuginfo is enabled).
     for var in mir.vars_iter() {
         let decl = &mir.local_decls[var];
         has_variables.insert(decl.visibility_scope);
@@ -48,31 +34,29 @@ pub fn create_mir_scopes(
     // Instantiate all scopes.
     for idx in 0..mir.source_scopes.len() {
         let scope = SourceScope::new(idx);
-        make_mir_scope(cx, &mir, &has_variables, debug_context, scope, &mut scopes);
+        make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope);
     }
-
-    scopes
 }
 
 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
                   mir: &Body<'_>,
+                  fn_metadata: &'ll DISubprogram,
                   has_variables: &BitSet<SourceScope>,
-                  debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
-                  scope: SourceScope,
-                  scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) {
-    if scopes[scope].is_valid() {
+                  debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
+                  scope: SourceScope) {
+    if debug_context.scopes[scope].is_valid() {
         return;
     }
 
     let scope_data = &mir.source_scopes[scope];
     let parent_scope = if let Some(parent) = scope_data.parent_scope {
-        make_mir_scope(cx, mir, has_variables, debug_context, parent, scopes);
-        scopes[parent]
+        make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent);
+        debug_context.scopes[parent]
     } else {
         // The root is the function itself.
         let loc = span_start(cx, mir.span);
-        scopes[scope] = MirDebugScope {
-            scope_metadata: Some(debug_context.fn_metadata),
+        debug_context.scopes[scope] = DebugScope {
+            scope_metadata: Some(fn_metadata),
             file_start_pos: loc.file.start_pos,
             file_end_pos: loc.file.end_pos,
         };
@@ -86,8 +70,8 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
         // However, we don't skip creating a nested scope if
         // our parent is the root, because we might want to
         // put arguments in the root and not have shadowing.
-        if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata {
-            scopes[scope] = parent_scope;
+        if parent_scope.scope_metadata.unwrap() != fn_metadata {
+            debug_context.scopes[scope] = parent_scope;
             return;
         }
     }
@@ -105,7 +89,7 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
             loc.line as c_uint,
             loc.col.to_usize() as c_uint))
     };
-    scopes[scope] = MirDebugScope {
+    debug_context.scopes[scope] = DebugScope {
         scope_metadata,
         file_start_pos: loc.file.start_pos,
         file_end_pos: loc.file.end_pos,
index 5b59f4c28de205248fe789f0e312daf5bd54ff74..7713fe47004b93182c0608c9a2bb56343ef2c901 100644 (file)
@@ -1,8 +1,7 @@
 // See doc.rs for documentation.
 mod doc;
 
-use rustc_codegen_ssa::debuginfo::VariableAccess::*;
-use rustc_codegen_ssa::debuginfo::VariableKind::*;
+use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
 
 use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
 use self::namespace::mangled_name_of_instance;
@@ -11,7 +10,7 @@
 use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
 
 use crate::llvm;
-use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
+use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DIArray, DIFlags,
     DISPFlags, DILexicalBlock};
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_index::vec::IndexVec;
-use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess,
-    VariableKind, FunctionDebugContextData, type_names};
+use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope,
+    VariableKind};
 
 use libc::c_uint;
 use std::cell::RefCell;
 use std::ffi::{CStr, CString};
 
-use syntax_pos::{self, Span, Pos};
+use smallvec::SmallVec;
+use syntax_pos::{self, BytePos, Span, Pos};
 use syntax::ast;
 use syntax::symbol::Symbol;
-use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
+use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Size};
 use rustc_codegen_ssa::traits::*;
 
 pub mod gdb;
@@ -47,7 +48,7 @@
 mod create_scope_map;
 mod source_loc;
 
-pub use self::create_scope_map::{create_mir_scopes};
+pub use self::create_scope_map::compute_mir_scopes;
 pub use self::metadata::create_global_var_metadata;
 pub use self::metadata::extend_scope_to_file;
 pub use self::source_loc::set_source_location;
@@ -148,21 +149,23 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
 impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn declare_local(
         &mut self,
-        dbg_context: &FunctionDebugContext<&'ll DISubprogram>,
+        dbg_context: &FunctionDebugContext<&'ll DIScope>,
         variable_name: ast::Name,
         variable_type: Ty<'tcx>,
         scope_metadata: &'ll DIScope,
-        variable_access: VariableAccess<'_, &'ll Value>,
+        variable_alloca: Self::Value,
+        direct_offset: Size,
+        indirect_offsets: &[Size],
         variable_kind: VariableKind,
         span: Span,
     ) {
-        assert!(!dbg_context.get_ref(span).source_locations_enabled);
+        assert!(!dbg_context.source_locations_enabled);
         let cx = self.cx();
 
         let file = span_start(cx, span).file;
         let file_metadata = file_metadata(cx,
                                           &file.name,
-                                          dbg_context.get_ref(span).defining_crate);
+                                          dbg_context.defining_crate);
 
         let loc = span_start(cx, span);
         let type_metadata = type_metadata(cx, variable_type, span);
@@ -173,49 +176,61 @@ fn declare_local(
         };
         let align = cx.align_of(variable_type);
 
-        let name = SmallCStr::new(&variable_name.as_str());
-        match (variable_access, &[][..]) {
-            (DirectVariable { alloca }, address_operations) |
-            (IndirectVariable {alloca, address_operations}, _) => {
-                let metadata = unsafe {
-                    llvm::LLVMRustDIBuilderCreateVariable(
-                        DIB(cx),
-                        dwarf_tag,
-                        scope_metadata,
-                        name.as_ptr(),
-                        file_metadata,
-                        loc.line as c_uint,
-                        type_metadata,
-                        cx.sess().opts.optimize != config::OptLevel::No,
-                        DIFlags::FlagZero,
-                        argument_index,
-                        align.bytes() as u32,
-                    )
-                };
-                source_loc::set_debug_location(self,
-                    InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
-                unsafe {
-                    let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
-                    let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
-                        DIB(cx),
-                        alloca,
-                        metadata,
-                        address_operations.as_ptr(),
-                        address_operations.len() as c_uint,
-                        debug_loc,
-                        self.llbb());
-
-                    llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
-                }
-                source_loc::set_debug_location(self, UnknownLocation);
+        // Convert the direct and indirect offsets to address ops.
+        let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
+        let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
+        let mut addr_ops = SmallVec::<[_; 8]>::new();
+
+        if direct_offset.bytes() > 0 {
+            addr_ops.push(op_plus_uconst());
+            addr_ops.push(direct_offset.bytes() as i64);
+        }
+        for &offset in indirect_offsets {
+            addr_ops.push(op_deref());
+            if offset.bytes() > 0 {
+                addr_ops.push(op_plus_uconst());
+                addr_ops.push(offset.bytes() as i64);
             }
         }
+
+        let name = SmallCStr::new(&variable_name.as_str());
+        let metadata = unsafe {
+            llvm::LLVMRustDIBuilderCreateVariable(
+                DIB(cx),
+                dwarf_tag,
+                scope_metadata,
+                name.as_ptr(),
+                file_metadata,
+                loc.line as c_uint,
+                type_metadata,
+                cx.sess().opts.optimize != config::OptLevel::No,
+                DIFlags::FlagZero,
+                argument_index,
+                align.bytes() as u32,
+            )
+        };
+        source_loc::set_debug_location(self,
+            InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
+        unsafe {
+            let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
+            let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
+                DIB(cx),
+                variable_alloca,
+                metadata,
+                addr_ops.as_ptr(),
+                addr_ops.len() as c_uint,
+                debug_loc,
+                self.llbb());
+
+            llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
+        }
+        source_loc::set_debug_location(self, UnknownLocation);
     }
 
     fn set_source_location(
         &mut self,
-        debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
-        scope: Option<&'ll DIScope>,
+        debug_context: &mut FunctionDebugContext<&'ll DIScope>,
+        scope: &'ll DIScope,
         span: Span,
     ) {
         set_source_location(debug_context, &self, scope, span)
@@ -224,7 +239,7 @@ fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
         gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
     }
 
-    fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) {
+    fn set_var_name(&mut self, value: &'ll Value, name: &str) {
         // Avoid wasting time if LLVM value names aren't even enabled.
         if self.sess().fewer_names() {
             return;
@@ -254,7 +269,7 @@ fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) {
             Err(_) => return,
         }
 
-        let cname = CString::new(name.to_string()).unwrap();
+        let cname = SmallCStr::new(name);
         unsafe {
             llvm::LLVMSetValueName(value, cname.as_ptr());
         }
@@ -268,14 +283,14 @@ fn create_function_debug_context(
         sig: ty::FnSig<'tcx>,
         llfn: &'ll Value,
         mir: &mir::Body<'_>,
-    ) -> FunctionDebugContext<&'ll DISubprogram> {
+    ) -> Option<FunctionDebugContext<&'ll DIScope>> {
         if self.sess().opts.debuginfo == DebugInfo::None {
-            return FunctionDebugContext::DebugInfoDisabled;
+            return None;
         }
 
         if let InstanceDef::Item(def_id) = instance.def {
             if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
-                return FunctionDebugContext::FunctionWithoutDebugInfo;
+                return None;
             }
         }
 
@@ -284,7 +299,7 @@ fn create_function_debug_context(
         // This can be the case for functions inlined from another crate
         if span.is_dummy() {
             // FIXME(simulacrum): Probably can't happen; remove.
-            return FunctionDebugContext::FunctionWithoutDebugInfo;
+            return None;
         }
 
         let def_id = instance.def_id();
@@ -357,14 +372,23 @@ fn create_function_debug_context(
                 None)
         };
 
-        // Initialize fn debug context (including scope map and namespace map)
-        let fn_debug_context = FunctionDebugContextData {
-            fn_metadata,
+        // Initialize fn debug context (including scopes).
+        // FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`.
+        let null_scope = DebugScope {
+            scope_metadata: None,
+            file_start_pos: BytePos(0),
+            file_end_pos: BytePos(0)
+        };
+        let mut fn_debug_context = FunctionDebugContext {
+            scopes: IndexVec::from_elem(null_scope, &mir.source_scopes),
             source_locations_enabled: false,
             defining_crate: def_id.krate,
         };
 
-        return FunctionDebugContext::RegularContext(fn_debug_context);
+        // Fill in all the scopes, with the information from the MIR body.
+        compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context);
+
+        return Some(fn_debug_context);
 
         fn get_function_signature<'ll, 'tcx>(
             cx: &CodegenCx<'ll, 'tcx>,
@@ -549,14 +573,6 @@ fn create_vtable_metadata(
         metadata::create_vtable_metadata(self, ty, vtable)
     }
 
-    fn create_mir_scopes(
-        &self,
-        mir: &mir::Body<'_>,
-        debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
-    ) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
-        create_scope_map::create_mir_scopes(self, mir, debug_context)
-    }
-
     fn extend_scope_to_file(
          &self,
          scope_metadata: &'ll DIScope,
@@ -569,13 +585,4 @@ fn extend_scope_to_file(
     fn debuginfo_finalize(&self) {
         finalize(self)
     }
-
-    fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
-        unsafe {
-            [llvm::LLVMRustDIBuilderCreateOpDeref(),
-             llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
-             byte_offset_of_var_in_env as i64,
-             llvm::LLVMRustDIBuilderCreateOpDeref()]
-        }
-    }
 }
index dec93a65dbaf49aa42526d0e4e2630d024178ff0..ccb3bde1cbe4e3bd4da90b36fdd942d840dac746 100644 (file)
@@ -2,7 +2,7 @@
 
 use super::utils::{debug_context, span_start};
 use super::metadata::UNKNOWN_COLUMN_NUMBER;
-use rustc_codegen_ssa::debuginfo::FunctionDebugContext;
+use rustc_codegen_ssa::mir::debuginfo::FunctionDebugContext;
 
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
 pub fn set_source_location<D>(
     debug_context: &FunctionDebugContext<D>,
     bx: &Builder<'_, 'll, '_>,
-    scope: Option<&'ll DIScope>,
+    scope: &'ll DIScope,
     span: Span,
 ) {
-    let function_debug_context = match *debug_context {
-        FunctionDebugContext::DebugInfoDisabled => return,
-        FunctionDebugContext::FunctionWithoutDebugInfo => {
-            set_debug_location(bx, UnknownLocation);
-            return;
-        }
-        FunctionDebugContext::RegularContext(ref data) => data
-    };
-
-    let dbg_loc = if function_debug_context.source_locations_enabled {
+    let dbg_loc = if debug_context.source_locations_enabled {
         debug!("set_source_location: {}", bx.sess().source_map().span_to_string(span));
         let loc = span_start(bx.cx(), span);
-        InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize())
+        InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
     } else {
         UnknownLocation
     };
index 3df8d4c26903bd43e859632e2c53a334b69689aa..02424956b9aa50474652c8e763d0a346c9232e53 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc::hir;
 use syntax::ast::{self, FloatTy};
+use rustc_target::abi::HasDataLayout;
 
 use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::traits::*;
@@ -694,6 +695,23 @@ fn codegen_intrinsic_call(
                 return;
             }
 
+            "ptr_offset_from" => {
+                let ty = substs.type_at(0);
+                let pointee_size = self.size_of(ty);
+
+                // This is the same sequence that Clang emits for pointer subtraction.
+                // It can be neither `nsw` nor `nuw` because the input is treated as
+                // unsigned but then the output is treated as signed, so neither works.
+                let a = args[0].immediate();
+                let b = args[1].immediate();
+                let a = self.ptrtoint(a, self.type_isize());
+                let b = self.ptrtoint(b, self.type_isize());
+                let d = self.sub(a, b);
+                let pointee_size = self.const_usize(pointee_size.bytes());
+                // this is where the signed magic happens (notice the `s` in `exactsdiv`)
+                self.exactsdiv(d, pointee_size)
+            }
+
             _ => bug!("unknown intrinsic '{}'", name),
         };
 
@@ -831,7 +849,7 @@ fn codegen_msvc_try(
         // We're generating an IR snippet that looks like:
         //
         //   declare i32 @rust_try(%func, %data, %ptr) {
-        //      %slot = alloca i64*
+        //      %slot = alloca [2 x i64]
         //      invoke %func(%data) to label %normal unwind label %catchswitch
         //
         //   normal:
@@ -855,21 +873,25 @@ fn codegen_msvc_try(
         //
         //      #include <stdint.h>
         //
+        //      struct rust_panic {
+        //          uint64_t x[2];
+        //      }
+        //
         //      int bar(void (*foo)(void), uint64_t *ret) {
         //          try {
         //              foo();
         //              return 0;
-        //          } catch(uint64_t a[2]) {
-        //              ret[0] = a[0];
-        //              ret[1] = a[1];
+        //          } catch(rust_panic a) {
+        //              ret[0] = a.x[0];
+        //              ret[1] = a.x[1];
         //              return 1;
         //          }
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
-        let i64p = bx.type_ptr_to(bx.type_i64());
-        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let slot = bx.alloca(i64p, ptr_align);
+        let i64_2 = bx.type_array(bx.type_i64(), 2);
+        let i64_align = bx.tcx().data_layout.i64_align.abi;
+        let slot = bx.alloca(i64_2, i64_align);
         bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
 
         normal.ret(bx.const_i32(0));
@@ -877,22 +899,15 @@ fn codegen_msvc_try(
         let cs = catchswitch.catch_switch(None, None, 1);
         catchswitch.add_handler(cs, catchpad.llbb());
 
-        let tydesc = match bx.tcx().lang_items().msvc_try_filter() {
+        let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
             Some(did) => bx.get_static(did),
-            None => bug!("msvc_try_filter not defined"),
+            None => bug!("eh_catch_typeinfo not defined, but needed for SEH unwinding"),
         };
         let funclet = catchpad.catch_pad(cs, &[tydesc, bx.const_i32(0), slot]);
-        let addr = catchpad.load(slot, ptr_align);
 
-        let i64_align = bx.tcx().data_layout.i64_align.abi;
-        let arg1 = catchpad.load(addr, i64_align);
-        let val1 = bx.const_i32(1);
-        let gep1 = catchpad.inbounds_gep(addr, &[val1]);
-        let arg2 = catchpad.load(gep1, i64_align);
-        let local_ptr = catchpad.bitcast(local_ptr, i64p);
-        let gep2 = catchpad.inbounds_gep(local_ptr, &[val1]);
-        catchpad.store(arg1, local_ptr, i64_align);
-        catchpad.store(arg2, gep2, i64_align);
+        let payload = catchpad.load(slot, i64_align);
+        let local_ptr = catchpad.bitcast(local_ptr, bx.type_ptr_to(i64_2));
+        catchpad.store(payload, local_ptr, i64_align);
         catchpad.catch_ret(&funclet, caught.llbb());
 
         caught.ret(bx.const_i32(1));
@@ -960,7 +975,14 @@ fn codegen_gnu_try(
         // rust_try ignores the selector.
         let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
         let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 1);
-        catch.add_clause(vals, bx.const_null(bx.type_i8p()));
+        let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
+            Some(tydesc) => {
+                let tydesc = bx.get_static(tydesc);
+                bx.bitcast(tydesc, bx.type_i8p())
+            }
+            None => bx.const_null(bx.type_i8p()),
+        };
+        catch.add_clause(vals, tydesc);
         let ptr = catch.extract_value(vals, 0);
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let bitcast = catch.bitcast(local_ptr, bx.type_ptr_to(bx.type_i8p()));
@@ -1224,7 +1246,6 @@ macro_rules! require_simd {
         // 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.
index 2ad6c28cd0838d2c24b58b9e5b5b19f5ebda4228..e7562c399b22256652e0dba04f52478b4b5d368f 100644 (file)
@@ -38,6 +38,7 @@
 extern crate rustc_driver as _;
 
 #[macro_use] extern crate log;
+extern crate smallvec;
 extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
index 2dce9b04c9e9eecff196da53b671ee368322f8fc..85e0b6d465ab06d7d0bd0f503e8c6fa847c2b6cd 100644 (file)
@@ -3,7 +3,7 @@
 use syntax_pos::symbol::Symbol;
 use rustc::session::Session;
 use rustc::session::config::PrintRequest;
-use rustc_target::spec::MergeFunctions;
+use rustc_target::spec::{MergeFunctions, PanicStrategy};
 use libc::c_int;
 use std::ffi::CString;
 use syntax::feature_gate::UnstableFeatures;
@@ -73,6 +73,11 @@ unsafe fn configure_llvm(sess: &Session) {
             }
         }
 
+        if sess.target.target.target_os == "emscripten" &&
+            sess.panic_strategy() == PanicStrategy::Unwind {
+            add("-enable-emscripten-cxx-exceptions");
+        }
+
         // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
         // during inlining. Unfortunately these may block other optimizations.
         add("-preserve-alignment-assumptions-during-inlining=false");
index ff87f0b1547cec36a61cb67a2780bc0adf8057dc..999cc406585030253ae30ac0efde7e465d645667 100644 (file)
@@ -14,7 +14,6 @@
 use rustc::session::Session;
 use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
                              LinkerPluginLto, Lto};
-use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::ty::TyCtxt;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
 use rustc_serialize::{json, Encoder};
@@ -1112,20 +1111,10 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
                     continue;
                 }
 
-                // Do not export generic symbols from upstream crates in linked
-                // artifact (notably the `dylib` crate type). The main reason
-                // for this is that `symbol_name` is actually wrong for generic
-                // symbols because it guesses the name we'd give them locally
-                // rather than the name it has upstream (depending on
-                // `share_generics` settings and such).
-                //
-                // To fix that issue we just say that linked artifacts, aka
-                // `dylib`s, never export generic symbols and they aren't
-                // available to downstream crates. (the not available part is
-                // handled elsewhere).
-                if let ExportedSymbol::Generic(..) = symbol {
-                    continue;
-                }
+                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
+                // We want to block export of generics from dylibs,
+                // but we must fix rust-lang/rust#65890 before we can
+                // do that robustly.
 
                 symbols.push(symbol.symbol_name(tcx).to_string());
             }
index 9443f225723788faaac36c3849ea27ab752d8027..85a90459f5ee473955c3f6a7625afe14ca8dc23f 100644 (file)
@@ -364,8 +364,9 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
         codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
 
     if is_extern && !std_internal {
-        // Emscripten cannot export statics, so reduce their export level here
-        if tcx.sess.target.target.options.is_like_emscripten {
+        let target = &tcx.sess.target.target.llvm_target;
+        // WebAssembly cannot export data symbols, so reduce their export level
+        if target.contains("wasm32") || target.contains("emscripten") {
             if let Some(Node::Item(&hir::Item {
                 kind: hir::ItemKind::Static(..),
                 ..
index c9b1c0260e8c36e54b2821e3ac95e1de6b2854d9..d1a0cf78d6a2efdae2902abc19a32c78015fcf55 100644 (file)
@@ -1,82 +1,2 @@
-use syntax_pos::{BytePos, Span};
-use rustc::hir::def_id::CrateNum;
-
+// FIXME(eddyb) find a place for this (or a way to replace it).
 pub mod type_names;
-
-pub enum FunctionDebugContext<D> {
-    RegularContext(FunctionDebugContextData<D>),
-    DebugInfoDisabled,
-    FunctionWithoutDebugInfo,
-}
-
-impl<D> FunctionDebugContext<D> {
-    pub fn get_ref(&self, span: Span) -> &FunctionDebugContextData<D> {
-        match *self {
-            FunctionDebugContext::RegularContext(ref data) => data,
-            FunctionDebugContext::DebugInfoDisabled => {
-                span_bug!(
-                    span,
-                    "debuginfo: Error trying to access FunctionDebugContext \
-                     although debug info is disabled!",
-                );
-            }
-            FunctionDebugContext::FunctionWithoutDebugInfo => {
-                span_bug!(
-                    span,
-                    "debuginfo: Error trying to access FunctionDebugContext \
-                     for function that should be ignored by debug info!",
-                );
-            }
-        }
-    }
-}
-
-/// Enables emitting source locations for the given functions.
-///
-/// Since we don't want source locations to be emitted for the function prelude,
-/// they are disabled when beginning to codegen a new function. This functions
-/// switches source location emitting on and must therefore be called before the
-/// first real statement/expression of the function is codegened.
-pub fn start_emitting_source_locations<D>(dbg_context: &mut FunctionDebugContext<D>) {
-    match *dbg_context {
-        FunctionDebugContext::RegularContext(ref mut data) => {
-            data.source_locations_enabled = true;
-        },
-        _ => { /* safe to ignore */ }
-    }
-}
-
-pub struct FunctionDebugContextData<D> {
-    pub fn_metadata: D,
-    pub source_locations_enabled: bool,
-    pub defining_crate: CrateNum,
-}
-
-pub enum VariableAccess<'a, V> {
-    // The llptr given is an alloca containing the variable's value
-    DirectVariable { alloca: V },
-    // The llptr given is an alloca containing the start of some pointer chain
-    // leading to the variable's content.
-    IndirectVariable { alloca: V, address_operations: &'a [i64] }
-}
-
-pub enum VariableKind {
-    ArgumentVariable(usize /*index*/),
-    LocalVariable,
-}
-
-
-#[derive(Clone, Copy, Debug)]
-pub struct MirDebugScope<D> {
-    pub scope_metadata: Option<D>,
-    // Start and end offsets of the file to which this DIScope belongs.
-    // These are used to quickly determine whether some span refers to the same file.
-    pub file_start_pos: BytePos,
-    pub file_end_pos: BytePos,
-}
-
-impl<D> MirDebugScope<D> {
-    pub fn is_valid(&self) -> bool {
-        !self.scope_metadata.is_none()
-    }
-}
index 604deffcf949bd7ffad5df2bc583f34ccb310f04..2e5dc3db31af90c89ef94eecb8f408a655ecfbd4 100644 (file)
@@ -7,6 +7,7 @@
 use rustc::mir::{self, Location, TerminatorKind};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::traversal;
+use rustc::session::config::DebugInfo;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, HasTyCtxt};
 use syntax_pos::DUMMY_SP;
@@ -21,13 +22,20 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     analyzer.visit_body(mir);
 
-    for (index, (ty, span)) in mir.local_decls.iter()
-        .map(|l| (l.ty, l.source_info.span))
-        .enumerate()
+    for (local, decl) in mir.local_decls.iter_enumerated()
     {
-        let ty = fx.monomorphize(&ty);
-        debug!("local {} has type {:?}", index, ty);
-        let layout = fx.cx.spanned_layout_of(ty, span);
+        // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
+        // of putting everything in allocas just so we can use llvm.dbg.declare.
+        if fx.cx.sess().opts.debuginfo == DebugInfo::Full {
+            if mir.local_kind(local) == mir::LocalKind::Arg || decl.name.is_some() {
+                analyzer.not_ssa(local);
+                continue;
+            }
+        }
+
+        let ty = fx.monomorphize(&decl.ty);
+        debug!("local {:?} has type `{}`", local, ty);
+        let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
         if fx.cx.is_backend_immediate(layout) {
             // These sorts of types are immediates that we can store
             // in an Value without an alloca.
@@ -40,7 +48,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             // (e.g., structs) into an alloca unconditionally, just so
             // that we don't have to deal with having two pathways
             // (gep vs extractvalue etc).
-            analyzer.not_ssa(mir::Local::new(index));
+            analyzer.not_ssa(local);
         }
     }
 
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
new file mode 100644 (file)
index 0000000..c215db3
--- /dev/null
@@ -0,0 +1,385 @@
+use rustc_index::vec::{Idx, IndexVec};
+use rustc::hir::def_id::CrateNum;
+use rustc::mir;
+use rustc::session::config::DebugInfo;
+use rustc::ty::{self, TyCtxt};
+use rustc::ty::layout::{LayoutOf, Size, VariantIdx};
+use crate::traits::*;
+
+use syntax_pos::{BytePos, Span, Symbol};
+use syntax::symbol::kw;
+
+use super::{FunctionCx, LocalRef};
+use super::OperandValue;
+
+pub struct FunctionDebugContext<D> {
+    pub scopes: IndexVec<mir::SourceScope, DebugScope<D>>,
+    pub source_locations_enabled: bool,
+    pub defining_crate: CrateNum,
+}
+
+#[derive(Copy, Clone)]
+pub enum VariableKind {
+    ArgumentVariable(usize /*index*/),
+    LocalVariable,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct DebugScope<D> {
+    pub scope_metadata: Option<D>,
+    // Start and end offsets of the file to which this DIScope belongs.
+    // These are used to quickly determine whether some span refers to the same file.
+    pub file_start_pos: BytePos,
+    pub file_end_pos: BytePos,
+}
+
+impl<D> DebugScope<D> {
+    pub fn is_valid(&self) -> bool {
+        !self.scope_metadata.is_none()
+    }
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
+    pub fn set_debug_loc(
+        &mut self,
+        bx: &mut Bx,
+        source_info: mir::SourceInfo
+    ) {
+        let (scope, span) = self.debug_loc(source_info);
+        if let Some(debug_context) = &mut self.debug_context {
+            // FIXME(eddyb) get rid of this unwrap somehow.
+            bx.set_source_location(debug_context, scope.unwrap(), span);
+        }
+    }
+
+    pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
+        // Bail out if debug info emission is not enabled.
+        match self.debug_context {
+            None => return (None, source_info.span),
+            Some(_) => {}
+        }
+
+        // In order to have a good line stepping behavior in debugger, we overwrite debug
+        // locations of macro expansions with that of the outermost expansion site
+        // (unless the crate is being compiled with `-Z debug-macros`).
+        if !source_info.span.from_expansion() ||
+           self.cx.sess().opts.debugging_opts.debug_macros {
+            let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
+            (scope, source_info.span)
+        } else {
+            // Walk up the macro expansion chain until we reach a non-expanded span.
+            // We also stop at the function body level because no line stepping can occur
+            // at the level above that.
+            let span = syntax_pos::hygiene::walk_chain(source_info.span, self.mir.span.ctxt());
+            let scope = self.scope_metadata_for_loc(source_info.scope, span.lo());
+            // Use span of the outermost expansion site, while keeping the original lexical scope.
+            (scope, span)
+        }
+    }
+
+    // DILocations inherit source file name from the parent DIScope.  Due to macro expansions
+    // it may so happen that the current span belongs to a different file than the DIScope
+    // corresponding to span's containing source scope.  If so, we need to create a DIScope
+    // "extension" into that file.
+    fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos)
+                              -> Option<Bx::DIScope> {
+        let debug_context = self.debug_context.as_ref()?;
+        let scope_metadata = debug_context.scopes[scope_id].scope_metadata;
+        if pos < debug_context.scopes[scope_id].file_start_pos ||
+           pos >= debug_context.scopes[scope_id].file_end_pos {
+            let sm = self.cx.sess().source_map();
+            let defining_crate = debug_context.defining_crate;
+            Some(self.cx.extend_scope_to_file(
+                scope_metadata.unwrap(),
+                &sm.lookup_char_pos(pos).file,
+                defining_crate
+            ))
+        } else {
+            scope_metadata
+        }
+    }
+
+    /// Apply debuginfo and/or name, after creating the `alloca` for a local,
+    /// or initializing the local with an operand (whichever applies).
+    // FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
+    // not just `llvm.dbg.declare` (which requires `alloca`).
+    pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
+        // FIXME(eddyb) maybe name the return place as `_0` or `return`?
+        if local == mir::RETURN_PLACE {
+            return;
+        }
+
+        let vars = match &self.per_local_var_debug_info {
+            Some(per_local) => &per_local[local],
+            None => return,
+        };
+        let whole_local_var = vars.iter().find(|var| {
+            var.place.projection.is_empty()
+        });
+        let has_proj = || vars.iter().any(|var| {
+            !var.place.projection.is_empty()
+        });
+
+        let (fallback_var, kind) = if self.mir.local_kind(local) == mir::LocalKind::Arg {
+            let arg_index = local.index() - 1;
+
+            // Add debuginfo even to unnamed arguments.
+            // FIXME(eddyb) is this really needed?
+            let var = if arg_index == 0 && has_proj() {
+                // Hide closure environments from debuginfo.
+                // FIXME(eddyb) shouldn't `ArgumentVariable` indices
+                // be offset to account for the hidden environment?
+                None
+            } else {
+                Some(VarDebugInfo {
+                    name: kw::Invalid,
+                    source_info: self.mir.local_decls[local].source_info,
+                    place: local.into(),
+                })
+            };
+            (var, VariableKind::ArgumentVariable(arg_index + 1))
+        } else {
+            (None, VariableKind::LocalVariable)
+        };
+
+        let local_ref = &self.locals[local];
+
+        if !bx.sess().fewer_names() {
+            let name = match whole_local_var.or(fallback_var.as_ref()) {
+                Some(var) if var.name != kw::Invalid => var.name.to_string(),
+                _ => format!("{:?}", local),
+            };
+            match local_ref {
+                LocalRef::Place(place) |
+                LocalRef::UnsizedPlace(place) => {
+                    bx.set_var_name(place.llval, &name);
+                }
+                LocalRef::Operand(Some(operand)) => match operand.val {
+                    OperandValue::Ref(x, ..) |
+                    OperandValue::Immediate(x) => {
+                        bx.set_var_name(x, &name);
+                    }
+                    OperandValue::Pair(a, b) => {
+                        // FIXME(eddyb) these are scalar components,
+                        // maybe extract the high-level fields?
+                        bx.set_var_name(a, &(name.clone() + ".0"));
+                        bx.set_var_name(b, &(name + ".1"));
+                    }
+                }
+                LocalRef::Operand(None) => {}
+            }
+        }
+
+        if bx.sess().opts.debuginfo != DebugInfo::Full {
+            return;
+        }
+
+        let debug_context = match &self.debug_context {
+            Some(debug_context) => debug_context,
+            None => return,
+        };
+
+        // FIXME(eddyb) add debuginfo for unsized places too.
+        let base = match local_ref {
+            LocalRef::Place(place) => place,
+            _ => return,
+        };
+
+        let vars = vars.iter().chain(if whole_local_var.is_none() {
+            fallback_var.as_ref()
+        } else {
+            None
+        });
+
+        for var in vars {
+            let mut layout = base.layout;
+            let mut direct_offset = Size::ZERO;
+            // FIXME(eddyb) use smallvec here.
+            let mut indirect_offsets = vec![];
+
+            let kind = if var.place.projection.is_empty() {
+                kind
+            } else {
+                VariableKind::LocalVariable
+            };
+
+            for elem in &var.place.projection[..] {
+                match *elem {
+                    mir::ProjectionElem::Deref => {
+                        indirect_offsets.push(Size::ZERO);
+                        layout = bx.cx().layout_of(
+                            layout.ty.builtin_deref(true)
+                                .unwrap_or_else(|| {
+                                    span_bug!(
+                                        var.source_info.span,
+                                        "cannot deref `{}`",
+                                        layout.ty,
+                                    )
+                                }).ty,
+                        );
+                    }
+                    mir::ProjectionElem::Field(field, _) => {
+                        let i = field.index();
+                        let offset = indirect_offsets.last_mut()
+                            .unwrap_or(&mut direct_offset);
+                        *offset += layout.fields.offset(i);
+                        layout = layout.field(bx.cx(), i);
+                    }
+                    mir::ProjectionElem::Downcast(_, variant) => {
+                        layout = layout.for_variant(bx.cx(), variant);
+                    }
+                    _ => span_bug!(
+                        var.source_info.span,
+                        "unsupported var debuginfo place `{:?}`",
+                        var.place,
+                    ),
+                }
+            }
+
+            let (scope, span) = self.debug_loc(var.source_info);
+            if let Some(scope) = scope {
+                bx.declare_local(debug_context, var.name, layout.ty, scope,
+                    base.llval, direct_offset, &indirect_offsets, kind, span);
+            }
+        }
+    }
+
+    pub fn debug_introduce_locals(&self, bx: &mut Bx) {
+        if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
+            for local in self.locals.indices() {
+                self.debug_introduce_local(bx, local);
+            }
+        }
+    }
+}
+
+pub fn per_local_var_debug_info(
+    tcx: TyCtxt<'tcx>,
+    body: &mir::Body<'tcx>,
+) -> Option<IndexVec<mir::Local, Vec<VarDebugInfo<'tcx>>>> {
+    if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() {
+        let mut per_local = IndexVec::from_elem(vec![], &body.local_decls);
+        for (local, decl) in body.local_decls.iter_enumerated() {
+            if let Some(name) = decl.name {
+                per_local[local].push(VarDebugInfo {
+                    name,
+                    source_info: mir::SourceInfo {
+                        span: decl.source_info.span,
+                        scope: decl.visibility_scope,
+                    },
+                    place: local.into(),
+                });
+            }
+        }
+
+        let upvar_debuginfo = &body.__upvar_debuginfo_codegen_only_do_not_use;
+        if !upvar_debuginfo.is_empty() {
+
+            let env_arg = mir::Local::new(1);
+            let mut env_projs = vec![];
+
+            let pin_did = tcx.lang_items().pin_type();
+            match body.local_decls[env_arg].ty.kind {
+                ty::RawPtr(_) |
+                ty::Ref(..)  => {
+                    env_projs.push(mir::ProjectionElem::Deref);
+                }
+                ty::Adt(def, substs) if Some(def.did) == pin_did => {
+                    if let ty::Ref(..) = substs.type_at(0).kind {
+                        env_projs.push(mir::ProjectionElem::Field(
+                            mir::Field::new(0),
+                            // HACK(eddyb) field types aren't used or needed here.
+                            tcx.types.err,
+                        ));
+                        env_projs.push(mir::ProjectionElem::Deref);
+                    }
+                }
+                _ => {}
+            }
+
+            let extra_locals = {
+                let upvars = upvar_debuginfo
+                    .iter()
+                    .enumerate()
+                    .map(|(i, upvar)| {
+                        let source_info = mir::SourceInfo {
+                            span: body.span,
+                            scope: mir::OUTERMOST_SOURCE_SCOPE,
+                        };
+                        (None, i, upvar.debug_name, upvar.by_ref, source_info)
+                    });
+
+                let generator_fields = body.generator_layout.as_ref().map(|generator_layout| {
+                    generator_layout.variant_fields.iter()
+                        .enumerate()
+                        .flat_map(move |(variant_idx, fields)| {
+                            let variant_idx = Some(VariantIdx::from(variant_idx));
+                            fields.iter()
+                                .enumerate()
+                                .filter_map(move |(i, field)| {
+                                    let decl = &generator_layout.
+                                        __local_debuginfo_codegen_only_do_not_use[*field];
+                                    if let Some(name) = decl.name {
+                                        let source_info = mir::SourceInfo {
+                                            span: decl.source_info.span,
+                                            scope: decl.visibility_scope,
+                                        };
+                                        Some((variant_idx, i, name, false, source_info))
+                                    } else {
+                                        None
+                                    }
+                            })
+                        })
+                }).into_iter().flatten();
+
+                upvars.chain(generator_fields)
+            };
+
+            for (variant_idx, field, name, by_ref, source_info) in extra_locals {
+                let mut projs = env_projs.clone();
+
+                if let Some(variant_idx) = variant_idx {
+                    projs.push(mir::ProjectionElem::Downcast(None, variant_idx));
+                }
+
+                projs.push(mir::ProjectionElem::Field(
+                    mir::Field::new(field),
+                    // HACK(eddyb) field types aren't used or needed here.
+                    tcx.types.err,
+                ));
+
+                if by_ref {
+                    projs.push(mir::ProjectionElem::Deref);
+                }
+
+                per_local[env_arg].push(VarDebugInfo {
+                    name,
+                    source_info,
+                    place: mir::Place {
+                        base: mir::PlaceBase::Local(env_arg),
+                        projection: tcx.intern_place_elems(&projs),
+                    },
+                });
+            }
+        }
+
+        Some(per_local)
+    } else {
+        None
+    }
+}
+
+/// Debug information relatating to an user variable.
+// FIXME(eddyb) move this to the MIR bodies themselves.
+#[derive(Clone)]
+pub struct VarDebugInfo<'tcx> {
+    pub name: Symbol,
+
+    /// Source info of the user variable, including the scope
+    /// within which the variable is visible (to debuginfo)
+    /// (see `LocalDecl`'s `source_info` field for more details).
+    pub source_info: mir::SourceInfo,
+
+    /// Where the data for this user variable is to be found.
+    pub place: mir::Place<'tcx>,
+}
index 1a2e796a5b7be6adc44b375316295c035d5ed2c9..5ad14456285ba80a7af96810ffbc7374e5275450 100644 (file)
@@ -1,22 +1,17 @@
-use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance};
+use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Body};
-use rustc::session::config::DebugInfo;
 use rustc_target::abi::call::{FnType, PassMode};
-use rustc_target::abi::{Variants, VariantIdx};
 use crate::base;
-use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext};
 use crate::traits::*;
 
-use syntax_pos::{DUMMY_SP, BytePos, Span};
-use syntax::symbol::kw;
-
 use std::iter;
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 
 use self::analyze::CleanupKind;
+use self::debuginfo::FunctionDebugContext;
 use self::place::PlaceRef;
 use rustc::mir::traversal;
 
@@ -28,7 +23,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
 
     mir: &'a mir::Body<'tcx>,
 
-    debug_context: FunctionDebugContext<Bx::DIScope>,
+    debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
 
     llfn: Bx::Function,
 
@@ -79,8 +74,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     /// notably `expect`.
     locals: IndexVec<mir::Local, LocalRef<'tcx, Bx::Value>>,
 
-    /// Debug information for MIR scopes.
-    scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<Bx::DIScope>>,
+    per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<debuginfo::VarDebugInfo<'tcx>>>>,
 }
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -93,64 +87,6 @@ pub fn monomorphize<T>(&self, value: &T) -> T
             value,
         )
     }
-
-    pub fn set_debug_loc(
-        &mut self,
-        bx: &mut Bx,
-        source_info: mir::SourceInfo
-    ) {
-        let (scope, span) = self.debug_loc(source_info);
-        bx.set_source_location(&mut self.debug_context, scope, span);
-    }
-
-    pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
-        // Bail out if debug info emission is not enabled.
-        match self.debug_context {
-            FunctionDebugContext::DebugInfoDisabled |
-            FunctionDebugContext::FunctionWithoutDebugInfo => {
-                return (self.scopes[source_info.scope].scope_metadata, source_info.span);
-            }
-            FunctionDebugContext::RegularContext(_) =>{}
-        }
-
-        // In order to have a good line stepping behavior in debugger, we overwrite debug
-        // locations of macro expansions with that of the outermost expansion site
-        // (unless the crate is being compiled with `-Z debug-macros`).
-        if !source_info.span.from_expansion() ||
-           self.cx.sess().opts.debugging_opts.debug_macros {
-            let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
-            (scope, source_info.span)
-        } else {
-            // Walk up the macro expansion chain until we reach a non-expanded span.
-            // We also stop at the function body level because no line stepping can occur
-            // at the level above that.
-            let span = syntax_pos::hygiene::walk_chain(source_info.span, self.mir.span.ctxt());
-            let scope = self.scope_metadata_for_loc(source_info.scope, span.lo());
-            // Use span of the outermost expansion site, while keeping the original lexical scope.
-            (scope, span)
-        }
-    }
-
-    // DILocations inherit source file name from the parent DIScope.  Due to macro expansions
-    // it may so happen that the current span belongs to a different file than the DIScope
-    // corresponding to span's containing source scope.  If so, we need to create a DIScope
-    // "extension" into that file.
-    fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos)
-                              -> Option<Bx::DIScope> {
-        let scope_metadata = self.scopes[scope_id].scope_metadata;
-        if pos < self.scopes[scope_id].file_start_pos ||
-           pos >= self.scopes[scope_id].file_end_pos {
-            let sm = self.cx.sess().source_map();
-            let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
-            Some(self.cx.extend_scope_to_file(
-                scope_metadata.unwrap(),
-                &sm.lookup_char_pos(pos).file,
-                defining_crate
-            ))
-        } else {
-            scope_metadata
-        }
-    }
 }
 
 enum LocalRef<'tcx, V> {
@@ -192,8 +128,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     let fn_ty = FnType::new(cx, sig, &[]);
     debug!("fn_ty: {:?}", fn_ty);
-    let mut debug_context =
+
+    let debug_context =
         cx.create_function_debug_context(instance, sig, llfn, mir);
+
     let mut bx = Bx::new_block(cx, llfn, "start");
 
     if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) {
@@ -215,8 +153,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             }
         }).collect();
 
-    // Compute debuginfo scopes from MIR scopes.
-    let scopes = cx.create_mir_scopes(mir, &mut debug_context);
     let (landing_pads, funclets) = create_funclets(mir, &mut bx, &cleanup_kinds, &block_bxs);
 
     let mut fx = FunctionCx {
@@ -231,9 +167,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         cleanup_kinds,
         landing_pads,
         funclets,
-        scopes,
         locals: IndexVec::new(),
         debug_context,
+        per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir),
     };
 
     let memory_locals = analyze::non_ssa_locals(&fx);
@@ -247,62 +183,22 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let layout = bx.layout_of(fx.monomorphize(&decl.ty));
             assert!(!layout.ty.has_erasable_regions());
 
-            if let Some(name) = decl.name {
-                // User variable
-                let debug_scope = fx.scopes[decl.visibility_scope];
-                let dbg = debug_scope.is_valid() &&
-                    bx.sess().opts.debuginfo == DebugInfo::Full;
-
-                if !memory_locals.contains(local) && !dbg {
-                    debug!("alloc: {:?} ({}) -> operand", local, name);
-                    return LocalRef::new_operand(&mut bx, layout);
-                }
+            if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
+                debug!("alloc: {:?} (return place) -> place", local);
+                let llretptr = bx.get_param(0);
+                return LocalRef::Place(PlaceRef::new_sized(llretptr, layout));
+            }
 
-                debug!("alloc: {:?} ({}) -> place", local, name);
+            if memory_locals.contains(local) {
+                debug!("alloc: {:?} -> place", local);
                 if layout.is_unsized() {
-                    let indirect_place =
-                        PlaceRef::alloca_unsized_indirect(&mut bx, layout);
-                    bx.set_var_name(indirect_place.llval, name);
-                    // FIXME: add an appropriate debuginfo
-                    LocalRef::UnsizedPlace(indirect_place)
+                    LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout))
                 } else {
-                    let place = PlaceRef::alloca(&mut bx, layout);
-                    bx.set_var_name(place.llval, name);
-                    if dbg {
-                        let (scope, span) = fx.debug_loc(mir::SourceInfo {
-                            span: decl.source_info.span,
-                            scope: decl.visibility_scope,
-                        });
-                        bx.declare_local(&fx.debug_context, name, layout.ty, scope.unwrap(),
-                            VariableAccess::DirectVariable { alloca: place.llval },
-                            VariableKind::LocalVariable, span);
-                    }
-                    LocalRef::Place(place)
+                    LocalRef::Place(PlaceRef::alloca(&mut bx, layout))
                 }
             } else {
-                // Temporary or return place
-                if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
-                    debug!("alloc: {:?} (return place) -> place", local);
-                    let llretptr = bx.get_param(0);
-                    LocalRef::Place(PlaceRef::new_sized(llretptr, layout))
-                } else if memory_locals.contains(local) {
-                    debug!("alloc: {:?} -> place", local);
-                    if layout.is_unsized() {
-                        let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout);
-                        bx.set_var_name(indirect_place.llval, format_args!("{:?}", local));
-                        LocalRef::UnsizedPlace(indirect_place)
-                    } else {
-                        let place = PlaceRef::alloca(&mut bx, layout);
-                        bx.set_var_name(place.llval, format_args!("{:?}", local));
-                        LocalRef::Place(place)
-                    }
-                } else {
-                    // If this is an immediate local, we do not create an
-                    // alloca in advance. Instead we wait until we see the
-                    // definition and update the operand there.
-                    debug!("alloc: {:?} -> operand", local);
-                    LocalRef::new_operand(&mut bx, layout)
-                }
+                debug!("alloc: {:?} -> operand", local);
+                LocalRef::new_operand(&mut bx, layout)
             }
         };
 
@@ -313,6 +209,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             .collect()
     };
 
+    // Apply debuginfo to the newly allocated locals.
+    fx.debug_introduce_locals(&mut bx);
+
     // Branch to the START block, if it's not the entry block.
     if reentrant_start_block {
         bx.br(fx.blocks[mir::START_BLOCK]);
@@ -321,7 +220,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     // Up until here, IR instructions for this function have explicitly not been annotated with
     // source code location, so we don't step into call setup code. From here on, source location
     // emitting should be enabled.
-    debuginfo::start_emitting_source_locations(&mut fx.debug_context);
+    if let Some(debug_context) = &mut fx.debug_context {
+        debug_context.source_locations_enabled = true;
+    }
 
     let rpo = traversal::reverse_postorder(&mir);
     let mut visited = BitSet::new_empty(mir.basic_blocks().len());
@@ -421,28 +322,12 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     memory_locals: &BitSet<mir::Local>,
 ) -> Vec<LocalRef<'tcx, Bx::Value>> {
     let mir = fx.mir;
-    let tcx = fx.cx.tcx();
     let mut idx = 0;
     let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize;
 
-    // Get the argument scope, if it exists and if we need it.
-    let arg_scope = fx.scopes[mir::OUTERMOST_SOURCE_SCOPE];
-    let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full {
-        arg_scope.scope_metadata
-    } else {
-        None
-    };
-
     mir.args_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
 
-        // FIXME(eddyb) don't allocate a `String` unless it gets used.
-        let name = if let Some(name) = arg_decl.name {
-            name.as_str().to_string()
-        } else {
-            format!("{:?}", local)
-        };
-
         if Some(local) == mir.spread_arg {
             // This argument (e.g., the last argument in the "rust-call" ABI)
             // is a tuple that was spread at the ABI level and now we have
@@ -456,7 +341,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             };
 
             let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
-            bx.set_var_name(place.llval, name);
             for i in 0..tupled_arg_tys.len() {
                 let arg = &fx.fn_ty.args[idx];
                 idx += 1;
@@ -467,22 +351,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 bx.store_fn_arg(arg, &mut llarg_idx, pr_field);
             }
 
-            // Now that we have one alloca that contains the aggregate value,
-            // we can create one debuginfo entry for the argument.
-            arg_scope.map(|scope| {
-                let variable_access = VariableAccess::DirectVariable {
-                    alloca: place.llval
-                };
-                bx.declare_local(
-                    &fx.debug_context,
-                    arg_decl.name.unwrap_or(kw::Invalid),
-                    arg_ty, scope,
-                    variable_access,
-                    VariableKind::ArgumentVariable(arg_index + 1),
-                    DUMMY_SP
-                );
-            });
-
             return LocalRef::Place(place);
         }
 
@@ -490,24 +358,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let arg_ty = fx.monomorphize(&arg_decl.ty);
 
             let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
-            bx.set_var_name(va_list.llval, name);
             bx.va_start(va_list.llval);
 
-            arg_scope.map(|scope| {
-                let variable_access = VariableAccess::DirectVariable {
-                    alloca: va_list.llval
-                };
-                bx.declare_local(
-                    &fx.debug_context,
-                    arg_decl.name.unwrap_or(kw::Invalid),
-                    va_list.layout.ty,
-                    scope,
-                    variable_access,
-                    VariableKind::ArgumentVariable(arg_index + 1),
-                    DUMMY_SP
-                );
-            });
-
             return LocalRef::Place(va_list);
         }
 
@@ -517,7 +369,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             llarg_idx += 1;
         }
 
-        if arg_scope.is_none() && !memory_locals.contains(local) {
+        if !memory_locals.contains(local) {
             // We don't have to cast or keep the argument in the alloca.
             // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
             // of putting everything in allocas just so we can use llvm.dbg.declare.
@@ -528,7 +380,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 }
                 PassMode::Direct(_) => {
                     let llarg = bx.get_param(llarg_idx);
-                    bx.set_var_name(llarg, &name);
                     llarg_idx += 1;
                     return local(
                         OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
@@ -537,11 +388,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                     let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1));
                     llarg_idx += 2;
 
-                    // FIXME(eddyb) these are scalar components,
-                    // maybe extract the high-level fields?
-                    bx.set_var_name(a, format_args!("{}.0", name));
-                    bx.set_var_name(b, format_args!("{}.1", name));
-
                     return local(OperandRef {
                         val: OperandValue::Pair(a, b),
                         layout: arg.layout
@@ -551,14 +397,13 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             }
         }
 
-        let place = if arg.is_sized_indirect() {
+        if arg.is_sized_indirect() {
             // Don't copy an indirect argument to an alloca, the caller
             // already put it in a temporary alloca and gave it up.
             // FIXME: lifetimes
             let llarg = bx.get_param(llarg_idx);
-            bx.set_var_name(llarg, &name);
             llarg_idx += 1;
-            PlaceRef::new_sized(llarg, arg.layout)
+            LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout))
         } else if arg.is_unsized_indirect() {
             // As the storage for the indirect argument lives during
             // the whole function call, we just copy the fat pointer.
@@ -569,151 +414,12 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let indirect_operand = OperandValue::Pair(llarg, llextra);
 
             let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout);
-            bx.set_var_name(tmp.llval, name);
             indirect_operand.store(bx, tmp);
-            tmp
+            LocalRef::UnsizedPlace(tmp)
         } else {
             let tmp = PlaceRef::alloca(bx, arg.layout);
-            bx.set_var_name(tmp.llval, name);
             bx.store_fn_arg(arg, &mut llarg_idx, tmp);
-            tmp
-        };
-        let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use;
-        arg_scope.map(|scope| {
-            // Is this a regular argument?
-            if arg_index > 0 || upvar_debuginfo.is_empty() {
-                // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
-                // need to insert a deref here, but the C ABI uses a pointer and a copy using the
-                // byval attribute, for which LLVM always does the deref itself,
-                // so we must not add it.
-                let variable_access = VariableAccess::DirectVariable {
-                    alloca: place.llval
-                };
-
-                bx.declare_local(
-                    &fx.debug_context,
-                    arg_decl.name.unwrap_or(kw::Invalid),
-                    arg.layout.ty,
-                    scope,
-                    variable_access,
-                    VariableKind::ArgumentVariable(arg_index + 1),
-                    DUMMY_SP
-                );
-                return;
-            }
-
-            let pin_did = tcx.lang_items().pin_type();
-            // Or is it the closure environment?
-            let (closure_layout, env_ref) = match arg.layout.ty.kind {
-                ty::RawPtr(ty::TypeAndMut { ty, .. }) |
-                ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
-                ty::Adt(def, substs) if Some(def.did) == pin_did => {
-                    match substs.type_at(0).kind {
-                        ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
-                        _ => (arg.layout, false),
-                    }
-                }
-                _ => (arg.layout, false)
-            };
-
-            let (def_id, upvar_substs) = match closure_layout.ty.kind {
-                ty::Closure(def_id, substs) => (def_id,
-                    UpvarSubsts::Closure(substs)),
-                ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
-                _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
-            };
-            let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
-
-            let extra_locals = {
-                let upvars = upvar_debuginfo
-                    .iter()
-                    .zip(upvar_tys)
-                    .enumerate()
-                    .map(|(i, (upvar, ty))| {
-                        (None, i, upvar.debug_name, upvar.by_ref, ty, scope, DUMMY_SP)
-                    });
-
-                let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
-                    let (def_id, gen_substs) = match closure_layout.ty.kind {
-                        ty::Generator(def_id, substs, _) => (def_id, substs),
-                        _ => bug!("generator layout without generator substs"),
-                    };
-                    let state_tys = gen_substs.as_generator().state_tys(def_id, tcx);
-
-                    generator_layout.variant_fields.iter()
-                        .zip(state_tys)
-                        .enumerate()
-                        .flat_map(move |(variant_idx, (fields, tys))| {
-                            let variant_idx = Some(VariantIdx::from(variant_idx));
-                            fields.iter()
-                                .zip(tys)
-                                .enumerate()
-                                .filter_map(move |(i, (field, ty))| {
-                                    let decl = &generator_layout.
-                                        __local_debuginfo_codegen_only_do_not_use[*field];
-                                    if let Some(name) = decl.name {
-                                        let ty = fx.monomorphize(&ty);
-                                        let (var_scope, var_span) = fx.debug_loc(mir::SourceInfo {
-                                            span: decl.source_info.span,
-                                            scope: decl.visibility_scope,
-                                        });
-                                        let var_scope = var_scope.unwrap_or(scope);
-                                        Some((variant_idx, i, name, false, ty, var_scope, var_span))
-                                    } else {
-                                        None
-                                    }
-                            })
-                        })
-                }).into_iter().flatten();
-
-                upvars.chain(generator_fields)
-            };
-
-            for (variant_idx, field, name, by_ref, ty, var_scope, var_span) in extra_locals {
-                let fields = match variant_idx {
-                    Some(variant_idx) => {
-                        match &closure_layout.variants {
-                            Variants::Multiple { variants, .. } => {
-                                &variants[variant_idx].fields
-                            },
-                            _ => bug!("variant index on univariant layout"),
-                        }
-                    }
-                    None => &closure_layout.fields,
-                };
-                let byte_offset_of_var_in_env = fields.offset(field).bytes();
-
-                let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
-
-                // The environment and the capture can each be indirect.
-                let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
-
-                let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.kind) {
-                    ty
-                } else {
-                    ops = &ops[..ops.len() - 1];
-                    ty
-                };
-
-                let variable_access = VariableAccess::IndirectVariable {
-                    alloca: place.llval,
-                    address_operations: &ops
-                };
-                bx.declare_local(
-                    &fx.debug_context,
-                    name,
-                    ty,
-                    var_scope,
-                    variable_access,
-                    VariableKind::LocalVariable,
-                    var_span
-                );
-            }
-        });
-        if arg.is_unsized_indirect() {
-            LocalRef::UnsizedPlace(place)
-        } else {
-            LocalRef::Place(place)
+            LocalRef::Place(tmp)
         }
     }).collect()
 }
@@ -721,6 +427,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 mod analyze;
 mod block;
 pub mod constant;
+pub mod debuginfo;
 pub mod place;
 pub mod operand;
 mod rvalue;
index 1d1bc2a81a2ca7459205a34391f665b92ec35a4e..3e7c4ef49fb5aeab6452dcf7aa71f43235ae3712 100644 (file)
@@ -68,6 +68,8 @@ fn new_thin_place<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         }
     }
 
+    // FIXME(eddyb) pass something else for the name so no work is done
+    // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
     pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,
@@ -78,6 +80,8 @@ pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
     }
 
     /// Returns a place for an indirect reference to an unsized place.
+    // FIXME(eddyb) pass something else for the name so no work is done
+    // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
     pub fn alloca_unsized_indirect<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,
index 43d5c2570b705e4f66cd4a68deec17679bd90c84..d11601be0b4ab3d02e0a249a0ab4874997ce6d05 100644 (file)
@@ -27,21 +27,8 @@ pub fn codegen_statement(
                         }
                         LocalRef::Operand(None) => {
                             let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
-                            if let Some(name) = self.mir.local_decls[index].name {
-                                match operand.val {
-                                    OperandValue::Ref(x, ..) |
-                                    OperandValue::Immediate(x) => {
-                                        bx.set_var_name(x, name);
-                                    }
-                                    OperandValue::Pair(a, b) => {
-                                        // FIXME(eddyb) these are scalar components,
-                                        // maybe extract the high-level fields?
-                                        bx.set_var_name(a, format_args!("{}.0", name));
-                                        bx.set_var_name(b, format_args!("{}.1", name));
-                                    }
-                                }
-                            }
                             self.locals[index] = LocalRef::Operand(Some(operand));
+                            self.debug_introduce_local(&mut bx, index);
                             bx
                         }
                         LocalRef::Operand(Some(op)) => {
index 989e6cf9dcaf1ea57aad2df096189b725a1adab8..802eaaa357ac09c4ea4245a2f28697fa99de909f 100644 (file)
@@ -1,9 +1,9 @@
 use super::BackendTypes;
-use crate::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess, VariableKind};
+use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
 use rustc::hir::def_id::CrateNum;
 use rustc::mir;
 use rustc::ty::{self, Ty, Instance};
-use rustc_index::vec::IndexVec;
+use rustc::ty::layout::Size;
 use syntax::ast::Name;
 use syntax_pos::{SourceFile, Span};
 
@@ -13,22 +13,15 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
     /// Creates the function-specific debug context.
     ///
     /// Returns the FunctionDebugContext for the function which holds state needed
-    /// for debug info creation. The function may also return another variant of the
-    /// FunctionDebugContext enum which indicates why no debuginfo should be created
-    /// for the function.
+    /// for debug info creation, if it is enabled.
     fn create_function_debug_context(
         &self,
         instance: Instance<'tcx>,
         sig: ty::FnSig<'tcx>,
         llfn: Self::Function,
         mir: &mir::Body<'_>,
-    ) -> FunctionDebugContext<Self::DIScope>;
+    ) -> Option<FunctionDebugContext<Self::DIScope>>;
 
-    fn create_mir_scopes(
-        &self,
-        mir: &mir::Body<'_>,
-        debug_context: &mut FunctionDebugContext<Self::DIScope>,
-    ) -> IndexVec<mir::SourceScope, MirDebugScope<Self::DIScope>>;
     fn extend_scope_to_file(
         &self,
         scope_metadata: Self::DIScope,
@@ -36,7 +29,6 @@ fn extend_scope_to_file(
         defining_crate: CrateNum,
     ) -> Self::DIScope;
     fn debuginfo_finalize(&self);
-    fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
 }
 
 pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
@@ -46,16 +38,19 @@ fn declare_local(
         variable_name: Name,
         variable_type: Ty<'tcx>,
         scope_metadata: Self::DIScope,
-        variable_access: VariableAccess<'_, Self::Value>,
+        variable_alloca: Self::Value,
+        direct_offset: Size,
+        // NB: each offset implies a deref (i.e. they're steps in a pointer chain).
+        indirect_offsets: &[Size],
         variable_kind: VariableKind,
         span: Span,
     );
     fn set_source_location(
         &mut self,
         debug_context: &mut FunctionDebugContext<Self::DIScope>,
-        scope: Option<Self::DIScope>,
+        scope: Self::DIScope,
         span: Span,
     );
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
-    fn set_var_name(&mut self, value: Self::Value, name: impl ToString);
+    fn set_var_name(&mut self, value: Self::Value, name: &str);
 }
index b835b1706b85f5cf3651a94bc6f4c489517d4a4e..0213eb4f2a2a4027f281f067ea6fbe8a601a1331 100644 (file)
@@ -1046,14 +1046,14 @@ unsafe impl<O, T: ?Sized> CloneStableAddress for OwningRef<O, T>
     where O: CloneStableAddress {}
 
 unsafe impl<O, T: ?Sized> Send for OwningRef<O, T>
-    where O: Send, for<'a> (&'a T): Send {}
+    where O: Send, for<'a> &'a T: Send {}
 unsafe impl<O, T: ?Sized> Sync for OwningRef<O, T>
-    where O: Sync, for<'a> (&'a T): Sync {}
+    where O: Sync, for<'a> &'a T: Sync {}
 
 unsafe impl<O, T: ?Sized> Send for OwningRefMut<O, T>
-    where O: Send, for<'a> (&'a mut T): Send {}
+    where O: Send, for<'a> &'a mut T: Send {}
 unsafe impl<O, T: ?Sized> Sync for OwningRefMut<O, T>
-    where O: Sync, for<'a> (&'a mut T): Sync {}
+    where O: Sync, for<'a> &'a mut T: Sync {}
 
 impl Debug for dyn Erased {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
index f09474ff4d344a8c37f801b09cd9b2de1f42d60a..6a19f52897e5de97d976aaae88e5b954060b81f5 100644 (file)
@@ -492,18 +492,20 @@ pub fn set(&self, value: T) {
         assert!(self.try_set(value).is_none());
     }
 
-    /// Tries to initialize the inner value by calling the closure while ensuring that no-one else
-    /// can access the value in the mean time by holding a lock for the duration of the closure.
-    /// If the value was already initialized the closure is not called and `false` is returned,
-    /// otherwise if the value from the closure initializes the inner value, `true` is returned
+    /// Initializes the inner value if it wasn't already done by calling the provided closure. It
+    /// ensures that no-one else can access the value in the mean time by holding a lock for the
+    /// duration of the closure.
+    /// A reference to the inner value is returned.
     #[inline]
-    pub fn init_locking<F: FnOnce() -> T>(&self, f: F) -> bool {
-        let mut lock = self.0.lock();
-        if lock.is_some() {
-            return false;
+    pub fn init_locking<F: FnOnce() -> T>(&self, f: F) -> &T {
+        {
+            let mut lock = self.0.lock();
+            if lock.is_none() {
+                *lock = Some(f());
+            }
         }
-        *lock = Some(f());
-        true
+
+        self.borrow()
     }
 
     /// Tries to initialize the inner value by calling the closure without ensuring that no-one
index 1781f2e165033976daadb9b3fed123a8aa68451f..5a09898f18fbdcb5b26e796c13fb1a535ff8b4ad 100644 (file)
@@ -34,7 +34,7 @@ pub struct SubDiagnostic {
     pub render_span: Option<MultiSpan>,
 }
 
-#[derive(PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq)]
 pub struct DiagnosticStyledString(pub Vec<StringPart>);
 
 impl DiagnosticStyledString {
@@ -60,7 +60,7 @@ pub fn content(&self) -> String {
     }
 }
 
-#[derive(PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq)]
 pub enum StringPart {
     Normal(String),
     Highlighted(String),
index 2a7f9ad25def00afd6a4e9291b9a19dd801dea52..b153f0f0e82bf1186dc8a6fb077e613129e31a96 100644 (file)
@@ -1816,10 +1816,9 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                     // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
                     add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
                 }
-                if middle < ann.line_end - 1 {
-                    for line in ann.line_end - 1..ann.line_end {
-                        add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
-                    }
+                let line_end = ann.line_end - 1;
+                if middle < line_end {
+                    add_annotation_to_file(&mut output, file.clone(), line_end, ann.as_line());
                 }
             } else {
                 end_ann.annotation_type = AnnotationType::Singleline;
index 63df052a225041095d263a75ae11e51d45dd33f9..9743cf0d805a3eac513bc6568ad62c7997c0a996 100644 (file)
@@ -704,6 +704,9 @@ pub fn err_count(&self) -> usize {
     pub fn has_errors(&self) -> bool {
         self.inner.borrow().has_errors()
     }
+    pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
+        self.inner.borrow().has_errors_or_delayed_span_bugs()
+    }
 
     pub fn print_error_count(&self, registry: &Registry) {
         self.inner.borrow_mut().print_error_count(registry)
@@ -862,6 +865,9 @@ fn err_count(&self) -> usize {
     fn has_errors(&self) -> bool {
         self.err_count() > 0
     }
+    fn has_errors_or_delayed_span_bugs(&self) -> bool {
+        self.has_errors() || !self.delayed_span_bugs.is_empty()
+    }
 
     fn abort_if_errors_and_should_abort(&mut self) {
         self.emit_stashed_diagnostics();
index 511175de5d8d1c043509f9ed4239ef2769e00896..cbebdeb602cc0b1101a8ebf36c1f36a4abd90f96 100644 (file)
@@ -307,7 +307,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
 
     let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
 
-    if sess.has_errors() {
+    if sess.has_errors_or_delayed_span_bugs() {
         // If there have been any errors during compilation, we don't want to
         // publish this session directory. Rather, we'll just delete it.
 
index f5935c9969baa04b367cb654e4d1b2b524c5a63f..ecc66e60175f0c4c091c015bdcbad650d3b4362c 100644 (file)
@@ -22,6 +22,10 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
         if sess.opts.incremental.is_none() {
             return;
         }
+        // This is going to be deleted in finalize_session_directory, so let's not create it
+        if sess.has_errors_or_delayed_span_bugs() {
+            return;
+        }
 
         let query_cache_path = query_cache_path(sess);
         let dep_graph_path = dep_graph_path(sess);
@@ -60,6 +64,10 @@ pub fn save_work_product_index(sess: &Session,
     if sess.opts.incremental.is_none() {
         return;
     }
+    // This is going to be deleted in finalize_session_directory, so let's not create it
+    if sess.has_errors_or_delayed_span_bugs() {
+            return;
+    }
 
     debug!("save_work_product_index()");
     dep_graph.assert_ignored();
index 7c19449f96b86f674bcb627584c02603d1910435..e3c3966c2f5e0e39e47ddf190904d9c632280b92 100644 (file)
@@ -1125,8 +1125,12 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
                 .map(|pred| pred.span()).collect();
             let mut err = cx.struct_span_lint(TYPE_ALIAS_BOUNDS, spans,
                 "where clauses are not enforced in type aliases");
-            err.help("the clause will not be checked when the type alias is used, \
-                      and should be removed");
+            err.span_suggestion(
+                type_alias_generics.where_clause.span_for_predicates_or_empty_place(),
+                "the clause will not be checked when the type alias is used, and should be removed",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
             if !suggested_changing_assoc_types {
                 TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
                 suggested_changing_assoc_types = true;
@@ -1136,14 +1140,19 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         // The parameters must not have bounds
         for param in type_alias_generics.params.iter() {
             let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
+            let suggestion = spans.iter().map(|sp| {
+                let start = param.span.between(*sp); // Include the `:` in `T: Bound`.
+                (start.to(*sp), String::new())
+            }).collect();
             if !spans.is_empty() {
                 let mut err = cx.struct_span_lint(
                     TYPE_ALIAS_BOUNDS,
                     spans,
                     "bounds on generic parameters are not enforced in type aliases",
                 );
-                err.help("the bound will not be checked when the type alias is used, \
-                          and should be removed");
+                let msg = "the bound will not be checked when the type alias is used, \
+                           and should be removed";
+                err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable);
                 if !suggested_changing_assoc_types {
                     TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
                     suggested_changing_assoc_types = true;
index 9a826de4b6eafb86ff8642c6ffbde9cf351da1d5..af43030d0f2aecf9e5038f4385d0995aded2e424 100644 (file)
@@ -598,6 +598,25 @@ fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
         self.check_unused_parens_pat(cx, &arm.pat, false, false);
     }
+
+    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
+        if let &ast::TyKind::Paren(ref r) = &ty.kind {
+            match &r.kind {
+                &ast::TyKind::TraitObject(..) => {}
+                &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {}
+                _ => {
+                    let pattern_text = if let Ok(snippet) = cx.sess().source_map()
+                        .span_to_snippet(ty.span) {
+                            snippet
+                        } else {
+                            pprust::ty_to_string(ty)
+                        };
+
+                    Self::remove_outer_parens(cx, ty.span, &pattern_text, "type", (false, false));
+                }
+            }
+        }
+    }
 }
 
 declare_lint! {
index 234a5395047c6a321d2166a020ee45d759922e7d..07c49d91797d46fb1a0928436ab8052c39c5fee4 100644 (file)
@@ -3,7 +3,7 @@
 use crate::cstore::{self, CStore, MetadataBlob};
 use crate::locator::{self, CratePaths};
 use crate::schema::{CrateRoot, CrateDep};
-use rustc_data_structures::sync::{RwLock, Lock, AtomicCell};
+use rustc_data_structures::sync::{Lock, Once, AtomicCell};
 
 use rustc::hir::def_id::CrateNum;
 use rustc_data_structures::svh::Svh;
@@ -191,6 +191,7 @@ fn register_crate(
 
         let Library { source, metadata } = lib;
         let crate_root = metadata.get_root();
+        let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash);
         self.verify_no_symbol_conflicts(span, &crate_root);
 
         let private_dep = self.sess.opts.externs.get(&name.as_str())
@@ -245,11 +246,12 @@ fn register_crate(
             def_path_table,
             trait_impls,
             root: crate_root,
+            host_hash,
             blob: metadata,
             cnum_map,
             cnum,
             dependencies: Lock::new(dependencies),
-            source_map_import_info: RwLock::new(vec![]),
+            source_map_import_info: Once::new(),
             alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index),
             dep_kind: Lock::new(dep_kind),
             source,
@@ -283,9 +285,7 @@ fn load_proc_macro<'b>(
                 LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
                 LoadResult::Loaded(library) => Some(LoadResult::Loaded(library))
             };
-            // Don't look for a matching hash when looking for the host crate.
-            // It won't be the same as the target crate hash
-            locate_ctxt.hash = None;
+            locate_ctxt.hash = locate_ctxt.host_hash;
             // Use the locate_ctxt when looking for the host proc macro crate, as that is required
             // so we want it to affect the error message
             (locate_ctxt, result)
@@ -334,10 +334,15 @@ fn maybe_resolve_crate<'b>(
         dep: Option<(&'b CratePaths, &'b CrateDep)>,
     ) -> Result<CrateNum, LoadError<'b>> {
         info!("resolving crate `{}`", name);
-        let (root, hash, extra_filename, path_kind) = match dep {
-            Some((root, dep)) =>
-                (Some(root), Some(&dep.hash), Some(&dep.extra_filename[..]), PathKind::Dependency),
-            None => (None, None, None, PathKind::Crate),
+        let (root, hash, host_hash, extra_filename, path_kind) = match dep {
+            Some((root, dep)) => (
+                Some(root),
+                Some(&dep.hash),
+                dep.host_hash.as_ref(),
+                Some(&dep.extra_filename[..]),
+                PathKind::Dependency
+            ),
+            None => (None, None, None, None, PathKind::Crate),
         };
         let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
             (LoadResult::Previous(cnum), None)
@@ -348,6 +353,7 @@ fn maybe_resolve_crate<'b>(
                 span,
                 crate_name: name,
                 hash,
+                host_hash,
                 extra_filename,
                 filesearch: self.sess.target_filesearch(path_kind),
                 target: &self.sess.target.target,
index 6b06cf575edcf5557aeddaf70335f4f4e7e809de..b7596d2018f7efa7dbbccf165a0f379fa4ddac4a 100644 (file)
@@ -9,7 +9,8 @@
 use rustc::mir::interpret::AllocDecodingState;
 use rustc_index::vec::IndexVec;
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell};
+use rustc_data_structures::sync::{Lrc, Lock, MetadataRef, Once, AtomicCell};
+use rustc_data_structures::svh::Svh;
 use syntax::ast;
 use syntax::edition::Edition;
 use syntax_expand::base::SyntaxExtension;
@@ -62,7 +63,7 @@
     /// Proc macro descriptions for this crate, if it's a proc macro crate.
     crate raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
-    crate source_map_import_info: RwLock<Vec<ImportedSourceFile>>,
+    crate source_map_import_info: Once<Vec<ImportedSourceFile>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     crate alloc_decoding_state: AllocDecodingState,
     /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
@@ -87,6 +88,8 @@
     /// Whether or not this crate should be consider a private dependency
     /// for purposes of the 'exported_private_dependencies' lint
     crate private_dep: bool,
+    /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
+    crate host_hash: Option<Svh>,
 
     // --- Data used only for improving diagnostics ---
 
index cdf5da006064a79a7ba12d1f5c0ec82ff0c71672..c5f830c0d042054d04a4d8769bf9f429d2bb887a 100644 (file)
@@ -9,7 +9,6 @@
 use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
-use rustc::middle::dependency_format::Linkage;
 use rustc::hir::def;
 use rustc::hir;
 use rustc::session::{CrateDisambiguator, Session};
@@ -235,26 +234,11 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     used_crate_source => { Lrc::new(cdata.source.clone()) }
 
     exported_symbols => {
-        let mut syms = cdata.exported_symbols(tcx);
-
-        // When linked into a dylib crates don't export their generic symbols,
-        // so if that's happening then we can't load upstream monomorphizations
-        // from this crate.
-        let formats = tcx.dependency_formats(LOCAL_CRATE);
-        let remove_generics = formats.iter().any(|(_ty, list)| {
-            match list.get(def_id.krate.as_usize() - 1) {
-                Some(Linkage::IncludedFromDylib) | Some(Linkage::Dynamic) => true,
-                _ => false,
-            }
-        });
-        if remove_generics {
-            syms.retain(|(sym, _threshold)| {
-                match sym {
-                    ExportedSymbol::Generic(..) => false,
-                    _ => return true,
-                }
-            });
-        }
+        let syms = cdata.exported_symbols(tcx);
+
+        // FIXME rust-lang/rust#64319, rust-lang/rust#64872: We want
+        // to block export of generics from dylibs, but we must fix
+        // rust-lang/rust#65890 before we can do that robustly.
 
         Arc::new(syms)
     }
@@ -505,6 +489,10 @@ fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh
         self.get_crate_data(cnum).root.hash
     }
 
+    fn crate_host_hash_untracked(&self, cnum: CrateNum) -> Option<Svh> {
+        self.get_crate_data(cnum).host_hash
+    }
+
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
index 0e6ecbbf0176a8c0a69900df4e12e21ca89eafac..c5954e1ea1d9830e2433ef64e8e4bff57e16abb0 100644 (file)
@@ -5,7 +5,7 @@
 use crate::table::{FixedSizeEncoding, PerDefTable};
 
 use rustc_index::vec::IndexVec;
-use rustc_data_structures::sync::{Lrc, ReadGuard};
+use rustc_data_structures::sync::Lrc;
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
 use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule};
@@ -664,7 +664,7 @@ fn get_variant(
         tcx: TyCtxt<'tcx>,
     ) -> ty::GenericPredicates<'tcx> {
         self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx))
-}
+    }
 
     crate fn get_predicates_defined_on(
         &self,
@@ -1290,87 +1290,68 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
     fn imported_source_files(
         &'a self,
         local_source_map: &source_map::SourceMap,
-    ) -> ReadGuard<'a, Vec<cstore::ImportedSourceFile>> {
-        {
-            let source_files = self.source_map_import_info.borrow();
-            if !source_files.is_empty() {
-                return source_files;
-            }
-        }
-
-        // Lock the source_map_import_info to ensure this only happens once
-        let mut source_map_import_info = self.source_map_import_info.borrow_mut();
-
-        if !source_map_import_info.is_empty() {
-            drop(source_map_import_info);
-            return self.source_map_import_info.borrow();
-        }
-
-        let external_source_map = self.root.source_map.decode(self);
-
-        let imported_source_files = external_source_map.map(|source_file_to_import| {
-            // We can't reuse an existing SourceFile, so allocate a new one
-            // containing the information we need.
-            let syntax_pos::SourceFile { name,
-                                      name_was_remapped,
-                                      src_hash,
-                                      start_pos,
-                                      end_pos,
-                                      mut lines,
-                                      mut multibyte_chars,
-                                      mut non_narrow_chars,
-                                      mut normalized_pos,
-                                      name_hash,
-                                      .. } = source_file_to_import;
-
-            let source_length = (end_pos - start_pos).to_usize();
-
-            // Translate line-start positions and multibyte character
-            // position into frame of reference local to file.
-            // `SourceMap::new_imported_source_file()` will then translate those
-            // coordinates to their new global frame of reference when the
-            // offset of the SourceFile is known.
-            for pos in &mut lines {
-                *pos = *pos - start_pos;
-            }
-            for mbc in &mut multibyte_chars {
-                mbc.pos = mbc.pos - start_pos;
-            }
-            for swc in &mut non_narrow_chars {
-                *swc = *swc - start_pos;
-            }
-            for np in &mut normalized_pos {
-                np.pos = np.pos - start_pos;
-            }
-
-            let local_version = local_source_map.new_imported_source_file(name,
-                                                                   name_was_remapped,
-                                                                   self.cnum.as_u32(),
-                                                                   src_hash,
-                                                                   name_hash,
-                                                                   source_length,
-                                                                   lines,
-                                                                   multibyte_chars,
-                                                                   non_narrow_chars,
-                                                                   normalized_pos);
-            debug!("CrateMetaData::imported_source_files alloc \
-                    source_file {:?} original (start_pos {:?} end_pos {:?}) \
-                    translated (start_pos {:?} end_pos {:?})",
-                   local_version.name, start_pos, end_pos,
-                   local_version.start_pos, local_version.end_pos);
-
-            cstore::ImportedSourceFile {
-                original_start_pos: start_pos,
-                original_end_pos: end_pos,
-                translated_source_file: local_version,
-            }
-        }).collect();
-
-        *source_map_import_info = imported_source_files;
-        drop(source_map_import_info);
+    ) -> &[cstore::ImportedSourceFile] {
+        self.source_map_import_info.init_locking(|| {
+            let external_source_map = self.root.source_map.decode(self);
+
+            external_source_map.map(|source_file_to_import| {
+                // We can't reuse an existing SourceFile, so allocate a new one
+                // containing the information we need.
+                let syntax_pos::SourceFile { name,
+                                          name_was_remapped,
+                                          src_hash,
+                                          start_pos,
+                                          end_pos,
+                                          mut lines,
+                                          mut multibyte_chars,
+                                          mut non_narrow_chars,
+                                          mut normalized_pos,
+                                          name_hash,
+                                          .. } = source_file_to_import;
+
+                let source_length = (end_pos - start_pos).to_usize();
+
+                // Translate line-start positions and multibyte character
+                // position into frame of reference local to file.
+                // `SourceMap::new_imported_source_file()` will then translate those
+                // coordinates to their new global frame of reference when the
+                // offset of the SourceFile is known.
+                for pos in &mut lines {
+                    *pos = *pos - start_pos;
+                }
+                for mbc in &mut multibyte_chars {
+                    mbc.pos = mbc.pos - start_pos;
+                }
+                for swc in &mut non_narrow_chars {
+                    *swc = *swc - start_pos;
+                }
+                for np in &mut normalized_pos {
+                    np.pos = np.pos - start_pos;
+                }
 
-        // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
-        self.source_map_import_info.borrow()
+                let local_version = local_source_map.new_imported_source_file(name,
+                                                                       name_was_remapped,
+                                                                       self.cnum.as_u32(),
+                                                                       src_hash,
+                                                                       name_hash,
+                                                                       source_length,
+                                                                       lines,
+                                                                       multibyte_chars,
+                                                                       non_narrow_chars,
+                                                                       normalized_pos);
+                debug!("CrateMetaData::imported_source_files alloc \
+                        source_file {:?} original (start_pos {:?} end_pos {:?}) \
+                        translated (start_pos {:?} end_pos {:?})",
+                       local_version.name, start_pos, end_pos,
+                       local_version.start_pos, local_version.end_pos);
+
+                cstore::ImportedSourceFile {
+                    original_start_pos: start_pos,
+                    original_end_pos: end_pos,
+                    translated_source_file: local_version,
+                }
+            }).collect()
+        })
     }
 
     /// Get the `DepNodeIndex` corresponding this crate. The result of this
index f6498f4eaa8919011a212465d0c3c971fb58acc2..f2b0cfa53050863090a428edeccce8dbec1cc98a 100644 (file)
@@ -1418,6 +1418,7 @@ fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
                 let dep = CrateDep {
                     name: self.tcx.original_crate_name(cnum),
                     hash: self.tcx.crate_hash(cnum),
+                    host_hash: self.tcx.crate_host_hash(cnum),
                     kind: self.tcx.dep_kind(cnum),
                     extra_filename: self.tcx.extra_filename(cnum),
                 };
index a5298402dd4115b95839ce89a65d2704d422bf92..4a263250f9b0d799fba07133e41ca264b6b8f5c4 100644 (file)
     pub span: Span,
     pub crate_name: Symbol,
     pub hash: Option<&'a Svh>,
+    pub host_hash: Option<&'a Svh>,
     pub extra_filename: Option<&'a str>,
     // points to either self.sess.target.target or self.sess.host, must match triple
     pub target: &'a Target,
@@ -929,6 +930,7 @@ pub fn find_plugin_registrar(
         span,
         crate_name: name,
         hash: None,
+        host_hash: None,
         extra_filename: None,
         filesearch: sess.host_filesearch(PathKind::Crate),
         target: &sess.host,
index ad39aa34fd5c8d3f1695d4936ad1749518bed1d8..8bece2511166e5923bf3207acfd9be3954331f9b 100644 (file)
@@ -217,6 +217,7 @@ macro_rules! Lazy {
 crate struct CrateDep {
     pub name: ast::Name,
     pub hash: Svh,
+    pub host_hash: Option<Svh>,
     pub kind: DepKind,
     pub extra_filename: String,
 }
index a46a1cc5647a9e597988d78254fba7e9ab39de69..1be1fcef61b6e4024ff2cf4af9780dca59cb02bd 100644 (file)
@@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> {
     body: &'cx Body<'tcx>,
     tcx: TyCtxt<'tcx>,
     kind: PrefixSet,
-    next: Option<(PlaceRef<'cx, 'tcx>)>,
+    next: Option<PlaceRef<'cx, 'tcx>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
index 419c905cb5127a070530064f1b056b4630f7cb21..c119ca536fb524fee9de6768b63fa7d83e3c8786 100644 (file)
@@ -2545,7 +2545,7 @@ const fn foo() -> impl T {
 //  E0471, // constant evaluation error (in pattern)
 //  E0385, // {} in an aliasable location
     E0521, // borrowed data escapes outside of closure
-    E0526, // shuffle indices are not constant
+//  E0526, // shuffle indices are not constant
     E0594, // cannot assign to {}
 //  E0598, // lifetime of {} is too short to guarantee its contents can be...
     E0625, // thread-local statics cannot be accessed at compile-time
index 519f4f0322228e9474d7c45f674eaec7e09c7496..c08e4c896094b6f99e00cc99e4fcff33d7fc0e09 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
 
 use super::{
-    Machine, PlaceTy, OpTy, InterpCx,
+    Machine, PlaceTy, OpTy, InterpCx, ImmTy,
 };
 
 mod caller_location;
@@ -249,6 +249,29 @@ pub fn emulate_intrinsic(
                 let result = Scalar::from_uint(truncated_bits, layout.size);
                 self.write_scalar(result, dest)?;
             }
+
+            "ptr_offset_from" => {
+                let a = self.read_immediate(args[0])?.to_scalar()?.to_ptr()?;
+                let b = self.read_immediate(args[1])?.to_scalar()?.to_ptr()?;
+                if a.alloc_id != b.alloc_id {
+                    throw_ub_format!(
+                        "ptr_offset_from cannot compute offset of pointers into different \
+                        allocations.",
+                    );
+                }
+                let usize_layout = self.layout_of(self.tcx.types.usize)?;
+                let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout);
+                let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout);
+                let (val, _overflowed, _ty) = self.overflowing_binary_op(
+                    BinOp::Sub, a_offset, b_offset,
+                )?;
+                let pointee_layout = self.layout_of(substs.type_at(0))?;
+                let isize_layout = self.layout_of(self.tcx.types.isize)?;
+                let val = ImmTy::from_scalar(val, isize_layout);
+                let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
+                self.exact_div(val, size, dest)?;
+            }
+
             "transmute" => {
                 self.copy_op_transmute(args[0], dest)?;
             }
@@ -354,4 +377,30 @@ pub fn hook_fn(
             return Ok(false);
         }
     }
+
+    pub fn exact_div(
+        &mut self,
+        a: ImmTy<'tcx, M::PointerTag>,
+        b: ImmTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx> {
+        // Performs an exact division, resulting in undefined behavior where
+        // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`.
+        // First, check x % y != 0.
+        if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 {
+            // Then, check if `b` is -1, which is the "min_value / -1" case.
+            let minus1 = Scalar::from_int(-1, dest.layout.size);
+            let b = b.to_scalar().unwrap();
+            if b == minus1 {
+                throw_ub_format!("exact_div: result of dividing MIN by -1 cannot be represented")
+            } else {
+                throw_ub_format!(
+                    "exact_div: {} cannot be divided by {} without remainder",
+                    a.to_scalar().unwrap(),
+                    b,
+                )
+            }
+        }
+        self.binop_ignore_overflow(BinOp::Div, a, b, dest)
+    }
 }
index 4fd5e6a5435517742aa728c558b637ecaf137397..ae23971849eea6819ab6d5f1e05174de84e9587c 100644 (file)
@@ -19,7 +19,7 @@
 };
 pub use rustc::mir::interpret::ScalarMaybeUndef;
 
-/// A `Value` represents a single immediate self-contained Rust value.
+/// An `Immediate` represents a single immediate self-contained Rust value.
 ///
 /// For optimization of a few very common cases, there is also a representation for a pair of
 /// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary
index 8def717f1580a3699f069e367689c944449eade0..83f3aafc55cb10cc8547a0f5a1430db7c47c79bc 100644 (file)
@@ -80,6 +80,17 @@ pub enum Candidate {
     Argument { bb: BasicBlock, index: usize },
 }
 
+impl Candidate {
+    /// Returns `true` if we should use the "explicit" rules for promotability for this `Candidate`.
+    fn forces_explicit_promotion(&self) -> bool {
+        match self {
+            Candidate::Ref(_) |
+            Candidate::Repeat(_) => false,
+            Candidate::Argument { .. } => true,
+        }
+    }
+}
+
 fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Vec<usize>> {
     let attrs = tcx.get_attrs(def_id);
     let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?;
@@ -727,16 +738,22 @@ pub fn validate_candidates(
     };
 
     candidates.iter().copied().filter(|&candidate| {
-        validator.explicit = match candidate {
-            Candidate::Ref(_) |
-            Candidate::Repeat(_) => false,
-            Candidate::Argument { .. } => true,
-        };
+        validator.explicit = candidate.forces_explicit_promotion();
 
         // FIXME(eddyb) also emit the errors for shuffle indices
         // and `#[rustc_args_required_const]` arguments here.
 
-        validator.validate_candidate(candidate).is_ok()
+        let is_promotable = validator.validate_candidate(candidate).is_ok();
+        match candidate {
+            Candidate::Argument { bb, index } if !is_promotable => {
+                let span = body[bb].terminator().source_info.span;
+                let msg = format!("argument {} is required to be a constant", index + 1);
+                tcx.sess.span_err(span, &msg);
+            }
+            _ => ()
+        }
+
+        is_promotable
     }).collect()
 }
 
index 3702dd9ad493fb3df20685c10d22e8addca7b8bb..5463b9444731f8c40657f0b156c6ef5609dd3d16 100644 (file)
@@ -564,6 +564,7 @@ fn in_call(
                             | "transmute"
                             | "simd_insert"
                             | "simd_extract"
+                            | "ptr_offset_from"
                             => return true,
 
                             _ => {}
@@ -1606,20 +1607,12 @@ fn visit_terminator_kind(&mut self,
                     // This is not a problem, because the argument explicitly
                     // requests constness, in contrast to regular promotion
                     // which happens even without the user requesting it.
-                    // We can error out with a hard error if the argument is not
-                    // constant here.
+                    //
+                    // `promote_consts` is responsible for emitting the error if
+                    // the argument is not promotable.
                     if !IsNotPromotable::in_operand(self, arg) {
                         debug!("visit_terminator_kind: candidate={:?}", candidate);
                         self.promotion_candidates.push(candidate);
-                    } else {
-                        if is_shuffle {
-                            span_err!(self.tcx.sess, self.span, E0526,
-                                      "shuffle indices are not constant");
-                        } else {
-                            self.tcx.sess.span_err(self.span,
-                                &format!("argument {} is required to be a constant",
-                                         i + 1));
-                        }
                     }
                 }
             }
index 7fcb7a40a3c0893d5cdbd8a291236fb516dbfabd..ff2946d3a690e1cdbbe56a118d354c5957b34b47 100644 (file)
@@ -16,10 +16,22 @@ pub fn write_mir_graphviz<W>(
 where
     W: Write,
 {
-    for def_id in dump_mir_def_ids(tcx, single) {
+    let def_ids = dump_mir_def_ids(tcx, single);
+
+    let use_subgraphs = def_ids.len() > 1;
+    if use_subgraphs {
+        writeln!(w, "digraph __crate__ {{")?;
+    }
+
+    for def_id in def_ids {
         let body = &tcx.optimized_mir(def_id);
-        write_mir_fn_graphviz(tcx, def_id, body, w)?;
+        write_mir_fn_graphviz(tcx, def_id, body, use_subgraphs, w)?;
     }
+
+    if use_subgraphs {
+        writeln!(w, "}}")?;
+    }
+
     Ok(())
 }
 
@@ -38,12 +50,16 @@ pub fn write_mir_fn_graphviz<'tcx, W>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     body: &Body<'_>,
+    subgraph: bool,
     w: &mut W,
 ) -> io::Result<()>
 where
     W: Write,
 {
-    writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;
+    let kind = if subgraph { "subgraph" } else { "digraph" };
+    let cluster = if subgraph { "cluster_" } else { "" }; // Prints a border around MIR
+    let def_name = graphviz_safe_def_name(def_id);
+    writeln!(w, "{} {}Mir_{} {{", kind, cluster, def_name)?;
 
     // Global graph properties
     writeln!(w, r#"    graph [fontname="monospace"];"#)?;
@@ -55,12 +71,12 @@ pub fn write_mir_fn_graphviz<'tcx, W>(
 
     // Nodes
     for (block, _) in body.basic_blocks().iter_enumerated() {
-        write_node(block, body, w)?;
+        write_node(def_id, block, body, w)?;
     }
 
     // Edges
     for (source, _) in body.basic_blocks().iter_enumerated() {
-        write_edges(source, body, w)?;
+        write_edges(def_id, source, body, w)?;
     }
     writeln!(w, "}}")
 }
@@ -111,25 +127,37 @@ pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
     fini(w)?;
 
     // Close the table
-    writeln!(w, "</table>")
+    write!(w, "</table>")
 }
 
 /// Write a graphviz DOT node for the given basic block.
-fn write_node<W: Write>(block: BasicBlock, body: &Body<'_>, w: &mut W) -> io::Result<()> {
+fn write_node<W: Write>(
+    def_id: DefId,
+    block: BasicBlock,
+    body: &Body<'_>,
+    w: &mut W,
+) -> io::Result<()> {
     // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
-    write!(w, r#"    {} [shape="none", label=<"#, node(block))?;
+    write!(w, r#"    {} [shape="none", label=<"#, node(def_id, block))?;
     write_node_label(block, body, w, 1, |_| Ok(()), |_| Ok(()))?;
     // Close the node label and the node itself.
     writeln!(w, ">];")
 }
 
 /// Write graphviz DOT edges with labels between the given basic block and all of its successors.
-fn write_edges<W: Write>(source: BasicBlock, body: &Body<'_>, w: &mut W) -> io::Result<()> {
+fn write_edges<W: Write>(
+    def_id: DefId,
+    source: BasicBlock,
+    body: &Body<'_>,
+    w: &mut W,
+) -> io::Result<()> {
     let terminator = body[source].terminator();
     let labels = terminator.kind.fmt_successor_labels();
 
     for (&target, label) in terminator.successors().zip(labels) {
-        writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label)?;
+        let src = node(def_id, source);
+        let trg = node(def_id, target);
+        writeln!(w, r#"    {} -> {} [label="{}"];"#, src, trg, label)?;
     }
 
     Ok(())
@@ -181,8 +209,8 @@ fn write_graph_label<'tcx, W: Write>(
     writeln!(w, ">;")
 }
 
-fn node(block: BasicBlock) -> String {
-    format!("bb{}", block.index())
+fn node(def_id: DefId, block: BasicBlock) -> String {
+    format!("bb{}__{}", block.index(), graphviz_safe_def_name(def_id))
 }
 
 fn escape<T: Debug>(t: &T) -> String {
index 7f6b60b1b116b48877fb18214adab1247407c997..89f298846d2f5ad6bc909384279d9d7922231d42 100644 (file)
@@ -145,7 +145,7 @@ fn dump_matched_mir_node<'tcx, F>(
         let _: io::Result<()> = try {
             let mut file =
                 create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
-            write_mir_fn_graphviz(tcx, source.def_id(), body, &mut file)?;
+            write_mir_fn_graphviz(tcx, source.def_id(), body, false, &mut file)?;
         };
     }
 }
index c18bdfad22cf074f190fed46038a9f126f93a026..648c5104b1af70050cb2ca668d8b8c8334016224 100644 (file)
@@ -256,9 +256,9 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                                 if self.r.is_accessible_from(vis, parent_scope.module) {
                                     vis
                                 } else {
-                                    let msg =
-                                        "visibilities can only be restricted to ancestor modules";
-                                    self.r.session.span_err(path.span, msg);
+                                    struct_span_err!(self.r.session, path.span, E0742,
+                                        "visibilities can only be restricted to ancestor modules")
+                                        .emit();
                                     ty::Visibility::Public
                                 }
                             }
index 9515c87ce4bb5194b813b738a97e1d56ee8bce38..c59959ae4f4c541c2f7f2eafcb786d076afbba45 100644 (file)
@@ -1823,6 +1823,61 @@ trait Hello {
 ```
 "##,
 
+E0577: r##"
+Something other than a module was found in visibility scope.
+
+Erroneous code example:
+
+```compile_fail,E0577,edition2018
+pub struct Sea;
+
+pub (in crate::Sea) struct Shark; // error!
+
+fn main() {}
+```
+
+`Sea` is not a module, therefore it is invalid to use it in a visibility path.
+To fix this error we need to ensure `Sea` is a module.
+
+Please note that the visibility scope can only be applied on ancestors!
+
+```edition2018
+pub mod Sea {
+    pub (in crate::Sea) struct Shark; // ok!
+}
+
+fn main() {}
+```
+"##,
+
+E0578: r##"
+A module cannot be found and therefore, the visibility cannot be determined.
+
+Erroneous code example:
+
+```compile_fail,E0578,edition2018
+foo!();
+
+pub (in ::Sea) struct Shark; // error!
+
+fn main() {}
+```
+
+Because of the call to the `foo` macro, the compiler guesses that the missing
+module could be inside it and fails because the macro definition cannot be
+found.
+
+To fix this error, please be sure that the module is in scope:
+
+```edition2018
+pub mod Sea {
+    pub (in crate::Sea) struct Shark;
+}
+
+fn main() {}
+```
+"##,
+
 E0603: r##"
 A private item was used outside its scope.
 
@@ -1910,6 +1965,7 @@ fn main() {
 
 Const parameters cannot depend on type parameters.
 The following is therefore invalid:
+
 ```compile_fail,E0741
 #![feature(const_generics)]
 
@@ -1933,6 +1989,44 @@ struct Foo<X = Box<Self>> {
 ```
 "##,
 
+E0742: r##"
+Visibility is restricted to a module which isn't an ancestor of the current
+item.
+
+Erroneous code example:
+
+```compile_fail,E0742,edition2018
+pub mod Sea {}
+
+pub (in crate::Sea) struct Shark; // error!
+
+fn main() {}
+```
+
+To fix this error, we need to move the `Shark` struct inside the `Sea` module:
+
+```edition2018
+pub mod Sea {
+    pub (in crate::Sea) struct Shark; // ok!
+}
+
+fn main() {}
+```
+
+Of course, you can do it as long as the module you're referring to is an
+ancestor:
+
+```edition2018
+pub mod Earth {
+    pub mod Sea {
+        pub (in crate::Earth) struct Shark; // ok!
+    }
+}
+
+fn main() {}
+```
+"##,
+
 ;
 //  E0153, unused error code
 //  E0157, unused error code
@@ -1951,6 +2045,4 @@ struct Foo<X = Box<Self>> {
 //  E0427, merged into 530
 //  E0467, removed
 //  E0470, removed
-    E0577,
-    E0578,
 }
index c95009858e4c0f91353cf3681043a841dbf26206..03ff8ba7dc158660cc1011f6a126cd9f445fe1bb 100644 (file)
@@ -977,8 +977,9 @@ fn finalize_import(
                 if !is_prelude &&
                    max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
                    !max_vis.get().is_at_least(directive.vis.get(), &*self) {
-                    let msg = "A non-empty glob must import something with the glob's visibility";
-                    self.r.session.span_err(directive.span, msg);
+                    let msg =
+                    "glob import doesn't reexport anything because no candidate is public enough";
+                    self.r.session.buffer_lint(UNUSED_IMPORTS, directive.id, directive.span, msg);
                 }
                 return None;
             }
index e282936b5d9e7e762938fc483af2dabddc0f315b..a372106d3795b57dc5c8a7615a4c9ca1828a20f4 100644 (file)
@@ -300,7 +300,16 @@ fn process_method(
             }
 
             if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
-                v.visit_ty(ret_ty);
+                // In async functions, return types are desugared and redefined
+                // as an `impl Trait` existential type. Because of this, to match
+                // the definition paths when resolving nested types we need to
+                // start walking from the newly-created definition.
+                match sig.header.asyncness.node {
+                    ast::IsAsync::Async { return_impl_trait_id, .. } => {
+                        v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty))
+                    }
+                    _ => v.visit_ty(ret_ty)
+                }
             }
 
             // walk the fn body
@@ -369,6 +378,7 @@ fn process_fn(
         &mut self,
         item: &'l ast::Item,
         decl: &'l ast::FnDecl,
+        header: &'l ast::FnHeader,
         ty_params: &'l ast::Generics,
         body: &'l ast::Block,
     ) {
@@ -391,7 +401,16 @@ fn process_fn(
                     // FIXME: Opaque type desugaring prevents us from easily
                     // processing trait bounds. See `visit_ty` for more details.
                 } else {
-                    v.visit_ty(&ret_ty);
+                    // In async functions, return types are desugared and redefined
+                    // as an `impl Trait` existential type. Because of this, to match
+                    // the definition paths when resolving nested types we need to
+                    // start walking from the newly-created definition.
+                    match header.asyncness.node {
+                        ast::IsAsync::Async { return_impl_trait_id, .. } => {
+                            v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty))
+                        }
+                        _ => v.visit_ty(ret_ty)
+                    }
                 }
             }
 
@@ -1315,8 +1334,8 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                     );
                 }
             }
-            Fn(ref decl, .., ref ty_params, ref body) => {
-                self.process_fn(item, &decl, ty_params, &body)
+            Fn(ref decl, ref header, ref ty_params, ref body) => {
+                self.process_fn(item, &decl, &header, ty_params, &body)
             }
             Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
             Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
index 6a2c8c495372f2d3483283aa7c6dd9065f975e41..906c704c804f36ff7df85f30284c296934e4c5c4 100644 (file)
@@ -9,12 +9,8 @@ pub fn target() -> Result<Target, String> {
                                "-s".to_string(),
                                "ASSERTIONS=1".to_string(),
                                "-s".to_string(),
-                               "DISABLE_EXCEPTION_CATCHING=1".to_string(),
-                               "-s".to_string(),
                                "ABORTING_MALLOC=0".to_string(),
-                               // FIXME(tlively): Enable this linker option once libc type errors
-                               // are resolved. See https://github.com/rust-lang/libc/pull/1478.
-                               // "-Wl,--fatal-warnings".to_string(),
+                               "-Wl,--fatal-warnings".to_string(),
                                ]);
 
     let opts = TargetOptions {
@@ -24,10 +20,7 @@ pub fn target() -> Result<Target, String> {
         linker: None,
         linker_is_gnu: true,
         is_like_emscripten: true,
-        // FIXME(tlively): Emscripten supports unwinding, but we would have to pass
-        // -enable-emscripten-cxx-exceptions to LLVM at codegen time and merge
-        // https://reviews.llvm.org/rG5c3cdef84b82464756bb571c13c31cf7773860c3to use it.
-        panic_strategy: PanicStrategy::Abort,
+        panic_strategy: PanicStrategy::Unwind,
         post_link_args,
         target_family: Some("unix".to_string()),
         .. wasm32_base::options()
index 76cc7062d3b8792145f1eb08e434b12d72ff10e0..33dc85fc68a2ee182ab4e8b7f2670d5e302e2d26 100644 (file)
@@ -317,6 +317,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
                 (1, vec![param(0), param(0)],
                 tcx.intern_tup(&[param(0), tcx.types.bool])),
 
+            "ptr_offset_from" =>
+                (1, vec![ tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0)) ], tcx.types.isize),
             "unchecked_div" | "unchecked_rem" | "exact_div" =>
                 (1, vec![param(0), param(0)], param(0)),
             "unchecked_shl" | "unchecked_shr" |
index 83793f9d8210d7cb8d4ad3d98b4a651f64e54eea..697dee0216e3bfbcc1af550036f18dfb8c194e3a 100644 (file)
@@ -106,61 +106,6 @@ pub fn render<T: Print, S: Print>(
     <section id=\"main\" class=\"content\">{content}</section>\
     <section id=\"search\" class=\"content hidden\"></section>\
     <section class=\"footer\"></section>\
-    <aside id=\"help\" class=\"hidden\">\
-        <div>\
-            <h1 class=\"hidden\">Help</h1>\
-            <div class=\"shortcuts\">\
-                <h2>Keyboard Shortcuts</h2>\
-                <dl>\
-                    <dt><kbd>?</kbd></dt>\
-                    <dd>Show this help dialog</dd>\
-                    <dt><kbd>S</kbd></dt>\
-                    <dd>Focus the search field</dd>\
-                    <dt><kbd>↑</kbd></dt>\
-                    <dd>Move up in search results</dd>\
-                    <dt><kbd>↓</kbd></dt>\
-                    <dd>Move down in search results</dd>\
-                    <dt><kbd>↹</kbd></dt>\
-                    <dd>Switch tab</dd>\
-                    <dt><kbd>&#9166;</kbd></dt>\
-                    <dd>Go to active search result</dd>\
-                    <dt><kbd>+</kbd></dt>\
-                    <dd>Expand all sections</dd>\
-                    <dt><kbd>-</kbd></dt>\
-                    <dd>Collapse all sections</dd>\
-                </dl>\
-            </div>\
-            <div class=\"infos\">\
-                <h2>Search Tricks</h2>\
-                <p>\
-                    Prefix searches with a type followed by a colon (e.g., \
-                    <code>fn:</code>) to restrict the search to a given type.\
-                </p>\
-                <p>\
-                    Accepted types are: <code>fn</code>, <code>mod</code>, \
-                    <code>struct</code>, <code>enum</code>, \
-                    <code>trait</code>, <code>type</code>, <code>macro</code>, \
-                    and <code>const</code>.\
-                </p>\
-                <p>\
-                    Search functions by type signature (e.g., \
-                    <code>vec -> usize</code> or <code>* -> vec</code>)\
-                </p>\
-                <p>\
-                    Search multiple things at once by splitting your query with comma (e.g., \
-                    <code>str,u8</code> or <code>String,struct:Vec,test</code>)\
-                </p>\
-                <p>\
-                    You can look for items with an exact name by putting double quotes around \
-                    your request: <code>\"string\"</code>\
-                </p>\
-                <p>\
-                    Look for items inside another one by searching for a path: \
-                    <code>vec::Vec</code>\
-                </p>\
-            </div>\
-        </div>\
-    </aside>\
     {after_content}\
     <script>\
         window.rootPath = \"{root_path}\";\
index a0e07d58c9da9d25e0ee956746d472a25c2765a4..de19ca3ed333a1676498549e98e803f3c86654a7 100644 (file)
@@ -379,9 +379,13 @@ function getSearchElement() {
 
                 set_fragment(cur_id);
             }
-        } else if (hasClass(document.getElementById("help"), "hidden") === false) {
-            addClass(document.getElementById("help"), "hidden");
-            removeClass(document.body, "blur");
+        } else if (hasClass(getHelpElement(), "hidden") === false) {
+            var help = getHelpElement();
+            var is_inside_help_popup = ev.target !== help && help.contains(ev.target);
+            if (is_inside_help_popup === false) {
+                addClass(help, "hidden");
+                removeClass(document.body, "blur");
+            }
         } else {
             // Making a collapsed element visible on onhashchange seems
             // too late
@@ -1218,7 +1222,7 @@ function getSearchElement() {
                 }
                 dst = dst[0];
                 if (window.location.pathname === dst.pathname) {
-                    addClass(document.getElementById("search"), "hidden");
+                    addClass(getSearchElement(), "hidden");
                     removeClass(main, "hidden");
                     document.location.href = dst.href;
                 }
@@ -2454,7 +2458,7 @@ function getSearchElement() {
     function putBackSearch(search_input) {
         if (search_input.value !== "") {
             addClass(main, "hidden");
-            removeClass(document.getElementById("search"), "hidden");
+            removeClass(getSearchElement(), "hidden");
             if (browserSupportsHistoryApi()) {
                 history.replaceState(search_input.value,
                                      "",
@@ -2553,6 +2557,53 @@ function getSearchElement() {
     }
 
     window.addSearchOptions = addSearchOptions;
+
+    function buildHelperPopup() {
+        var popup = document.createElement("aside");
+        addClass(popup, "hidden");
+        popup.id = "help";
+
+        var container = document.createElement("div");
+        var shortcuts = [
+            ["?", "Show this help dialog"],
+            ["S", "Focus the search field"],
+            ["↑", "Move up in search results"],
+            ["↓", "Move down in search results"],
+            ["↹", "Switch tab"],
+            ["&#9166;", "Go to active search result"],
+            ["+", "Expand all sections"],
+            ["-", "Collapse all sections"],
+        ].map(x => "<dt><kbd>" + x[0] + "</kbd></dt><dd>" + x[1] + "</dd>").join("");
+        var div_shortcuts = document.createElement("div");
+        addClass(div_shortcuts, "shortcuts");
+        div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
+
+        var infos = [
+            "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
+             restrict the search to a given type.",
+            "Accepted types are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
+             <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
+             and <code>const</code>.",
+            "Search functions by type signature (e.g., <code>vec -> usize</code> or \
+             <code>* -> vec</code>)",
+            "Search multiple things at once by splitting your query with comma (e.g., \
+             <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
+            "You can look for items with an exact name by putting double quotes around \
+             your request: <code>\"string\"</code>",
+            "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
+        ].map(x => "<p>" + x + "</p>").join("");
+        var div_infos = document.createElement("div");
+        addClass(div_infos, "infos");
+        div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
+
+        container.appendChild(div_shortcuts);
+        container.appendChild(div_infos);
+
+        popup.appendChild(container);
+        insertAfter(popup, getSearchElement());
+    }
+
+    buildHelperPopup();
 }());
 
 // Sets the focus on the search bar at the top of the page
index caa7f08f68cffb3fb15840ab08108ab8ba229e7b..ab34f8daad7197bd1d64ba1573e8a3a68c76863f 100644 (file)
@@ -322,9 +322,26 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                     continue;
                 }
 
+                // In order to correctly resolve intra-doc-links we need to
+                // pick a base AST node to work from.  If the documentation for
+                // this module came from an inner comment (//!) then we anchor
+                // our name resolution *inside* the module.  If, on the other
+                // hand it was an outer comment (///) then we anchor the name
+                // resolution in the parent module on the basis that the names
+                // used are more likely to be intended to be parent names.  For
+                // this, we set base_node to None for inner comments since
+                // we've already pushed this node onto the resolution stack but
+                // for outer comments we explicitly try and resolve against the
+                // parent_node first.
+                let base_node = if item.is_mod() && item.attrs.inner_docs {
+                    None
+                } else {
+                    parent_node
+                };
+
                 match kind {
                     Some(ns @ ValueNS) => {
-                        if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
+                        if let Ok(res) = self.resolve(path_str, ns, &current_item, base_node) {
                             res
                         } else {
                             resolution_failure(cx, &item, path_str, &dox, link_range);
@@ -335,7 +352,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         }
                     }
                     Some(ns @ TypeNS) => {
-                        if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
+                        if let Ok(res) = self.resolve(path_str, ns, &current_item, base_node) {
                             res
                         } else {
                             resolution_failure(cx, &item, path_str, &dox, link_range);
@@ -348,10 +365,10 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         let candidates = PerNS {
                             macro_ns: macro_resolve(cx, path_str).map(|res| (res, None)),
                             type_ns: self
-                                .resolve(path_str, TypeNS, &current_item, parent_node)
+                                .resolve(path_str, TypeNS, &current_item, base_node)
                                 .ok(),
                             value_ns: self
-                                .resolve(path_str, ValueNS, &current_item, parent_node)
+                                .resolve(path_str, ValueNS, &current_item, base_node)
                                 .ok()
                                 .and_then(|(res, fragment)| {
                                     // Constructors are picked up in the type namespace.
index 6b0225a1b443ae489c7cf09e1aa615fb81dea166..de2f12c9f33efa83e6cf73e9a14581592bea1473 100644 (file)
@@ -1818,7 +1818,7 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
 
     #[inline]
-    fn next(&mut self) -> Option<(&'a K)> {
+    fn next(&mut self) -> Option<&'a K> {
         self.inner.next().map(|(k, _)| k)
     }
     #[inline]
@@ -1841,7 +1841,7 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
 
     #[inline]
-    fn next(&mut self) -> Option<(&'a V)> {
+    fn next(&mut self) -> Option<&'a V> {
         self.inner.next().map(|(_, v)| v)
     }
     #[inline]
@@ -1864,7 +1864,7 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
     type Item = &'a mut V;
 
     #[inline]
-    fn next(&mut self) -> Option<(&'a mut V)> {
+    fn next(&mut self) -> Option<&'a mut V> {
         self.inner.next().map(|(_, v)| v)
     }
     #[inline]
index 69fcfa8b39ca5e5ea4ad1b1bbcae90266a823280..28d9906eb93b5d6ce3bdd7cac5d80d94a42067cb 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::os_str::{OsString, OsStr};
 
-#[stable(feature = "raw_os", since = "1.1.0")]
+#[stable(feature = "core_c_void", since = "1.30.0")]
 pub use core::ffi::c_void;
 
 #[unstable(feature = "c_variadic",
index 6595f54162f0a8a1ceeca203cf93ba5205937622..30db6a58d40c2032422cd1d1c89b5b506555acf5 100644 (file)
@@ -29,7 +29,7 @@
 ///
 /// # Examples
 ///
-/// Creates a new file and write bytes to it:
+/// Creates a new file and write bytes to it (you can also use [`write`]):
 ///
 /// ```no_run
 /// use std::fs::File;
@@ -42,7 +42,7 @@
 /// }
 /// ```
 ///
-/// Read the contents of a file into a [`String`]:
+/// Read the contents of a file into a [`String`] (you can also use [`read`]):
 ///
 /// ```no_run
 /// use std::fs::File;
@@ -89,6 +89,8 @@
 /// [`Write`]: ../io/trait.Write.html
 /// [`BufReader<R>`]: ../io/struct.BufReader.html
 /// [`sync_all`]: struct.File.html#method.sync_all
+/// [`read`]: fn.read.html
+/// [`write`]: fn.write.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
     inner: fs_imp::File,
@@ -397,6 +399,37 @@ pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
         OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())
     }
 
+    /// Returns a new OpenOptions object.
+    ///
+    /// This function returns a new OpenOptions object that you can use to
+    /// open or create a file with specific options if `open()` or `create()`
+    /// are not appropriate.
+    ///
+    /// It is equivalent to `OpenOptions::new()` but allows you to write more
+    /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")`
+    /// you can write `File::with_options().read(true).open("foo.txt"). This
+    /// also avoids the need to import `OpenOptions`.
+    ///
+    /// See the [`OpenOptions::new`] function for more details.
+    ///
+    /// [`OpenOptions::new`]: struct.OpenOptions.html#method.new
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(with_options)]
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::with_options().read(true).open("foo.txt")?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "with_options", issue = "65439")]
+    pub fn with_options() -> OpenOptions {
+        OpenOptions::new()
+    }
+
     /// Attempts to sync all OS-internal metadata to disk.
     ///
     /// This function will attempt to ensure that all in-memory data reaches the
index 6bcc59495e3635511bd7d63bbf807d8ec44e8a33..df6255a3e9e03306cedd55ff9d636e663b4d76e7 100644 (file)
@@ -6,7 +6,8 @@
 use crate::os::raw;
 use crate::sys;
 use crate::io;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::net;
 
 /// Raw file descriptors.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -110,3 +111,61 @@ fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO }
 impl<'a> AsRawFd for io::StderrLock<'a> {
     fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO }
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::UdpSocket {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
index c2ebc38c30039583c6264ec4296a56e50c3b3056..d0f467b303ff93615a0dfecf78fd816093e7bb69 100644 (file)
@@ -1,4 +1,3 @@
-// Uhhh
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 
@@ -7,7 +6,6 @@
 pub mod fs;
 pub mod raw;
 pub mod process;
-pub mod net;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod prelude {
diff --git a/src/libstd/sys/vxworks/ext/net.rs b/src/libstd/sys/vxworks/ext/net.rs
deleted file mode 100644 (file)
index 3f0a7e9..0000000
+++ /dev/null
@@ -1,1825 +0,0 @@
-#![stable(feature = "unix_socket", since = "1.10.0")]
-
-//! Unix-specific networking functionality
-
-#[cfg(unix)]
-use libc;
-
-use crate::ascii;
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io::{self, Initializer, IoSlice, IoSliceMut};
-use crate::mem;
-use crate::net::{self, Shutdown};
-use crate::os::unix::ffi::OsStrExt;
-use crate::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
-use crate::path::Path;
-use crate::time::Duration;
-use crate::sys::{self, cvt};
-use crate::sys::net::Socket;
-use crate::sys_common::{self, AsInner, FromInner, IntoInner};
-
-const MSG_NOSIGNAL: libc::c_int = 0x0;
-
-fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
-    // Work with an actual instance of the type since using a null pointer is UB
-    let base = addr as *const _ as usize;
-    let path = &addr.sun_path as *const _ as usize;
-    path - base
-}
-
-unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
-    let mut addr: libc::sockaddr_un = mem::zeroed();
-    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;
-
-    let bytes = path.as_os_str().as_bytes();
-
-    if bytes.contains(&0) {
-        return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                  "paths may not contain interior null bytes"));
-    }
-
-    if bytes.len() >= addr.sun_path.len() {
-        return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                  "path must be shorter than SUN_LEN"));
-    }
-    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
-        *dst = *src as libc::c_char;
-    }
-    // null byte for pathname addresses is already there because we zeroed the
-    // struct
-
-    let mut len = sun_path_offset(&addr) + bytes.len();
-    match bytes.get(0) {
-        Some(&0) | None => {}
-        Some(_) => len += 1,
-    }
-    Ok((addr, len as libc::socklen_t))
-}
-
-enum AddressKind<'a> {
-    Unnamed,
-    Pathname(&'a Path),
-    Abstract(&'a [u8]),
-}
-
-/// An address associated with a Unix socket.
-///
-/// # Examples
-///
-/// ```
-/// use std::os::unix::net::UnixListener;
-///
-/// let socket = match UnixListener::bind("/tmp/sock") {
-///     Ok(sock) => sock,
-///     Err(e) => {
-///         println!("Couldn't bind: {:?}", e);
-///         return
-///     }
-/// };
-/// let addr = socket.local_addr().expect("Couldn't get local address");
-/// ```
-#[derive(Clone)]
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct SocketAddr {
-    addr: libc::sockaddr_un,
-    len: libc::socklen_t,
-}
-
-impl SocketAddr {
-    fn new<F>(f: F) -> io::Result<SocketAddr>
-        where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int
-    {
-        unsafe {
-            let mut addr: libc::sockaddr_un = mem::zeroed();
-            let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
-            cvt(f(&mut addr as *mut _ as *mut _, &mut len))?;
-            SocketAddr::from_parts(addr, len)
-        }
-    }
-
-    fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<SocketAddr> {
-        if len == 0 {
-            // When there is a datagram from unnamed unix socket
-            // linux returns zero bytes of address
-            len = sun_path_offset(&addr) as libc::socklen_t;  // i.e., zero-length address
-        } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
-            return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                      "file descriptor did not correspond to a Unix socket"));
-        }
-
-        Ok(SocketAddr {
-            addr,
-            len,
-        })
-    }
-
-    /// Returns `true` if the address is unnamed.
-    ///
-    /// # Examples
-    ///
-    /// A named address:
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.is_unnamed(), false);
-    /// ```
-    ///
-    /// An unnamed address:
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let socket = UnixDatagram::unbound().unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.is_unnamed(), true);
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn is_unnamed(&self) -> bool {
-        if let AddressKind::Unnamed = self.address() {
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Returns the contents of this address if it is a `pathname` address.
-    ///
-    /// # Examples
-    ///
-    /// With a pathname:
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    /// use std::path::Path;
-    ///
-    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
-    /// ```
-    ///
-    /// Without a pathname:
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let socket = UnixDatagram::unbound().unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.as_pathname(), None);
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn as_pathname(&self) -> Option<&Path> {
-        if let AddressKind::Pathname(path) = self.address() {
-            Some(path)
-        } else {
-            None
-        }
-    }
-
-    fn address<'a>(&'a self) -> AddressKind<'a> {
-        let len = self.len as usize - sun_path_offset(&self.addr);
-        let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
-
-        if self.addr.sun_path[0] == 0 {
-            AddressKind::Abstract(&path[1..len])
-        } else {
-            AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
-        }
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for SocketAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.address() {
-            AddressKind::Unnamed => write!(fmt, "(unnamed)"),
-            AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
-            AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path),
-        }
-    }
-}
-
-struct AsciiEscaped<'a>(&'a [u8]);
-
-impl<'a> fmt::Display for AsciiEscaped<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "\"")?;
-        for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
-            write!(fmt, "{}", byte as char)?;
-        }
-        write!(fmt, "\"")
-    }
-}
-
-/// A Unix stream socket.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::unix::net::UnixStream;
-/// use std::io::prelude::*;
-///
-/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap();
-/// stream.write_all(b"hello world").unwrap();
-/// let mut response = String::new();
-/// stream.read_to_string(&mut response).unwrap();
-/// println!("{}", response);
-/// ```
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct UnixStream(Socket);
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for UnixStream {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixStream");
-        builder.field("fd", self.0.as_inner());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        if let Ok(addr) = self.peer_addr() {
-            builder.field("peer", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixStream {
-    /// Connects to the socket named by `path`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = match UnixStream::connect("/tmp/sock") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
-        fn inner(path: &Path) -> io::Result<UnixStream> {
-            unsafe {
-                let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?;
-                Ok(UnixStream(inner))
-            }
-        }
-        inner(path.as_ref())
-    }
-
-    /// Creates an unnamed pair of connected sockets.
-    ///
-    /// Returns two `UnixStream`s which are connected to each other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let (sock1, sock2) = match UnixStream::pair() {
-    ///     Ok((sock1, sock2)) => (sock1, sock2),
-    ///     Err(e) => {
-    ///         println!("Couldn't create a pair of sockets: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
-        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
-        Ok((UnixStream(i1), UnixStream(i2)))
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixStream` is a reference to the same stream that this
-    /// object references. Both handles will read and write the same stream of
-    /// data, and options set on one stream will be propagated to the other
-    /// stream.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn try_clone(&self) -> io::Result<UnixStream> {
-        self.0.duplicate().map(UnixStream)
-    }
-
-    /// Returns the socket address of the local half of this connection.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Returns the socket address of the remote half of this connection.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let addr = socket.peer_addr().expect("Couldn't get peer address");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Sets the read timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`read`] calls will block
-    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
-    /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
-    /// [`Duration`]: ../../../../std/time/struct.Duration.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
-    /// let err = result.unwrap_err();
-    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
-    }
-
-    /// Sets the write timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`write`] calls will block
-    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
-    /// passed to this method.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
-    /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
-    /// [`Duration`]: ../../../../std/time/struct.Duration.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::net::UdpSocket;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
-    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
-    /// let err = result.unwrap_err();
-    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
-    }
-
-    /// Returns the read timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
-    /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_RCVTIMEO)
-    }
-
-    /// Returns the write timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
-    /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_SNDTIMEO)
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// if let Ok(Some(err)) = socket.take_error() {
-    ///     println!("Got error: {:?}", err);
-    /// }
-    /// ```
-    ///
-    /// # Platform specific
-    /// On Redox this always returns `None`.
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0.take_error()
-    }
-
-    /// Shuts down the read, write, or both halves of this connection.
-    ///
-    /// This function will cause all pending and future I/O calls on the
-    /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of [`Shutdown`]).
-    ///
-    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::net::Shutdown;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        self.0.shutdown(how)
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl io::Read for UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        io::Read::read(&mut &*self, buf)
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        io::Read::read_vectored(&mut &*self, bufs)
-    }
-
-    #[inline]
-    unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> io::Read for &'a UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0.read_vectored(bufs)
-    }
-
-    #[inline]
-    unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl io::Write for UnixStream {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        io::Write::write(&mut &*self, buf)
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        io::Write::write_vectored(&mut &*self, bufs)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        io::Write::flush(&mut &*self)
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> io::Write for &'a UnixStream {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl AsRawFd for UnixStream {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.0.as_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl FromRawFd for UnixStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
-        UnixStream(Socket::from_inner(fd))
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl IntoRawFd for UnixStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_inner()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpStream {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpListener {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::UdpSocket {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-}
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
-    }
-}
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
-    }
-}
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::UdpSocket {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
-    }
-}
-
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::UdpSocket {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-
-/// A structure representing a Unix domain socket server.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread;
-/// use std::os::unix::net::{UnixStream, UnixListener};
-///
-/// fn handle_client(stream: UnixStream) {
-///     // ...
-/// }
-///
-/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-///
-/// // accept connections and process them, spawning a new thread for each one
-/// for stream in listener.incoming() {
-///     match stream {
-///         Ok(stream) => {
-///             /* connection succeeded */
-///             thread::spawn(|| handle_client(stream));
-///         }
-///         Err(err) => {
-///             /* connection failed */
-///             break;
-///         }
-///     }
-/// }
-/// ```
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct UnixListener(Socket);
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for UnixListener {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixListener");
-        builder.field("fd", self.0.as_inner());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixListener {
-    /// Creates a new `UnixListener` bound to the specified socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = match UnixListener::bind("/path/to/the/socket") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
-        fn inner(path: &Path) -> io::Result<UnixListener> {
-            unsafe {
-                let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
-                cvt(libc::listen(*inner.as_inner(), 128))?;
-
-                Ok(UnixListener(inner))
-            }
-        }
-        inner(path.as_ref())
-    }
-
-    /// Accepts a new incoming connection to this listener.
-    ///
-    /// This function will block the calling thread until a new Unix connection
-    /// is established. When established, the corresponding [`UnixStream`] and
-    /// the remote peer's address will be returned.
-    ///
-    /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// match listener.accept() {
-    ///     Ok((socket, addr)) => println!("Got a client: {:?}", addr),
-    ///     Err(e) => println!("accept function failed: {:?}", e),
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
-        let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
-        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
-        let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?;
-        let addr = SocketAddr::from_parts(storage, len)?;
-        Ok((UnixStream(sock), addr))
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixListener` is a reference to the same socket that this
-    /// object references. Both handles can be used to accept incoming
-    /// connections and options set on one listener will affect the other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// let listener_copy = listener.try_clone().expect("try_clone failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn try_clone(&self) -> io::Result<UnixListener> {
-        self.0.duplicate().map(UnixListener)
-    }
-
-    /// Returns the local socket address of this listener.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// let addr = listener.local_addr().expect("Couldn't get local address");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/tmp/sock").unwrap();
-    ///
-    /// if let Ok(Some(err)) = listener.take_error() {
-    ///     println!("Got error: {:?}", err);
-    /// }
-    /// ```
-    ///
-    /// # Platform specific
-    /// On Redox this always returns `None`.
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0.take_error()
-    }
-
-    /// Returns an iterator over incoming connections.
-    ///
-    /// The iterator will never return [`None`] and will also not yield the
-    /// peer's [`SocketAddr`] structure.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`SocketAddr`]: struct.SocketAddr.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::thread;
-    /// use std::os::unix::net::{UnixStream, UnixListener};
-    ///
-    /// fn handle_client(stream: UnixStream) {
-    ///     // ...
-    /// }
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// for stream in listener.incoming() {
-    ///     match stream {
-    ///         Ok(stream) => {
-    ///             thread::spawn(|| handle_client(stream));
-    ///         }
-    ///         Err(err) => {
-    ///             break;
-    ///         }
-    ///     }
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
-        Incoming { listener: self }
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl AsRawFd for UnixListener {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.0.as_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl FromRawFd for UnixListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
-        UnixListener(Socket::from_inner(fd))
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl IntoRawFd for UnixListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> IntoIterator for &'a UnixListener {
-    type Item = io::Result<UnixStream>;
-    type IntoIter = Incoming<'a>;
-
-    fn into_iter(self) -> Incoming<'a> {
-        self.incoming()
-    }
-}
-
-/// An iterator over incoming connections to a [`UnixListener`].
-///
-/// It will never return [`None`].
-///
-/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-/// [`UnixListener`]: struct.UnixListener.html
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread;
-/// use std::os::unix::net::{UnixStream, UnixListener};
-///
-/// fn handle_client(stream: UnixStream) {
-///     // ...
-/// }
-///
-/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-///
-/// for stream in listener.incoming() {
-///     match stream {
-///         Ok(stream) => {
-///             thread::spawn(|| handle_client(stream));
-///         }
-///         Err(err) => {
-///             break;
-///         }
-///     }
-/// }
-/// ```
-#[derive(Debug)]
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct Incoming<'a> {
-    listener: &'a UnixListener,
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> Iterator for Incoming<'a> {
-    type Item = io::Result<UnixStream>;
-
-    fn next(&mut self) -> Option<io::Result<UnixStream>> {
-        Some(self.listener.accept().map(|s| s.0))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::max_value(), None)
-    }
-}
-
-/// A Unix datagram socket.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::unix::net::UnixDatagram;
-///
-/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
-/// socket.send_to(b"hello world", "/path/to/other/socket").unwrap();
-/// let mut buf = [0; 100];
-/// let (count, address) = socket.recv_from(&mut buf).unwrap();
-/// println!("socket {:?} sent {:?}", address, &buf[..count]);
-/// ```
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct UnixDatagram(Socket);
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for UnixDatagram {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixDatagram");
-        builder.field("fd", self.0.as_inner());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        if let Ok(addr) = self.peer_addr() {
-            builder.field("peer", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixDatagram {
-    /// Creates a Unix datagram socket bound to the given path.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = match UnixDatagram::bind("/path/to/the/socket") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't bind: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
-        fn inner(path: &Path) -> io::Result<UnixDatagram> {
-            unsafe {
-                let socket = UnixDatagram::unbound()?;
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
-
-                Ok(socket)
-            }
-        }
-        inner(path.as_ref())
-    }
-
-    /// Creates a Unix Datagram socket which is not bound to any address.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = match UnixDatagram::unbound() {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't unbound: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn unbound() -> io::Result<UnixDatagram> {
-        let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
-        Ok(UnixDatagram(inner))
-    }
-
-    /// Creates an unnamed pair of connected sockets.
-    ///
-    /// Returns two `UnixDatagrams`s which are connected to each other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let (sock1, sock2) = match UnixDatagram::pair() {
-    ///     Ok((sock1, sock2)) => (sock1, sock2),
-    ///     Err(e) => {
-    ///         println!("Couldn't unbound: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
-        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
-        Ok((UnixDatagram(i1), UnixDatagram(i2)))
-    }
-
-    /// Connects the socket to the specified address.
-    ///
-    /// The [`send`] method may be used to send data to the specified address.
-    /// [`recv`] and [`recv_from`] will only receive data from that address.
-    ///
-    /// [`send`]: #method.send
-    /// [`recv`]: #method.recv
-    /// [`recv_from`]: #method.recv_from
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// match sock.connect("/path/to/the/socket") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
-        fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
-            unsafe {
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::connect(*d.0.as_inner(), &addr as *const _ as *const _, len))?;
-
-                Ok(())
-            }
-        }
-        inner(self, path.as_ref())
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixDatagram` is a reference to the same socket that this
-    /// object references. Both handles can be used to accept incoming
-    /// connections and options set on one side will affect the other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
-    ///
-    /// let sock_copy = sock.try_clone().expect("try_clone failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn try_clone(&self) -> io::Result<UnixDatagram> {
-        self.0.duplicate().map(UnixDatagram)
-    }
-
-    /// Returns the address of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
-    ///
-    /// let addr = sock.local_addr().expect("Couldn't get local address");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Returns the address of this socket's peer.
-    ///
-    /// The [`connect`] method will connect the socket to a peer.
-    ///
-    /// [`connect`]: #method.connect
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.connect("/path/to/the/socket").unwrap();
-    ///
-    /// let addr = sock.peer_addr().expect("Couldn't get peer address");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Receives data from the socket.
-    ///
-    /// On success, returns the number of bytes read and the address from
-    /// whence the data came.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// let mut buf = vec![0; 10];
-    /// match sock.recv_from(buf.as_mut_slice()) {
-    ///     Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender),
-    ///     Err(e) => println!("recv_from function failed: {:?}", e),
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        let mut count = 0;
-        let addr = SocketAddr::new(|addr, len| {
-            unsafe {
-                count = libc::recvfrom(*self.0.as_inner(),
-                                       buf.as_mut_ptr() as *mut _,
-                                       buf.len(),
-                                       0,
-                                       addr,
-                                       len);
-                if count > 0 {
-                    1
-                } else if count == 0 {
-                    0
-                } else {
-                    -1
-                }
-            }
-        })?;
-
-        Ok((count as usize, addr))
-    }
-
-    /// Receives data from the socket.
-    ///
-    /// On success, returns the number of bytes read.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
-    /// let mut buf = vec![0; 10];
-    /// sock.recv(buf.as_mut_slice()).expect("recv function failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    /// Sends data on the socket to the specified address.
-    ///
-    /// On success, returns the number of bytes written.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
-        fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
-            unsafe {
-                let (addr, len) = sockaddr_un(path)?;
-
-                let count = cvt(libc::sendto(*d.0.as_inner(),
-                                             buf.as_ptr() as *const _,
-                                             buf.len(),
-                                             MSG_NOSIGNAL,
-                                             &addr as *const _ as *const _,
-                                             len))?;
-                Ok(count as usize)
-            }
-        }
-        inner(self, buf, path.as_ref())
-    }
-
-    /// Sends data on the socket to the socket's peer.
-    ///
-    /// The peer address may be set by the `connect` method, and this method
-    /// will return an error if the socket has not already been connected.
-    ///
-    /// On success, returns the number of bytes written.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.connect("/some/sock").expect("Couldn't connect");
-    /// sock.send(b"omelette au fromage").expect("send_to function failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    /// Sets the read timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
-    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
-    /// is passed to this method.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
-    /// [`recv`]: #method.recv
-    /// [`recv_from`]: #method.recv_from
-    /// [`Duration`]: ../../../../std/time/struct.Duration.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixDatagram::unbound().unwrap();
-    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
-    /// let err = result.unwrap_err();
-    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
-    }
-
-    /// Sets the write timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
-    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`send`]: #method.send
-    /// [`send_to`]: #method.send_to
-    /// [`Duration`]: ../../../../std/time/struct.Duration.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.set_write_timeout(Some(Duration::new(1, 0)))
-    ///     .expect("set_write_timeout function failed");
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixDatagram::unbound().unwrap();
-    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
-    /// let err = result.unwrap_err();
-    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
-    }
-
-    /// Returns the read timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
-    /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0)));
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_RCVTIMEO)
-    }
-
-    /// Returns the write timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.set_write_timeout(Some(Duration::new(1, 0)))
-    ///     .expect("set_write_timeout function failed");
-    /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0)));
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_SNDTIMEO)
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.set_nonblocking(true).expect("set_nonblocking function failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// if let Ok(Some(err)) = sock.take_error() {
-    ///     println!("Got error: {:?}", err);
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0.take_error()
-    }
-
-    /// Shut down the read, write, or both halves of this connection.
-    ///
-    /// This function will cause all pending and future I/O calls on the
-    /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of [`Shutdown`]).
-    ///
-    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::net::Shutdown;
-    ///
-    /// let sock = UnixDatagram::unbound().unwrap();
-    /// sock.shutdown(Shutdown::Both).expect("shutdown function failed");
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        self.0.shutdown(how)
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl AsRawFd for UnixDatagram {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.0.as_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl FromRawFd for UnixDatagram {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
-        UnixDatagram(Socket::from_inner(fd))
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl IntoRawFd for UnixDatagram {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_inner()
-    }
-}
-
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod test {
-    use crate::thread;
-    use crate::io::{self, ErrorKind};
-    use crate::io::prelude::*;
-    use crate::time::Duration;
-    use crate::sys_common::io::test::tmpdir;
-
-    use super::*;
-
-    macro_rules! or_panic {
-        ($e:expr) => {
-            match $e {
-                Ok(e) => e,
-                Err(e) => panic!("{}", e),
-            }
-        }
-    }
-
-    #[test]
-    fn basic() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-        let msg1 = b"hello";
-        let msg2 = b"world!";
-
-        let listener = or_panic!(UnixListener::bind(&socket_path));
-        let thread = thread::spawn(move || {
-            let mut stream = or_panic!(listener.accept()).0;
-            let mut buf = [0; 5];
-            or_panic!(stream.read(&mut buf));
-            assert_eq!(&msg1[..], &buf[..]);
-            or_panic!(stream.write_all(msg2));
-        });
-
-        let mut stream = or_panic!(UnixStream::connect(&socket_path));
-        assert_eq!(Some(&*socket_path),
-                   stream.peer_addr().unwrap().as_pathname());
-        or_panic!(stream.write_all(msg1));
-        let mut buf = vec![];
-        or_panic!(stream.read_to_end(&mut buf));
-        assert_eq!(&msg2[..], &buf[..]);
-        drop(stream);
-
-        thread.join().unwrap();
-    }
-
-    #[test]
-    fn vectored() {
-        let (mut s1, mut s2) = or_panic!(UnixStream::pair());
-
-        let len = or_panic!(s1.write_vectored(
-            &[IoSlice::new(b"hello"), IoSlice::new(b" "), IoSlice::new(b"world!")],
-        ));
-        assert_eq!(len, 12);
-
-        let mut buf1 = [0; 6];
-        let mut buf2 = [0; 7];
-        let len = or_panic!(s2.read_vectored(
-            &mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],
-        ));
-        assert_eq!(len, 12);
-        assert_eq!(&buf1, b"hello ");
-        assert_eq!(&buf2, b"world!\0");
-    }
-
-    #[test]
-    fn pair() {
-        let msg1 = b"hello";
-        let msg2 = b"world!";
-
-        let (mut s1, mut s2) = or_panic!(UnixStream::pair());
-        let thread = thread::spawn(move || {
-            // s1 must be moved in or the test will hang!
-            let mut buf = [0; 5];
-            or_panic!(s1.read(&mut buf));
-            assert_eq!(&msg1[..], &buf[..]);
-            or_panic!(s1.write_all(msg2));
-        });
-
-        or_panic!(s2.write_all(msg1));
-        let mut buf = vec![];
-        or_panic!(s2.read_to_end(&mut buf));
-        assert_eq!(&msg2[..], &buf[..]);
-        drop(s2);
-
-        thread.join().unwrap();
-    }
-
-    #[test]
-    fn try_clone() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-        let msg1 = b"hello";
-        let msg2 = b"world";
-
-        let listener = or_panic!(UnixListener::bind(&socket_path));
-        let thread = thread::spawn(move || {
-            let mut stream = or_panic!(listener.accept()).0;
-            or_panic!(stream.write_all(msg1));
-            or_panic!(stream.write_all(msg2));
-        });
-
-        let mut stream = or_panic!(UnixStream::connect(&socket_path));
-        let mut stream2 = or_panic!(stream.try_clone());
-
-        let mut buf = [0; 5];
-        or_panic!(stream.read(&mut buf));
-        assert_eq!(&msg1[..], &buf[..]);
-        or_panic!(stream2.read(&mut buf));
-        assert_eq!(&msg2[..], &buf[..]);
-
-        thread.join().unwrap();
-    }
-
-    #[test]
-    fn iter() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-
-        let listener = or_panic!(UnixListener::bind(&socket_path));
-        let thread = thread::spawn(move || {
-            for stream in listener.incoming().take(2) {
-                let mut stream = or_panic!(stream);
-                let mut buf = [0];
-                or_panic!(stream.read(&mut buf));
-            }
-        });
-
-        for _ in 0..2 {
-            let mut stream = or_panic!(UnixStream::connect(&socket_path));
-            or_panic!(stream.write_all(&[0]));
-        }
-
-        thread.join().unwrap();
-    }
-
-    #[test]
-    fn long_path() {
-        let dir = tmpdir();
-        let socket_path = dir.path()
-                             .join("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa\
-                                    sasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf");
-        match UnixStream::connect(&socket_path) {
-            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
-            Err(e) => panic!("unexpected error {}", e),
-            Ok(_) => panic!("unexpected success"),
-        }
-
-        match UnixListener::bind(&socket_path) {
-            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
-            Err(e) => panic!("unexpected error {}", e),
-            Ok(_) => panic!("unexpected success"),
-        }
-
-        match UnixDatagram::bind(&socket_path) {
-            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
-            Err(e) => panic!("unexpected error {}", e),
-            Ok(_) => panic!("unexpected success"),
-        }
-    }
-
-    #[test]
-    fn timeouts() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-
-        let _listener = or_panic!(UnixListener::bind(&socket_path));
-
-        let stream = or_panic!(UnixStream::connect(&socket_path));
-        let dur = Duration::new(15410, 0);
-
-        assert_eq!(None, or_panic!(stream.read_timeout()));
-
-        or_panic!(stream.set_read_timeout(Some(dur)));
-        assert_eq!(Some(dur), or_panic!(stream.read_timeout()));
-
-        assert_eq!(None, or_panic!(stream.write_timeout()));
-
-        or_panic!(stream.set_write_timeout(Some(dur)));
-        assert_eq!(Some(dur), or_panic!(stream.write_timeout()));
-
-        or_panic!(stream.set_read_timeout(None));
-        assert_eq!(None, or_panic!(stream.read_timeout()));
-
-        or_panic!(stream.set_write_timeout(None));
-        assert_eq!(None, or_panic!(stream.write_timeout()));
-    }
-
-    #[test]
-    fn test_read_timeout() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-
-        let _listener = or_panic!(UnixListener::bind(&socket_path));
-
-        let mut stream = or_panic!(UnixStream::connect(&socket_path));
-        or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
-
-        let mut buf = [0; 10];
-        let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
-        assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
-                "unexpected_error: {:?}", kind);
-    }
-
-    #[test]
-    fn test_read_with_timeout() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-
-        let listener = or_panic!(UnixListener::bind(&socket_path));
-
-        let mut stream = or_panic!(UnixStream::connect(&socket_path));
-        or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
-
-        let mut other_end = or_panic!(listener.accept()).0;
-        or_panic!(other_end.write_all(b"hello world"));
-
-        let mut buf = [0; 11];
-        or_panic!(stream.read(&mut buf));
-        assert_eq!(b"hello world", &buf[..]);
-
-        let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
-        assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
-                "unexpected_error: {:?}", kind);
-    }
-
-    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
-    // when passed zero Durations
-    #[test]
-    fn test_unix_stream_timeout_zero_duration() {
-        let dir = tmpdir();
-        let socket_path = dir.path().join("sock");
-
-        let listener = or_panic!(UnixListener::bind(&socket_path));
-        let stream = or_panic!(UnixStream::connect(&socket_path));
-
-        let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-
-        let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-
-        drop(listener);
-    }
-
-    #[test]
-    fn test_unix_datagram() {
-        let dir = tmpdir();
-        let path1 = dir.path().join("sock1");
-        let path2 = dir.path().join("sock2");
-
-        let sock1 = or_panic!(UnixDatagram::bind(&path1));
-        let sock2 = or_panic!(UnixDatagram::bind(&path2));
-
-        let msg = b"hello world";
-        or_panic!(sock1.send_to(msg, &path2));
-        let mut buf = [0; 11];
-        or_panic!(sock2.recv_from(&mut buf));
-        assert_eq!(msg, &buf[..]);
-    }
-
-    #[test]
-    fn test_unnamed_unix_datagram() {
-        let dir = tmpdir();
-        let path1 = dir.path().join("sock1");
-
-        let sock1 = or_panic!(UnixDatagram::bind(&path1));
-        let sock2 = or_panic!(UnixDatagram::unbound());
-
-        let msg = b"hello world";
-        or_panic!(sock2.send_to(msg, &path1));
-        let mut buf = [0; 11];
-        let (usize, addr) = or_panic!(sock1.recv_from(&mut buf));
-        assert_eq!(usize, 11);
-        assert!(addr.is_unnamed());
-        assert_eq!(msg, &buf[..]);
-    }
-
-    #[test]
-    fn test_connect_unix_datagram() {
-        let dir = tmpdir();
-        let path1 = dir.path().join("sock1");
-        let path2 = dir.path().join("sock2");
-
-        let bsock1 = or_panic!(UnixDatagram::bind(&path1));
-        let bsock2 = or_panic!(UnixDatagram::bind(&path2));
-        let sock = or_panic!(UnixDatagram::unbound());
-        or_panic!(sock.connect(&path1));
-
-        // Check send()
-        let msg = b"hello there";
-        or_panic!(sock.send(msg));
-        let mut buf = [0; 11];
-        let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf));
-        assert_eq!(usize, 11);
-        assert!(addr.is_unnamed());
-        assert_eq!(msg, &buf[..]);
-
-        // Changing default socket works too
-        or_panic!(sock.connect(&path2));
-        or_panic!(sock.send(msg));
-        or_panic!(bsock2.recv_from(&mut buf));
-    }
-
-    #[test]
-    fn test_unix_datagram_recv() {
-        let dir = tmpdir();
-        let path1 = dir.path().join("sock1");
-
-        let sock1 = or_panic!(UnixDatagram::bind(&path1));
-        let sock2 = or_panic!(UnixDatagram::unbound());
-        or_panic!(sock2.connect(&path1));
-
-        let msg = b"hello world";
-        or_panic!(sock2.send(msg));
-        let mut buf = [0; 11];
-        let size = or_panic!(sock1.recv(&mut buf));
-        assert_eq!(size, 11);
-        assert_eq!(msg, &buf[..]);
-    }
-
-    #[test]
-    fn datagram_pair() {
-        let msg1 = b"hello";
-        let msg2 = b"world!";
-
-        let (s1, s2) = or_panic!(UnixDatagram::pair());
-        let thread = thread::spawn(move || {
-            // s1 must be moved in or the test will hang!
-            let mut buf = [0; 5];
-            or_panic!(s1.recv(&mut buf));
-            assert_eq!(&msg1[..], &buf[..]);
-            or_panic!(s1.send(msg2));
-        });
-
-        or_panic!(s2.send(msg1));
-        let mut buf = [0; 6];
-        or_panic!(s2.recv(&mut buf));
-        assert_eq!(&msg2[..], &buf[..]);
-        drop(s2);
-
-        thread.join().unwrap();
-    }
-
-    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
-    // when passed zero Durations
-    #[test]
-    fn test_unix_datagram_timeout_zero_duration() {
-        let dir = tmpdir();
-        let path = dir.path().join("sock");
-
-        let datagram = or_panic!(UnixDatagram::bind(&path));
-
-        let result = datagram.set_write_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-
-        let result = datagram.set_read_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-    }
-
-    #[test]
-    fn abstract_namespace_not_allowed() {
-        assert!(UnixStream::connect("\0asdf").is_err());
-    }
-}
index 17ea4767520646ae18be10ca27e26eb183302583..941df5ea57087bd1e38e6af240cd0fa0e6ca2f2d 100644 (file)
@@ -487,7 +487,6 @@ pub(in crate::foo) struct Bar {
                                // `test_2018_feature` is
                                // included in the Rust 2018 edition
 ```
-
 "##,
 
 E0725: r##"
@@ -505,6 +504,20 @@ pub(in crate::foo) struct Bar {
 features in the `-Z allow_features` flag.
 "##,
 
+E0743: r##"
+C-variadic has been used on a non-foreign function.
+
+Erroneous code example:
+
+```compile_fail,E0743
+fn foo2(x: u8, ...) {} // error!
+```
+
+Only foreign functions can use C-variadic (`...`). It is used to give an
+undefined number of parameters to a given function (like `printf` in C). The
+equivalent in Rust would be to use macros directly.
+"##,
+
 ;
 
     E0539, // incorrect meta item
index d309a17298baa3471f42d7d954185149be348b22..a1cf2d421084ef60867468e68ce798f013aa31ab 100644 (file)
@@ -251,6 +251,8 @@ macro_rules! declare_features {
     (accepted, non_exhaustive, "1.40.0", Some(44109), None),
     /// Allows calling constructor functions in `const fn`.
     (accepted, const_constructor, "1.40.0", Some(61456), None),
+    /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
+    (accepted, cfg_doctest, "1.40.0", Some(62210), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
index 22638a1376c72cab90b979f054742e37074eb04a..736a363bbfc0a020d94eae30a02377f82dc2f9d0 100644 (file)
@@ -506,9 +506,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows `async || body` closures.
     (active, async_closure, "1.37.0", Some(62290), None),
 
-    /// Allows the use of `#[cfg(doctest)]`; set when rustdoc is collecting doctests.
-    (active, cfg_doctest, "1.37.0", Some(62210), None),
-
     /// Allows `[x; N]` where `x` is a constant (RFC 2203).
     (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None),
 
index efe84238795a5739ab84251cf58b6ec4557f91c0..eb811c3e0ff9b590ba03e9dabf0d1f8729ee437f 100644 (file)
@@ -31,7 +31,6 @@ macro_rules! cfg_fn {
     (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)),
-    (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)),
 ];
 
 #[derive(Debug)]
index 97b99b9392f3f0ab3dfd47815dd9f76228f63e88..13a24ca046d51bb64248e43e3d4f0aac193d89d7 100644 (file)
@@ -3,8 +3,12 @@
 use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
 use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 
-use crate::ast::{self, NodeId, PatKind, VariantData};
+use crate::ast::{
+    self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
+    PatKind, RangeEnd, VariantData,
+};
 use crate::attr::{self, check_builtin_attribute};
+use crate::source_map::Spanned;
 use crate::edition::{ALL_EDITIONS, Edition};
 use crate::visit::{self, FnKind, Visitor};
 use crate::parse::token;
@@ -153,6 +157,9 @@ fn leveled_feature_err<'a, S: Into<MultiSpan>>(
 
 }
 
+const EXPLAIN_BOX_SYNTAX: &str =
+    "box expression syntax is experimental; you can call `Box::new` instead";
+
 pub const EXPLAIN_STMT_ATTR_SYNTAX: &str =
     "attributes on expressions are experimental";
 
@@ -439,6 +446,20 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                    "auto traits are experimental and possibly buggy");
             }
 
+            ast::ItemKind::TraitAlias(..) => {
+                gate_feature_post!(
+                    &self,
+                    trait_alias,
+                    i.span,
+                    "trait aliases are experimental"
+                );
+            }
+
+            ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
+                let msg = "`macro` is experimental";
+                gate_feature_post!(&self, decl_macro, i.span, msg);
+            }
+
             ast::ItemKind::OpaqueTy(..) => {
                 gate_feature_post!(
                     &self,
@@ -502,6 +523,37 @@ fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
         }
     }
 
+    fn visit_expr(&mut self, e: &'a ast::Expr) {
+        match e.kind {
+            ast::ExprKind::Box(_) => {
+                gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
+            }
+            ast::ExprKind::Type(..) => {
+                // To avoid noise about type ascription in common syntax errors, only emit if it
+                // is the *only* error.
+                if self.parse_sess.span_diagnostic.err_count() == 0 {
+                    gate_feature_post!(&self, type_ascription, e.span,
+                                       "type ascription is experimental");
+                }
+            }
+            ast::ExprKind::TryBlock(_) => {
+                gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
+            }
+            ast::ExprKind::Block(_, opt_label) => {
+                if let Some(label) = opt_label {
+                    gate_feature_post!(&self, label_break_value, label.ident.span,
+                                    "labels on blocks are unstable");
+                }
+            }
+            _ => {}
+        }
+        visit::walk_expr(self, e)
+    }
+
+    fn visit_arm(&mut self, arm: &'a ast::Arm) {
+        visit::walk_arm(self, arm)
+    }
+
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match &pattern.kind {
             PatKind::Slice(pats) => {
@@ -521,12 +573,25 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
                     }
                 }
             }
+            PatKind::Box(..) => {
+                gate_feature_post!(&self, box_patterns,
+                                  pattern.span,
+                                  "box pattern syntax is experimental");
+            }
+            PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
+                gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
+                                   "exclusive range pattern syntax is experimental");
+            }
             _ => {}
         }
         visit::walk_pat(self, pattern)
     }
 
-    fn visit_fn(&mut self, fn_kind: FnKind<'a>, fn_decl: &'a ast::FnDecl, span: Span, _: NodeId) {
+    fn visit_fn(&mut self,
+                fn_kind: FnKind<'a>,
+                fn_decl: &'a ast::FnDecl,
+                span: Span,
+                _node_id: NodeId) {
         if let Some(header) = fn_kind.header() {
             // Stability of const fn methods are covered in
             // `visit_trait_item` and `visit_impl_item` below; this is
@@ -541,6 +606,26 @@ fn visit_fn(&mut self, fn_kind: FnKind<'a>, fn_decl: &'a ast::FnDecl, span: Span
         visit::walk_fn(self, fn_kind, fn_decl, span)
     }
 
+    fn visit_generic_param(&mut self, param: &'a GenericParam) {
+        match param.kind {
+            GenericParamKind::Const { .. } =>
+                gate_feature_post!(&self, const_generics, param.ident.span,
+                    "const generics are unstable"),
+            _ => {}
+        }
+        visit::walk_generic_param(self, param)
+    }
+
+    fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
+        match constraint.kind {
+            AssocTyConstraintKind::Bound { .. } =>
+                gate_feature_post!(&self, associated_type_bounds, constraint.span,
+                    "associated type bounds are unstable"),
+            _ => {}
+        }
+        visit::walk_assoc_ty_constraint(self, constraint)
+    }
+
     fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
         match ti.kind {
             ast::TraitItemKind::Method(ref sig, ref block) => {
@@ -598,6 +683,14 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
         }
         visit::walk_impl_item(self, ii)
     }
+
+    fn visit_vis(&mut self, vis: &'a ast::Visibility) {
+        if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
+            gate_feature_post!(&self, crate_visibility_modifier, vis.span,
+                               "`crate` visibility modifier is experimental");
+        }
+        visit::walk_vis(self, vis)
+    }
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
@@ -783,6 +876,21 @@ macro_rules! gate_all {
     gate_all!(yields, generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
+
+    // All uses of `gate_all!` below this point were added in #65742,
+    // and subsequently disabled (with the non-early gating readded).
+    macro_rules! gate_all {
+        ($gate:ident, $msg:literal) => {
+            // FIXME(eddyb) do something more useful than always
+            // disabling these uses of early feature-gatings.
+            if false {
+                for span in &*parse_sess.gated_spans.$gate.borrow() {
+                    gate_feature!(&visitor, $gate, *span, $msg);
+                }
+            }
+        }
+    }
+
     gate_all!(trait_alias, "trait aliases are experimental");
     gate_all!(associated_type_bounds, "associated type bounds are unstable");
     gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental");
index 86c94b680b2c9da4a0b61fb2fcadc3d2ecee9976..e8f718a24835c085a824e5960b5cb18f6499f860 100644 (file)
@@ -197,8 +197,11 @@ pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery:
                 self.eat(&token::DotDotDot);
                 TyKind::CVarArgs
             } else {
-                return Err(self.fatal(
-                    "only foreign functions are allowed to be C-variadic"
+                return Err(struct_span_fatal!(
+                    self.sess.span_diagnostic,
+                    self.token.span,
+                    E0743,
+                    "only foreign functions are allowed to be C-variadic",
                 ));
             }
         } else {
index 8ba161f55c1fff6b759185db0976df8a07c67490..57131ffe18cb3a36238f2e84962d8e089c422f97 100644 (file)
         issue_5723_bootstrap,
         issue_tracker_base_url,
         item,
+        item_context: "ItemContext",
         item_like_imports,
         iter,
         Iterator,
index 61651a927c5f7aea2222b461d33d64f8610ccc25..6b0c8a8af32b456a9d6934fbedcd17acacd1ccf4 100644 (file)
@@ -54,6 +54,12 @@ fn num_cpus() -> usize {
         1
     }
 
+    #[cfg(target_os = "hermit")]
+    fn num_cpus() -> usize {
+        // FIXME: Implement num_cpus on HermitCore
+        1
+    }
+
     #[cfg(any(
         all(target_arch = "wasm32", not(target_os = "emscripten")),
         all(target_vendor = "fortanix", target_env = "sgx")
index 6e4954778e60523c90cd4011cbad0be3951b9bb4..4955e1fc88862c838992f88c86e6eabf81665da3 100644 (file)
@@ -2,7 +2,7 @@
 //! if stdout is a tty.
 
 #[cfg(any(
-    target_os = "cloudabi",
+    target_os = "cloudabi", target_os = "hermit",
     all(target_arch = "wasm32", not(target_os = "emscripten")),
     all(target_vendor = "fortanix", target_env = "sgx")
 ))]
index 8c1e9f1722a267a990625330973473f9bb61a153..341a2e18db5fcfd50f449851647a41f74512c12f 100644 (file)
@@ -441,9 +441,9 @@ pub fn run_test(
 ) {
     let TestDescAndFn { desc, testfn } = test;
 
-    // FIXME: Re-enable emscripten once it can catch panics again
+    // Emscripten can catch panics but other wasm targets cannot
     let ignore_because_no_process_support = desc.should_panic != ShouldPanic::No
-        && (cfg!(target_arch = "wasm32") || cfg!(target_os = "emscripten"));
+        && cfg!(target_arch = "wasm32") && !cfg!(target_os = "emscripten");
 
     if force_ignore || desc.ignore || ignore_because_no_process_support {
         let message = CompletedTest::new(desc, TrIgnored, None, Vec::new());
index f24d957d67b7588ed323aebdc9ce123a91f6966f..b8db16f8f2ac8dcfac2afa518dda66457ca3e75e 100644 (file)
@@ -56,12 +56,18 @@ mod llvm_libunwind {
     pub fn compile() {
         let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
         let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
+        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
         let cfg = &mut cc::Build::new();
 
         cfg.cpp(true);
         cfg.cpp_set_stdlib(None);
         cfg.warnings(false);
 
+        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
+        if target_endian_little {
+            cfg.define("__LITTLE_ENDIAN__", Some("1"));
+        }
+
         if target_env == "msvc" {
             // Don't pull in extra libraries on MSVC
             cfg.flag("/Zl");
index 7c9eaa51fd94e8d5a84621a224eccfa9e8711abb..0b39503c0d03453b08da3bf2a5f0420b6433747b 100644 (file)
@@ -244,3 +244,30 @@ pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Rea
     }
 }
 } // cfg_if!
+
+cfg_if::cfg_if! {
+if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
+    // We declare these as opaque types. This is fine since you just need to
+    // pass them to _GCC_specific_handler and forget about them.
+    pub enum EXCEPTION_RECORD {}
+    pub type LPVOID = *mut c_void;
+    pub enum CONTEXT {}
+    pub enum DISPATCHER_CONTEXT {}
+    pub type EXCEPTION_DISPOSITION = c_int;
+    type PersonalityFn = unsafe extern "C" fn(version: c_int,
+                                              actions: _Unwind_Action,
+                                              exception_class: _Unwind_Exception_Class,
+                                              exception_object: *mut _Unwind_Exception,
+                                              context: *mut _Unwind_Context)
+                                              -> _Unwind_Reason_Code;
+
+    extern "C" {
+        pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
+                                establisherFrame: LPVOID,
+                                contextRecord: *mut CONTEXT,
+                                dispatcherContext: *mut DISPATCHER_CONTEXT,
+                                personality: PersonalityFn)
+                                -> EXCEPTION_DISPOSITION;
+    }
+}
+} // cfg_if!
index 7fa61d15f77c4af42e3ef9eeb331f3916e9295ab..971f4e3e12ea81eb2cb411884a9b3b605b9b3bcf 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C no-prepopulate-passes
 // ignore-tidy-linelength
 
index 49e40d5f243f16c80e9e5990037108c9105f3dbe..959929fbafbf10424f937f4b3b0c2eb68eb8832a 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
index 376447e5b5db0cd61be2297c4e312266a34baba1..4a5b7c05231dcb05f428f70ce3a91b46b4cc8c4a 100644 (file)
@@ -8,7 +8,7 @@
 
 // CHECK-LABEL: define i32 @nothing
 // CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
-// NO-OPT: ret i32 %1
+// NO-OPT: ret i32 %_1.0
 // SIZE-OPT: ret i32 4
 // SPEEC-OPT: ret i32 4
 #[no_mangle]
@@ -18,7 +18,7 @@ pub fn nothing() -> i32 {
 
 // CHECK-LABEL: define i32 @size
 // CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]]
-// NO-OPT: ret i32 %1
+// NO-OPT: ret i32 %_1.0
 // SIZE-OPT: ret i32 6
 // SPEED-OPT: ret i32 6
 #[optimize(size)]
@@ -31,7 +31,7 @@ pub fn size() -> i32 {
 // NO-OPT-SAME: [[NOTHING_ATTRS]]
 // SPEED-OPT-SAME: [[NOTHING_ATTRS]]
 // SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]]
-// NO-OPT: ret i32 %1
+// NO-OPT: ret i32 %_1.0
 // SIZE-OPT: ret i32 8
 // SPEED-OPT: ret i32 8
 #[optimize(speed)]
index c82ae476b1b2c2a9cc3c10c26177895201e44d6f..9f07488a9a8a6a3be34c9fc8e0f8706d98a7d48c 100644 (file)
@@ -1,5 +1,5 @@
 // ignore-msvc
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 // compile-flags: -O -C no-prepopulate-passes
 
index 237d15a5c68cf4239f1e990aebcde51523a637bc..267c995e0704ff453534de86a953c3ba67aa0aee 100644 (file)
     fn simd_saturating_sub<T>(x: T, y: T) -> T;
 }
 
+// NOTE(eddyb) `%{{x|_3}}` is used because on some targets (e.g. WASM)
+// SIMD vectors are passed directly, resulting in `%x` being a vector,
+// while on others they're passed indirectly, resulting in `%x` being
+// a pointer to a vector, and `%_3` a vector loaded from that pointer.
+// This is controlled by the target spec option `simd_types_indirect`.
+// The same applies to `%{{y|_4}}` as well.
+
 // CHECK-LABEL: @sadd_i8x2
 #[no_mangle]
 pub unsafe fn sadd_i8x2(x: i8x2, y: i8x2) -> i8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x4
 #[no_mangle]
 pub unsafe fn sadd_i8x4(x: i8x4, y: i8x4) -> i8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x8
 #[no_mangle]
 pub unsafe fn sadd_i8x8(x: i8x8, y: i8x8) -> i8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x16
 #[no_mangle]
 pub unsafe fn sadd_i8x16(x: i8x16, y: i8x16) -> i8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x32
 #[no_mangle]
 pub unsafe fn sadd_i8x32(x: i8x32, y: i8x32) -> i8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x64
 #[no_mangle]
 pub unsafe fn sadd_i8x64(x: i8x64, y: i8x64) -> i8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x2
 #[no_mangle]
 pub unsafe fn sadd_i16x2(x: i16x2, y: i16x2) -> i16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x4
 #[no_mangle]
 pub unsafe fn sadd_i16x4(x: i16x4, y: i16x4) -> i16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x8
 #[no_mangle]
 pub unsafe fn sadd_i16x8(x: i16x8, y: i16x8) -> i16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x16
 #[no_mangle]
 pub unsafe fn sadd_i16x16(x: i16x16, y: i16x16) -> i16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x32
 #[no_mangle]
 pub unsafe fn sadd_i16x32(x: i16x32, y: i16x32) -> i16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x2
 #[no_mangle]
 pub unsafe fn sadd_i32x2(x: i32x2, y: i32x2) -> i32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x4
 #[no_mangle]
 pub unsafe fn sadd_i32x4(x: i32x4, y: i32x4) -> i32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x8
 #[no_mangle]
 pub unsafe fn sadd_i32x8(x: i32x8, y: i32x8) -> i32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x16
 #[no_mangle]
 pub unsafe fn sadd_i32x16(x: i32x16, y: i32x16) -> i32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i64x2
 #[no_mangle]
 pub unsafe fn sadd_i64x2(x: i64x2, y: i64x2) -> i64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i64x4
 #[no_mangle]
 pub unsafe fn sadd_i64x4(x: i64x4, y: i64x4) -> i64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i64x8
 #[no_mangle]
 pub unsafe fn sadd_i64x8(x: i64x8, y: i64x8) -> i64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i128x2
 #[no_mangle]
 pub unsafe fn sadd_i128x2(x: i128x2, y: i128x2) -> i128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i128x4
 #[no_mangle]
 pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
@@ -261,140 +268,140 @@ pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 {
 // CHECK-LABEL: @uadd_u8x2
 #[no_mangle]
 pub unsafe fn uadd_u8x2(x: u8x2, y: u8x2) -> u8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x4
 #[no_mangle]
 pub unsafe fn uadd_u8x4(x: u8x4, y: u8x4) -> u8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x8
 #[no_mangle]
 pub unsafe fn uadd_u8x8(x: u8x8, y: u8x8) -> u8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x16
 #[no_mangle]
 pub unsafe fn uadd_u8x16(x: u8x16, y: u8x16) -> u8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x32
 #[no_mangle]
 pub unsafe fn uadd_u8x32(x: u8x32, y: u8x32) -> u8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x64
 #[no_mangle]
 pub unsafe fn uadd_u8x64(x: u8x64, y: u8x64) -> u8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x2
 #[no_mangle]
 pub unsafe fn uadd_u16x2(x: u16x2, y: u16x2) -> u16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x4
 #[no_mangle]
 pub unsafe fn uadd_u16x4(x: u16x4, y: u16x4) -> u16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x8
 #[no_mangle]
 pub unsafe fn uadd_u16x8(x: u16x8, y: u16x8) -> u16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x16
 #[no_mangle]
 pub unsafe fn uadd_u16x16(x: u16x16, y: u16x16) -> u16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x32
 #[no_mangle]
 pub unsafe fn uadd_u16x32(x: u16x32, y: u16x32) -> u16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x2
 #[no_mangle]
 pub unsafe fn uadd_u32x2(x: u32x2, y: u32x2) -> u32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x4
 #[no_mangle]
 pub unsafe fn uadd_u32x4(x: u32x4, y: u32x4) -> u32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x8
 #[no_mangle]
 pub unsafe fn uadd_u32x8(x: u32x8, y: u32x8) -> u32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x16
 #[no_mangle]
 pub unsafe fn uadd_u32x16(x: u32x16, y: u32x16) -> u32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u64x2
 #[no_mangle]
 pub unsafe fn uadd_u64x2(x: u64x2, y: u64x2) -> u64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u64x4
 #[no_mangle]
 pub unsafe fn uadd_u64x4(x: u64x4, y: u64x4) -> u64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u64x8
 #[no_mangle]
 pub unsafe fn uadd_u64x8(x: u64x8, y: u64x8) -> u64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u128x2
 #[no_mangle]
 pub unsafe fn uadd_u128x2(x: u128x2, y: u128x2) -> u128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u128x4
 #[no_mangle]
 pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
     simd_saturating_add(x, y)
 }
 
@@ -405,140 +412,140 @@ pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 {
 // CHECK-LABEL: @ssub_i8x2
 #[no_mangle]
 pub unsafe fn ssub_i8x2(x: i8x2, y: i8x2) -> i8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x4
 #[no_mangle]
 pub unsafe fn ssub_i8x4(x: i8x4, y: i8x4) -> i8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x8
 #[no_mangle]
 pub unsafe fn ssub_i8x8(x: i8x8, y: i8x8) -> i8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x16
 #[no_mangle]
 pub unsafe fn ssub_i8x16(x: i8x16, y: i8x16) -> i8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x32
 #[no_mangle]
 pub unsafe fn ssub_i8x32(x: i8x32, y: i8x32) -> i8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x64
 #[no_mangle]
 pub unsafe fn ssub_i8x64(x: i8x64, y: i8x64) -> i8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x2
 #[no_mangle]
 pub unsafe fn ssub_i16x2(x: i16x2, y: i16x2) -> i16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x4
 #[no_mangle]
 pub unsafe fn ssub_i16x4(x: i16x4, y: i16x4) -> i16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x8
 #[no_mangle]
 pub unsafe fn ssub_i16x8(x: i16x8, y: i16x8) -> i16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x16
 #[no_mangle]
 pub unsafe fn ssub_i16x16(x: i16x16, y: i16x16) -> i16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x32
 #[no_mangle]
 pub unsafe fn ssub_i16x32(x: i16x32, y: i16x32) -> i16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x2
 #[no_mangle]
 pub unsafe fn ssub_i32x2(x: i32x2, y: i32x2) -> i32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x4
 #[no_mangle]
 pub unsafe fn ssub_i32x4(x: i32x4, y: i32x4) -> i32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x8
 #[no_mangle]
 pub unsafe fn ssub_i32x8(x: i32x8, y: i32x8) -> i32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x16
 #[no_mangle]
 pub unsafe fn ssub_i32x16(x: i32x16, y: i32x16) -> i32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i64x2
 #[no_mangle]
 pub unsafe fn ssub_i64x2(x: i64x2, y: i64x2) -> i64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i64x4
 #[no_mangle]
 pub unsafe fn ssub_i64x4(x: i64x4, y: i64x4) -> i64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i64x8
 #[no_mangle]
 pub unsafe fn ssub_i64x8(x: i64x8, y: i64x8) -> i64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i128x2
 #[no_mangle]
 pub unsafe fn ssub_i128x2(x: i128x2, y: i128x2) -> i128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i128x4
 #[no_mangle]
 pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
@@ -547,139 +554,139 @@ pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 {
 // CHECK-LABEL: @usub_u8x2
 #[no_mangle]
 pub unsafe fn usub_u8x2(x: u8x2, y: u8x2) -> u8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x4
 #[no_mangle]
 pub unsafe fn usub_u8x4(x: u8x4, y: u8x4) -> u8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x8
 #[no_mangle]
 pub unsafe fn usub_u8x8(x: u8x8, y: u8x8) -> u8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x16
 #[no_mangle]
 pub unsafe fn usub_u8x16(x: u8x16, y: u8x16) -> u8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x32
 #[no_mangle]
 pub unsafe fn usub_u8x32(x: u8x32, y: u8x32) -> u8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x64
 #[no_mangle]
 pub unsafe fn usub_u8x64(x: u8x64, y: u8x64) -> u8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x2
 #[no_mangle]
 pub unsafe fn usub_u16x2(x: u16x2, y: u16x2) -> u16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x4
 #[no_mangle]
 pub unsafe fn usub_u16x4(x: u16x4, y: u16x4) -> u16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x8
 #[no_mangle]
 pub unsafe fn usub_u16x8(x: u16x8, y: u16x8) -> u16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x16
 #[no_mangle]
 pub unsafe fn usub_u16x16(x: u16x16, y: u16x16) -> u16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x32
 #[no_mangle]
 pub unsafe fn usub_u16x32(x: u16x32, y: u16x32) -> u16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x2
 #[no_mangle]
 pub unsafe fn usub_u32x2(x: u32x2, y: u32x2) -> u32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x4
 #[no_mangle]
 pub unsafe fn usub_u32x4(x: u32x4, y: u32x4) -> u32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x8
 #[no_mangle]
 pub unsafe fn usub_u32x8(x: u32x8, y: u32x8) -> u32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x16
 #[no_mangle]
 pub unsafe fn usub_u32x16(x: u32x16, y: u32x16) -> u32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u64x2
 #[no_mangle]
 pub unsafe fn usub_u64x2(x: u64x2, y: u64x2) -> u64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u64x4
 #[no_mangle]
 pub unsafe fn usub_u64x4(x: u64x4, y: u64x4) -> u64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u64x8
 #[no_mangle]
 pub unsafe fn usub_u64x8(x: u64x8, y: u64x8) -> u64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u128x2
 #[no_mangle]
 pub unsafe fn usub_u128x2(x: u128x2, y: u128x2) -> u128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u128x4
 #[no_mangle]
 pub unsafe fn usub_u128x4(x: u128x4, y: u128x4) -> u128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
     simd_saturating_sub(x, y)
 }
index 543664014868c5ad07606c2053bf3f6f0a866701..87c8b0d87d8bbc575425b69fe327a68d3f0bf2c7 100644 (file)
@@ -26,10 +26,16 @@ pub struct i8x16(
     fn simd_bitmask<T, U>(x: T) -> U;
 }
 
+// NOTE(eddyb) `%{{x|_2}}` is used because on some targets (e.g. WASM)
+// SIMD vectors are passed directly, resulting in `%x` being a vector,
+// while on others they're passed indirectly, resulting in `%x` being
+// a pointer to a vector, and `%_2` a vector loaded from that pointer.
+// This is controlled by the target spec option `simd_types_indirect`.
+
 // CHECK-LABEL: @bitmask_int
 #[no_mangle]
 pub unsafe fn bitmask_int(x: i32x2) -> u8 {
-    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9a-z]+}}, <i32 31, i32 31>
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|_2}}, <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
@@ -39,7 +45,7 @@ pub unsafe fn bitmask_int(x: i32x2) -> u8 {
 // CHECK-LABEL: @bitmask_uint
 #[no_mangle]
 pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
-    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9a-z]+}}, <i32 31, i32 31>
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|_2}}, <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
@@ -49,7 +55,7 @@ pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
 // CHECK-LABEL: @bitmask_int16
 #[no_mangle]
 pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
-    // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{[0-9a-z]+}}, <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: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|_2}}, <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
index d924a3b75dde3809d4daf732b2895fdbfa6fb5dd..e5a2936b92497aa6cf26a8f126079f12c40e766f 100644 (file)
@@ -1,5 +1,5 @@
 // compile-flags: -C opt-level=0
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![crate_type = "lib"]
 #![feature(unwind_attributes)]
index d88a498775642f8d8697f1a6dccf25f77331ec37..8403e1e9da9fa381f0b86be85e8b8647f765a8ae 100644 (file)
@@ -1,5 +1,5 @@
 // compile-flags: -C no-prepopulate-passes
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![crate_type = "lib"]
 #![feature(unwind_attributes)]
index 2bcb06d6eb8b7c976ac80659c75912b29cdda788..8c35f6ca0000dd8f6f57809bfd0f5993544723ab 100644 (file)
@@ -1,7 +1,7 @@
 // Test that we detect changes to the `dep_kind` query. If the change is not
 // detected then -Zincremental-verify-ich will trigger an assertion.
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph -Cpanic=unwind
 // build-pass (FIXME(62277): could be check-pass?)
index 4b66c07b0934b48560f6276bfbaae6f4de180bca..8dc6b73edf6d473ecd804cdd314597fbdb86dcd9 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(box_syntax)]
 
index b595c100039d6bed04a7c5ae388a61668ad8e0b7..109304d6d22ccdd4cb9368c12bbea673702e2f76 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 // Test that we generate StorageDead on unwind paths for generators.
 //
index 67a6d1d263bf53f543fea3d30f186621d43364ef..fdd4e226c5a765a5f6f5d392849b9642bf8bfab3 100644 (file)
@@ -12,12 +12,9 @@ fn main() {}
 //     node [fontname="monospace"];
 //     edge [fontname="monospace"];
 //     label=<fn main() -&gt; ()<br align="left"/>>;
-//     bb0 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = ()<br/></td></tr><tr><td align="left">goto</td></tr></table>
-// >];
-//     bb1 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>
-// >];
-//     bb2 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left">return</td></tr></table>
-// >];
-//     bb0 -> bb2 [label=""];
+//     bb0__0_12 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = ()<br/></td></tr><tr><td align="left">goto</td></tr></table>>];
+//     bb1__0_12 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>>];
+//     bb2__0_12 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left">return</td></tr></table>>];
+//     bb0__0_12 -> bb2__0_12 [label=""];
 // }
 // END rustc.main.mir_map.0.dot
index 8824496fdb07cc4a68530ae82a862828d20c52a6..e73390f52b5d552fc3287e923a0f52ac9a117c52 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 // check that we don't emit multiple drop flags when they are not needed.
 
index 93250fd48d82d00935eb568c10135625baa5b78c..a3b517e9bca87bfa0cf295af84a7496c3ad5fe65 100644 (file)
@@ -1,7 +1,7 @@
 // check that we don't forget to drop the Box if we early return before
 // initializing it
 // ignore-tidy-linelength
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(box_syntax)]
 
index 370cd593b02bb75aad365419f82e84c6bfa35965..782bc31186ca5fb8eb8a4931bc077d8579e4d351 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 // Test that after the call to `std::mem::drop` we do not generate a
 // MIR drop of the argument. (We used to have a `DROP(_2)` in the code
index eaa1fbd69ecc6beec8277fa021d44118a4bc577a..da73cc96348f059e4c15e29ce839204b2b824ed4 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 fn main() {
     let mut x = Packed(Aligned(Droppy(0)));
index 71beaa736639ddfa8151b6b953a779f3dfc2d129..965897ad541e78f362328754b06da3d47e0c6c4d 100644 (file)
@@ -1,6 +1,6 @@
 // Test that the fake borrows for matches are removed after borrow checking.
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 fn match_guard(x: Option<&&i32>, c: bool) -> i32 {
     match x {
index a0bdfb3ab8ba94c9fb5fae19aafb2fe6cf476c0c..db36a1fab5f2104f48e2dc3a3dedea1532753d86 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // ignore-tidy-linelength
 // compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats
 
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-exceptions/Makefile
new file mode 100644 (file)
index 0000000..7eba52f
--- /dev/null
@@ -0,0 +1,10 @@
+-include ../tools.mk
+
+all: foo
+       $(call RUN,foo)
+
+foo: foo.rs $(call NATIVE_STATICLIB,foo)
+       $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS)
+
+$(TMPDIR)/libfoo.o: foo.cpp
+       $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
new file mode 100644 (file)
index 0000000..b0fd65f
--- /dev/null
@@ -0,0 +1,60 @@
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+
+void println(const char* s) {
+    puts(s);
+    fflush(stdout);
+}
+
+struct exception {};
+struct rust_panic {};
+
+struct drop_check {
+    bool* ok;
+    ~drop_check() {
+        println("~drop_check");
+
+        if (ok)
+            *ok = true;
+    }
+};
+
+extern "C" {
+    void rust_catch_callback(void (*cb)(), bool* rust_ok);
+
+    static void callback() {
+        println("throwing C++ exception");
+        throw exception();
+    }
+
+    void throw_cxx_exception() {
+        bool rust_ok = false;
+        try {
+            rust_catch_callback(callback, &rust_ok);
+            assert(false && "unreachable");
+        } catch (exception e) {
+            println("caught C++ exception");
+            assert(rust_ok);
+            return;
+        }
+        assert(false && "did not catch thrown C++ exception");
+    }
+
+    void cxx_catch_callback(void (*cb)(), bool* cxx_ok) {
+        drop_check x;
+        x.ok = NULL;
+        try {
+            cb();
+        } catch (rust_panic e) {
+            assert(false && "shouldn't be able to catch a rust panic");
+        } catch (...) {
+            println("caught foreign exception in catch (...)");
+            // Foreign exceptions are caught by catch (...). We only set the ok
+            // flag if we successfully caught the panic. The destructor of
+            // drop_check will then set the flag to true if it is executed.
+            x.ok = cxx_ok;
+            throw;
+        }
+    }
+}
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
new file mode 100644 (file)
index 0000000..399c78f
--- /dev/null
@@ -0,0 +1,66 @@
+// Tests that C++ exceptions can unwind through Rust code, run destructors and
+// are ignored by catch_unwind. Also tests that Rust panics can unwind through
+// C++ code.
+
+// For linking libstdc++ on MinGW
+#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
+
+#![feature(unwind_attributes)]
+
+use std::panic::{catch_unwind, AssertUnwindSafe};
+
+struct DropCheck<'a>(&'a mut bool);
+impl<'a> Drop for DropCheck<'a> {
+    fn drop(&mut self) {
+        println!("DropCheck::drop");
+        *self.0 = true;
+    }
+}
+
+extern "C" {
+    fn throw_cxx_exception();
+
+    #[unwind(allowed)]
+    fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
+}
+
+#[no_mangle]
+#[unwind(allowed)]
+extern "C" fn rust_catch_callback(cb: extern "C" fn(), rust_ok: &mut bool) {
+    let _caught_unwind = catch_unwind(AssertUnwindSafe(|| {
+        let _drop = DropCheck(rust_ok);
+        cb();
+        unreachable!("should have unwound instead of returned");
+    }));
+    unreachable!("catch_unwind should not have caught foreign exception");
+}
+
+fn throw_rust_panic() {
+    #[unwind(allowed)]
+    extern "C" fn callback() {
+        println!("throwing rust panic");
+        panic!(1234i32);
+    }
+
+    let mut dropped = false;
+    let mut cxx_ok = false;
+    let caught_unwind = catch_unwind(AssertUnwindSafe(|| {
+        let _drop = DropCheck(&mut dropped);
+        unsafe {
+            cxx_catch_callback(callback, &mut cxx_ok);
+        }
+        unreachable!("should have unwound instead of returned");
+    }));
+    println!("caught rust panic");
+    assert!(dropped);
+    assert!(caught_unwind.is_err());
+    let panic_obj = caught_unwind.unwrap_err();
+    let panic_int = *panic_obj.downcast_ref::<i32>().unwrap();
+    assert_eq!(panic_int, 1234);
+    assert!(cxx_ok);
+}
+
+fn main() {
+    unsafe { throw_cxx_exception() };
+    throw_rust_panic();
+}
index dc1fbb4cefb8450d97ae4d91f41a4747d2931dae..4f93d97636e6004df6f86731d5937e2e7ed0dbfb 100644 (file)
@@ -6,7 +6,7 @@ all: foo
        $(call RUN,foo)
 
 foo: foo.rs $(call NATIVE_STATICLIB,foo)
-       $(RUSTC) $< -lfoo $(EXTRACXXFLAGS)
+       $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS)
 
 $(TMPDIR)/libfoo.o: foo.cpp
        $(call COMPILE_OBJ_CXX,$@,$<)
index a9d3effbd18060cb959807fbb9cacf1cc211c2d8..061f07c32434016b3686361998f8331171904e19 100644 (file)
@@ -1,5 +1,8 @@
 // Tests that linking to C++ code with global destructors works.
 
+// For linking libstdc++ on MinGW
+#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
+
 extern { fn get() -> u32; }
 
 fn main() {
diff --git a/src/test/run-make-fulldeps/issue-64319/Makefile b/src/test/run-make-fulldeps/issue-64319/Makefile
deleted file mode 100644 (file)
index b2c6b8b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
--include ../tools.mk
-
-# Different optimization levels imply different values for `-Zshare-generics`,
-# so try out a whole bunch of combinations to make sure everything is compatible
-all:
-       # First up, try some defaults
-       $(RUSTC) --crate-type rlib foo.rs
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3
-
-       # Next try mixing up some things explicitly
-       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
-       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
-       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
-       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
-
-       # Now combine a whole bunch of options together
-       $(RUSTC) --crate-type rlib foo.rs
-       $(RUSTC) --crate-type dylib bar.rs
-       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=1
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=2
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=s
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=z
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no
-       $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes
diff --git a/src/test/run-make-fulldeps/issue-64319/bar.rs b/src/test/run-make-fulldeps/issue-64319/bar.rs
deleted file mode 100644 (file)
index 3895c0b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-extern crate foo;
-
-pub fn bar() {
-    foo::foo();
-}
diff --git a/src/test/run-make-fulldeps/issue-64319/foo.rs b/src/test/run-make-fulldeps/issue-64319/foo.rs
deleted file mode 100644 (file)
index c54a238..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-pub fn foo() {
-    bar::<usize>();
-}
-
-pub fn bar<T>() {
-    baz();
-}
-
-fn baz() {}
index 840fe801a953c9ed4e7e35f8fd91ef5304b5ebb8..7901866015bf2ffa564a7a4b8e10ddb8961baeb4 100644 (file)
@@ -79,12 +79,12 @@ all:
        # Check that a Rust dylib exports its monomorphic functions, including generics this time
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
-       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "0" ]
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "1" ]
 
        # Check that a Rust dylib exports the monomorphic functions from its dependencies
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ]
-       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "0" ]
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "1" ]
 
        # Check that an executable does not export any dynamic symbols
        [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ]
index 9a113b7fa6370145e2ed15b14a7b35e1f33a3640..20a5e8e64225dcbec2b5c5544ff21d37e50d3bf5 100644 (file)
@@ -60,7 +60,7 @@ endif
 
 ifdef IS_MSVC
 COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2)
-COMPILE_OBJ_CXX = $(CXX) -c -Fo:`cygpath -w $(1)` $(2)
+COMPILE_OBJ_CXX = $(CXX) -EHs -c -Fo:`cygpath -w $(1)` $(2)
 NATIVE_STATICLIB_FILE = $(1).lib
 NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
 OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
@@ -80,10 +80,29 @@ ifdef IS_MSVC
        EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib
 else
        EXTRACFLAGS := -lws2_32 -luserenv
+       EXTRACXXFLAGS := -lstdc++
+       # So this is a bit hacky: we can't use the DLL version of libstdc++ because
+       # it pulls in the DLL version of libgcc, which means that we end up with 2
+       # instances of the DW2 unwinding implementation. This is a problem on
+       # i686-pc-windows-gnu because each module (DLL/EXE) needs to register its
+       # unwind information with the unwinding implementation, and libstdc++'s
+       # __cxa_throw won't see the unwinding info we registered with our statically
+       # linked libgcc.
+       #
+       # Now, simply statically linking libstdc++ would fix this problem, except
+       # that it is compiled with the expectation that pthreads is dynamically
+       # linked as a DLL and will fail to link with a statically linked libpthread.
+       #
+       # So we end up with the following hack: we link use static-nobundle to only
+       # link the parts of libstdc++ that we actually use, which doesn't include
+       # the dependency on the pthreads DLL.
+       EXTRARSCXXFLAGS := -l static-nobundle=stdc++
 endif
 else
 ifeq ($(UNAME),Darwin)
        EXTRACFLAGS := -lresolv
+       EXTRACXXFLAGS := -lc++
+       EXTRARSCXXFLAGS := -lc++
 else
 ifeq ($(UNAME),FreeBSD)
        EXTRACFLAGS := -lm -lpthread -lgcc_s
@@ -97,6 +116,7 @@ ifeq ($(UNAME),OpenBSD)
 else
        EXTRACFLAGS := -lm -lrt -ldl -lpthread
        EXTRACXXFLAGS := -lstdc++
+       EXTRARSCXXFLAGS := -lstdc++
 endif
 endif
 endif
index e88ddfb9e2ad206d858d8f8c3111ead2776da8b9..587fe21f8fa738b629ab49927188e4b2b9599575 100644 (file)
@@ -5,8 +5,6 @@
 // Crates like core have doctests gated on `cfg(not(test))` so we need to make
 // sure `cfg(test)` is not active when running `rustdoc --test`.
 
-#![feature(cfg_doctest)]
-
 /// this doctest will be ignored:
 ///
 /// ```
index 86141aed5c3f2b0cfee6922ea5f17d08ad373503..474f13cfa9843d874421d079443393d25713e688 100644 (file)
@@ -1,7 +1,7 @@
 
 running 2 tests
-test $DIR/cfg-test.rs - Bar (line 28) ... ok
-test $DIR/cfg-test.rs - Foo (line 20) ... ok
+test $DIR/cfg-test.rs - Bar (line 26) ... ok
+test $DIR/cfg-test.rs - Foo (line 18) ... ok
 
 test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
 
index fca6d1029f981ea7b108b4bd40c553d481b5fe9d..6a9d26a4bb78cbaabc2a6458a6ed71edca3eba1a 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(cfg_doctest)]
-
 // @!has cfg_doctest/struct.SomeStruct.html
 // @!has cfg_doctest/index.html '//a/@href' 'struct.SomeStruct.html'
 
diff --git a/src/test/rustdoc/issue-55364.rs b/src/test/rustdoc/issue-55364.rs
new file mode 100644 (file)
index 0000000..200a29f
--- /dev/null
@@ -0,0 +1,88 @@
+// ignore-tidy-linelength
+
+// First a module with inner documentation
+
+// @has issue_55364/subone/index.html
+// These foo/bar links in the module's documentation should refer inside `subone`
+// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.foo.html"]' 'foo'
+// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.bar.html"]' 'bar'
+pub mod subone {
+    //! See either [foo] or [bar].
+
+    // This should refer to subone's `bar`
+    // @has issue_55364/subone/fn.foo.html
+    // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.bar.html"]' 'bar'
+    /// See [bar]
+    pub fn foo() {}
+    // This should refer to subone's `foo`
+    // @has issue_55364/subone/fn.bar.html
+    // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.foo.html"]' 'foo'
+    /// See [foo]
+    pub fn bar() {}
+}
+
+// A module with outer documentation
+
+// @has issue_55364/subtwo/index.html
+// These foo/bar links in the module's documentation should not reference inside `subtwo`
+// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.foo.html"]' 'foo'
+// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.bar.html"]' 'bar'
+// Instead it should be referencing the top level functions
+// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.foo.html"]' 'foo'
+// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.bar.html"]' 'bar'
+// Though there should be such links later
+// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.foo.html"]' 'foo'
+// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.bar.html"]' 'bar'
+/// See either [foo] or [bar].
+pub mod subtwo {
+
+    // Despite the module's docs referring to the top level foo/bar,
+    // this should refer to subtwo's `bar`
+    // @has issue_55364/subtwo/fn.foo.html
+    // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.bar.html"]' 'bar'
+    /// See [bar]
+    pub fn foo() {}
+    // Despite the module's docs referring to the top level foo/bar,
+    // this should refer to subtwo's `foo`
+    // @has issue_55364/subtwo/fn.bar.html
+    // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.foo.html"]' 'foo'
+    /// See [foo]
+    pub fn bar() {}
+}
+
+// These are the function referred to by the module above with outer docs
+
+/// See [bar]
+pub fn foo() {}
+/// See [foo]
+pub fn bar() {}
+
+// This module refers to the outer foo/bar by means of `super::`
+
+// @has issue_55364/subthree/index.html
+// This module should also refer to the top level foo/bar
+// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.foo.html"]' 'foo'
+// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.bar.html"]' 'bar'
+pub mod subthree {
+    //! See either [foo][super::foo] or [bar][super::bar]
+}
+
+// Next we go *deeper* - In order to ensure it's not just "this or parent"
+// we test `crate::` and a `super::super::...` chain
+// @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html
+// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../../issue_55364/subone/fn.foo.html"]' 'other foo'
+// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../../issue_55364/subtwo/fn.bar.html"]' 'other bar'
+pub mod subfour {
+    pub mod subfive {
+        pub mod subsix {
+            pub mod subseven {
+                pub mod subeight {
+                    /// See [other foo][crate::subone::foo]
+                    pub fn foo() {}
+                    /// See [other bar][super::super::super::super::super::subtwo::bar]
+                    pub fn bar() {}
+                }
+            }
+        }
+    }
+}
index 55a880be0f985ab5002f5d44983a425956987299..7b74be7a95482f80d6fcac00d7162d87c0c581ef 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-stage1
 
 #![feature(plugin)]
-#![plugin(lint_group_plugin_test)]
+#![plugin(lint_group_plugin_test)] //~ WARNING use of deprecated attribute
 #![allow(dead_code)]
 
 fn lintme() { } //~ WARNING item is named 'lintme'
index 5f8bc16301a74eadc832f44ebbd8567cc04110c5..66057eea6bcf7bd11b6ee5d1af8605165fa95583 100644 (file)
@@ -2,7 +2,7 @@
 // aux-build:lint-plugin-test.rs
 // ignore-stage1
 #![feature(plugin)]
-#![plugin(lint_plugin_test)]
+#![plugin(lint_plugin_test)] //~ WARNING use of deprecated attribute
 #![allow(dead_code)]
 
 fn lintme() { } //~ WARNING item is named 'lintme'
index b30e8f00e4035c93067b64624a8c52c085608c99..5d6fa416b9895e7e3aa2a1890a64f3c9846589cb 100644 (file)
@@ -5,10 +5,6 @@
 
 // ignore-wasm32-bare no libc to test ffi with
 
-// FIXME: This will work on emscripten once libc is updated to include
-// rust-lang/libc/#1478
-// ignore-emscripten libc type mismatch
-
 #![feature(rustc_private)]
 
 extern crate libc;
index c51c56b08992618171b902bf53459b47d9be0426..adbd05ed8c1757593995a802f856518ad7ae3d6e 100644 (file)
@@ -28,7 +28,7 @@ fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
     box Invoker {
         a: a,
         b: b,
-    } as (Box<dyn Invokable<A>+'static>)
+    } as Box<dyn Invokable<A>+'static>
 }
 
 pub fn main() {
index a9f6fceb08ff093a10ca1bd3328e216ad717e905..feb0cb30ccaccf49f057db73e9f492e52e538db7 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 
+#[allow(unused_parens)]
 fn main() {
     assert_eq!(3 as usize * 3, 9);
     assert_eq!(3 as (usize) * 3, 9);
index a3fa97f54e385c863f343916923008ee74da54ee..7f58f7f73e38c8d77044065182ad55652135e028 100644 (file)
@@ -5,7 +5,10 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(type_alias_bounds)]` on by default
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaWhere1<T>  = T;
+   |                  --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias.rs:6:25
@@ -13,7 +16,10 @@ warning: where clauses are not enforced in type aliases
 LL | type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaWhere2<T>  = T;
+   |                  --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias.rs:7:25
@@ -21,7 +27,10 @@ warning: where clauses are not enforced in type aliases
 LL | type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaWhere3<T>  = T;
+   |                  --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias.rs:8:25
@@ -29,7 +38,10 @@ warning: where clauses are not enforced in type aliases
 LL | type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaWhere4<T>  = T;
+   |                  --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias.rs:9:25
@@ -37,7 +49,10 @@ warning: where clauses are not enforced in type aliases
 LL | type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaWhere5<T>  = T;
+   |                  --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias.rs:10:25
@@ -45,7 +60,10 @@ warning: where clauses are not enforced in type aliases
 LL | type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaWhere6<T>  = T;
+   |                  --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias.rs:12:20
@@ -53,7 +71,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type _TaInline1<T: Iterator<Item: Copy>> = T;
    |                    ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaInline1<T> = T;
+   |                 --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias.rs:13:20
@@ -61,7 +82,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type _TaInline2<T: Iterator<Item: 'static>> = T;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaInline2<T> = T;
+   |                 --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias.rs:14:20
@@ -69,7 +93,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type _TaInline3<T: Iterator<Item: 'static>> = T;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaInline3<T> = T;
+   |                 --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias.rs:15:20
@@ -77,7 +104,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaInline4<T> = T;
+   |                 --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias.rs:16:20
@@ -85,7 +115,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaInline5<T> = T;
+   |                 --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias.rs:17:20
@@ -93,5 +126,8 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type _TaInline6<T> = T;
+   |                 --
 
index 6a2135ca46445bceacffd8e7627cfcc74ff0cf2a..800b762911a62e3bf3532317cd6a6bb3bacf04d1 100644 (file)
@@ -5,10 +5,10 @@ LL | fn blue_car<C:Car<Color=Blue>>(c: C) {
    |    --------       ---------- required by this bound in `blue_car`
 ...
 LL | fn b() { blue_car(ModelT); }
-   |          ^^^^^^^^ expected struct `Black`, found struct `Blue`
+   |          ^^^^^^^^ expected struct `Blue`, found struct `Black`
    |
-   = note: expected type `Black`
-              found type `Blue`
+   = note: expected type `Blue`
+              found type `Black`
 
 error[E0271]: type mismatch resolving `<ModelU as Vehicle>::Color == Black`
   --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10
@@ -17,10 +17,10 @@ LL | fn black_car<C:Car<Color=Black>>(c: C) {
    |    ---------       ----------- required by this bound in `black_car`
 ...
 LL | fn c() { black_car(ModelU); }
-   |          ^^^^^^^^^ expected struct `Blue`, found struct `Black`
+   |          ^^^^^^^^^ expected struct `Black`, found struct `Blue`
    |
-   = note: expected type `Blue`
-              found type `Black`
+   = note: expected type `Black`
+              found type `Blue`
 
 error: aborting due to 2 previous errors
 
index 9366148b587d2dded4f117511c73acfd90848077..22e04a8f15ca823f5d607b2eb7e207dbae63f96b 100644 (file)
@@ -37,8 +37,8 @@ pub fn main() {
     let a = 42;
     foo1(a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize, found struct `Bar`
+    //~| expected struct `Bar`, found usize
     baz(&a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize, found struct `Bar`
+    //~| expected struct `Bar`, found usize
 }
index 83d89924944ab9202b8b4c1d15ef39e86fd1c628..0f2bc84aa1c592d5563d94bb4e293cc5552a9b97 100644 (file)
@@ -16,19 +16,19 @@ LL | fn foo1<I: Foo<A=Bar>>(x: I) {
    |    ----        ----- required by this bound in `foo1`
 ...
 LL |     foo1(a);
-   |     ^^^^ expected usize, found struct `Bar`
+   |     ^^^^ expected struct `Bar`, found usize
    |
-   = note: expected type `usize`
-              found type `Bar`
+   = note: expected type `Bar`
+              found type `usize`
 
 error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
   --> $DIR/associated-types-eq-3.rs:41:9
    |
 LL |     baz(&a);
-   |         ^^ expected usize, found struct `Bar`
+   |         ^^ expected struct `Bar`, found usize
    |
-   = note: expected type `usize`
-              found type `Bar`
+   = note: expected type `Bar`
+              found type `usize`
    = note: required for the cast to the object type `dyn Foo<A = Bar>`
 
 error: aborting due to 3 previous errors
index 45b6cc9ba5f982761c276dc5c26148064aa5ed72..a8c239389e9776f8b2b8e8d10ead891a5fdd9839 100644 (file)
@@ -7,10 +7,10 @@ LL |     where T : for<'x> TheTrait<&'x isize, A = &'x isize>
    |                                           ------------- required by this bound in `foo`
 ...
 LL |     foo::<UintStruct>();
-   |     ^^^^^^^^^^^^^^^^^ expected usize, found isize
+   |     ^^^^^^^^^^^^^^^^^ expected isize, found usize
    |
-   = note: expected type `&usize`
-              found type `&isize`
+   = note: expected type `&isize`
+              found type `&usize`
 
 error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
   --> $DIR/associated-types-eq-hr.rs:86:5
@@ -21,10 +21,10 @@ LL |     where T : for<'x> TheTrait<&'x isize, A = &'x usize>
    |                                           ------------- required by this bound in `bar`
 ...
 LL |     bar::<IntStruct>();
-   |     ^^^^^^^^^^^^^^^^ expected isize, found usize
+   |     ^^^^^^^^^^^^^^^^ expected usize, found isize
    |
-   = note: expected type `&isize`
-              found type `&usize`
+   = note: expected type `&usize`
+              found type `&isize`
 
 error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
   --> $DIR/associated-types-eq-hr.rs:91:17
index c8f8725afc45cd9ec7465fbc9abb89f58f53bd7b..b763b82d540cce32fbf0b00c09c6ebc3ba809915 100644 (file)
@@ -5,10 +5,10 @@ LL | fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
    |    --------------                ------ required by this bound in `is_iterator_of`
 ...
 LL |     is_iterator_of::<Option<T>, _>(&adapter);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found type parameter
    |
-   = note: expected type `T`
-              found type `std::option::Option<T>`
+   = note: expected type `std::option::Option<T>`
+              found type `T`
    = help: type parameters must be constrained to match other types
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
index c7de186c1d3e072a680c085793a542e1f585b3fc..e3a2b5edf3f1b6ee3b02a75a8aa1f0192ddf3c2e 100644 (file)
@@ -2,28 +2,28 @@ error[E0271]: type mismatch resolving `<T as Foo>::Y == i32`
   --> $DIR/associated-types-multiple-types-one-trait.rs:13:5
    |
 LL |     want_y(t);
-   |     ^^^^^^ expected associated type, found i32
+   |     ^^^^^^ expected i32, found associated type
 ...
 LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
    |    ------       ----- required by this bound in `want_y`
    |
-   = note: expected type `<T as Foo>::Y`
-              found type `i32`
-   = note: consider constraining the associated type `<T as Foo>::Y` to `i32` or calling a method that returns `<T as Foo>::Y`
+   = note: expected type `i32`
+              found type `<T as Foo>::Y`
+   = note: consider constraining the associated type `<T as Foo>::Y` to `i32`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error[E0271]: type mismatch resolving `<T as Foo>::X == u32`
   --> $DIR/associated-types-multiple-types-one-trait.rs:18:5
    |
 LL |     want_x(t);
-   |     ^^^^^^ expected associated type, found u32
+   |     ^^^^^^ expected u32, found associated type
 ...
 LL | fn want_x<T:Foo<X=u32>>(t: &T) { }
    |    ------       ----- required by this bound in `want_x`
    |
-   = note: expected type `<T as Foo>::X`
-              found type `u32`
-   = note: consider constraining the associated type `<T as Foo>::X` to `u32` or calling a method that returns `<T as Foo>::X`
+   = note: expected type `u32`
+              found type `<T as Foo>::X`
+   = note: consider constraining the associated type `<T as Foo>::X` to `u32`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error: aborting due to 2 previous errors
index aff067c289107a60db7cb4150658ebe39e1c8258..02a6ac12dd927a8afca22e25237dfffefabc2c94 100644 (file)
@@ -2,10 +2,10 @@ error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::It
   --> $DIR/associated-types-overridden-binding-2.rs:6:43
    |
 LL |     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
-   |                                           ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
+   |                                           ^^^^^^^^^^^^^^^^^^^^^ expected i32, found u32
    |
-   = note: expected type `u32`
-              found type `i32`
+   = note: expected type `i32`
+              found type `u32`
    = note: required for the cast to the object type `dyn std::iter::Iterator<Item = u32, Item = i32>`
 
 error: aborting due to previous error
index a9b0e7ae7795daf6fdc18fb5c39945defe7c505b..6bef9dca265e72cbfebed5123b1969fa46dfde92 100644 (file)
@@ -33,10 +33,10 @@ error[E0271]: type mismatch resolving `<impl std::future::Future as std::future:
   --> $DIR/async-block-control-flow-static-semantics.rs:18:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
-   |                                       ^^^^^^ expected u8, found ()
+   |                                       ^^^^^^ expected (), found u8
    |
-   = note: expected type `u8`
-              found type `()`
+   = note: expected type `()`
+              found type `u8`
    = note: required for the cast to the object type `dyn std::future::Future<Output = ()>`
 
 error[E0308]: mismatched types
@@ -59,10 +59,10 @@ error[E0271]: type mismatch resolving `<impl std::future::Future as std::future:
   --> $DIR/async-block-control-flow-static-semantics.rs:27:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
-   |                                       ^^^^^^ expected u8, found ()
+   |                                       ^^^^^^ expected (), found u8
    |
-   = note: expected type `u8`
-              found type `()`
+   = note: expected type `()`
+              found type `u8`
    = note: required for the cast to the object type `dyn std::future::Future<Output = ()>`
 
 error[E0308]: mismatched types
diff --git a/src/test/ui/async-await/try-on-option-in-async.rs b/src/test/ui/async-await/try-on-option-in-async.rs
new file mode 100644 (file)
index 0000000..51ac522
--- /dev/null
@@ -0,0 +1,27 @@
+#![feature(try_trait, async_closure)]
+// edition:2018
+fn main() {}
+
+async fn an_async_block() -> u32 {
+    async {
+        let x: Option<u32> = None;
+        x?; //~ ERROR the `?` operator
+        22
+    }.await
+}
+
+async fn async_closure_containing_fn() -> u32 {
+    let async_closure = async || {
+        let x: Option<u32> = None;
+        x?; //~ ERROR the `?` operator
+        22_u32
+    };
+
+    async_closure().await
+}
+
+async fn an_async_function() -> u32 {
+    let x: Option<u32> = None;
+    x?; //~ ERROR the `?` operator
+    22
+}
diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr
new file mode 100644 (file)
index 0000000..7d31f60
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-in-async.rs:8:9
+   |
+LL |         x?;
+   |         ^^ cannot use the `?` operator in an async block that returns `{integer}`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `{integer}`
+   = note: required by `std::ops::Try::from_error`
+
+error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-in-async.rs:16:9
+   |
+LL |         x?;
+   |         ^^ cannot use the `?` operator in an async closure that returns `u32`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `u32`
+   = note: required by `std::ops::Try::from_error`
+
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-in-async.rs:25:5
+   |
+LL |     x?;
+   |     ^^ cannot use the `?` operator in an async function that returns `u32`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `u32`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 4e0a238c5d48d9b86c02a4abe18a389cc7182a1c..ea4a9e5afa50157279c76ac8d737e16e329f2ab7 100644 (file)
@@ -2,7 +2,7 @@
 // Check that partially moved from function parameters are dropped after the
 // named bindings that move from them.
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 use std::{panic, cell::RefCell};
 
index 1fd91440a7884b4d07006a24b01c213f0674dfdf..339bcfa1060a48e6a3c560176a987535317c2230 100644 (file)
@@ -2,7 +2,7 @@
 
 #![allow(unused_variables)]
 #![allow(unused_imports)]
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 // Test that builtin implementations of `Clone` cleanup everything
 // in case of unwinding.
index c2c21bca7ef71be79dfafb356545828905e463f0..f181991713b2cd3fb4add9cec8f6f0db83a35bfb 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 fn worker() -> ! {
     panic!()
index 40e5f500df4a833131639aab8755d0406f46f1a9..4d6edf4ecb0f330522ce374a08209a48c3a10210 100644 (file)
@@ -30,7 +30,7 @@ fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
     box Invoker {
         a: a,
         b: b,
-    } as (Box<dyn Invokable<A>+'static>)
+    } as Box<dyn Invokable<A>+'static>
 }
 
 pub fn main() {
index 645e4e71dfe9aca73d0f8a4c9942ca4f5f8f8f3f..cd635c6a722023ff75256a071b7ac5ba703a0919 100644 (file)
@@ -17,5 +17,5 @@ fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
 
 fn main() {
     MustUseDeprecated::new(); //~ warning: use of deprecated item
-    //| warning: unused `MustUseDeprecated` that must be used
+    //~| warning: unused `MustUseDeprecated` that must be used
 }
index cb40734c1d257fa88c0cf4490dcdbcf3fc68a242..0fbd0bbcbaebd4972f84b5bc640b5613cd558675 100644 (file)
@@ -8,6 +8,5 @@
 struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]);
 
 fn main() {
-    let _ = Foo::<3>([1, 2, 3]); //~ ERROR type annotations needed
-    //~^ ERROR mismatched types
+    let _ = Foo::<3>([1, 2, 3]);
 }
index 330c93e83b5e7d1f2230cbd27f001af1a15ff3b0..cfb1f8b581c85039c1ca3d3cf1d25133d99a3f49 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: const generics are unstable
-  --> $DIR/const-param-in-trait-ungated.rs:1:13
+  --> $DIR/const-param-in-trait-ungated.rs:1:19
    |
 LL | trait Trait<const T: ()> {}
-   |             ^^^^^^^^^^^
+   |                   ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
index e34a2da24cecc8d3daef20dc866d672ef398d5b0..a2872ab982da49ed13519285ddc23608e86c2405 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: const generics are unstable
-  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:13
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
    |
 LL | struct B<T, const N: T>(PhantomData<[T; N]>);
-   |             ^^^^^^^^^^
+   |                   ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
index 5223c8c5137aeae97552db686946db730a7a0b71..fe7b6fdb1904d7fcb85b3be677dec5a04da974c9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: const generics are unstable
-  --> $DIR/issue-60263.rs:1:10
+  --> $DIR/issue-60263.rs:1:16
    |
 LL | struct B<const I: u8>;
-   |          ^^^^^^^^^^^
+   |                ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
index 4dc46eb0ef65aa26c77b964c52f6ea325a6113b9..4e5e4d045c8f226c9e661621613828735072f9c9 100644 (file)
@@ -12,5 +12,5 @@ pub trait BitLen: Sized {
 }
 
 fn main() {
-    let foo = <[u8; 2]>::BIT_LEN;
+    let foo = <[u8; 2]>::BIT_LEN; //~ WARN unused variable
 }
diff --git a/src/test/ui/consts/offset_from.rs b/src/test/ui/consts/offset_from.rs
new file mode 100644 (file)
index 0000000..4d68006
--- /dev/null
@@ -0,0 +1,47 @@
+// run-pass
+
+#![feature(const_raw_ptr_deref)]
+#![feature(const_ptr_offset_from)]
+#![feature(ptr_offset_from)]
+
+struct Struct {
+    field: (),
+}
+
+#[repr(C)]
+struct Struct2 {
+    data: u8,
+    field: u8,
+}
+
+pub const OFFSET: usize = {
+    let uninit = std::mem::MaybeUninit::<Struct>::uninit();
+    let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
+    // The following statement is UB (taking the address of an uninitialized field).
+    // Const eval doesn't detect this right now, but it may stop compiling at some point
+    // in the future.
+    let field_ptr = unsafe { &(*base_ptr).field as *const () as *const u8 };
+    let offset = unsafe { field_ptr.offset_from(base_ptr as *const u8) };
+    offset as usize
+};
+
+pub const OFFSET_2: usize = {
+    let uninit = std::mem::MaybeUninit::<Struct2>::uninit();
+    let base_ptr: *const Struct2 = &uninit as *const _ as *const Struct2;
+    let field_ptr = unsafe { &(*base_ptr).field as *const u8 };
+    let offset = unsafe { field_ptr.offset_from(base_ptr as *const u8) };
+    offset as usize
+};
+
+pub const OVERFLOW: isize = {
+    let uninit = std::mem::MaybeUninit::<Struct2>::uninit();
+    let base_ptr: *const Struct2 = &uninit as *const _ as *const Struct2;
+    let field_ptr = unsafe { &(*base_ptr).field as *const u8 };
+    unsafe { (base_ptr as *const u8).offset_from(field_ptr) }
+};
+
+fn main() {
+    assert_eq!(OFFSET, 0);
+    assert_eq!(OFFSET_2, 1);
+    assert_eq!(OVERFLOW, -1);
+}
diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs
new file mode 100644 (file)
index 0000000..18b4d72
--- /dev/null
@@ -0,0 +1,37 @@
+// ignore-x86 FIXME: missing sysroot spans (#53081)
+
+#![feature(const_raw_ptr_deref)]
+#![feature(const_ptr_offset_from)]
+#![feature(ptr_offset_from)]
+
+#[repr(C)]
+struct Struct {
+    data: u8,
+    field: u8,
+}
+
+pub const DIFFERENT_ALLOC: usize = {
+    //~^ NOTE
+    let uninit = std::mem::MaybeUninit::<Struct>::uninit();
+    let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
+    let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
+    let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
+    let offset = unsafe { field_ptr.offset_from(base_ptr) };
+    offset as usize
+};
+
+pub const NOT_PTR: usize = {
+    //~^ NOTE
+    unsafe { (42 as *const u8).offset_from(&5u8) as usize }
+};
+
+pub const NOT_MULTIPLE_OF_SIZE: usize = {
+    //~^ NOTE
+    let data = [5u8, 6, 7];
+    let base_ptr = data.as_ptr();
+    let field_ptr = &data[1] as *const u8 as *const u16;
+    let offset = unsafe { field_ptr.offset_from(base_ptr as *const u16) };
+    offset as usize
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr
new file mode 100644 (file)
index 0000000..289128b
--- /dev/null
@@ -0,0 +1,61 @@
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+   |
+LL |           intrinsics::ptr_offset_from(self, origin)
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |           |
+   |           ptr_offset_from cannot compute offset of pointers into different allocations.
+   |           inside call to `std::ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:19:27
+   | 
+  ::: $DIR/offset_from_ub.rs:13:1
+   |
+LL | / pub const DIFFERENT_ALLOC: usize = {
+LL | |
+LL | |     let uninit = std::mem::MaybeUninit::<Struct>::uninit();
+LL | |     let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
+...  |
+LL | |     offset as usize
+LL | | };
+   | |__-
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+   |
+LL |           intrinsics::ptr_offset_from(self, origin)
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |           |
+   |           a memory access tried to interpret some bytes as a pointer
+   |           inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:25:14
+   | 
+  ::: $DIR/offset_from_ub.rs:23:1
+   |
+LL | / pub const NOT_PTR: usize = {
+LL | |
+LL | |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
+LL | | };
+   | |__-
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+   |
+LL |           intrinsics::ptr_offset_from(self, origin)
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |           |
+   |           exact_div: 1 cannot be divided by 2 without remainder
+   |           inside call to `std::ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:27
+   | 
+  ::: $DIR/offset_from_ub.rs:28:1
+   |
+LL | / pub const NOT_MULTIPLE_OF_SIZE: usize = {
+LL | |
+LL | |     let data = [5u8, 6, 7];
+LL | |     let base_ptr = data.as_ptr();
+...  |
+LL | |     offset as usize
+LL | | };
+   | |__-
+
+error: aborting due to 3 previous errors
+
index b94c365f2539a904269473532e6928c6800c9823..c3eea2e7b8ad6629d04fb8e56aadacc548cfbb80 100644 (file)
@@ -3,8 +3,8 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main`
    |
 LL | / #![allow(dead_code)]
 LL | |
-LL | | // error-pattern:`main` function not found in crate
-LL | |
+LL | | struct Tableau<'a, MP> {
+LL | |     provider: &'a MP,
 ...  |
 LL | |
 LL | | }
index 7455c2a431d6289fdb7c9bb8f2255d183afe8843..55796408e9d79ab1278398049bfe9fde0bb23fa2 100644 (file)
@@ -1,6 +1,4 @@
-#![allow(dead_code)]
-
-// error-pattern:`main` function not found in crate
+#![allow(dead_code)] //~ ERROR `main` function not found in crate
 
 struct Tableau<'a, MP> {
     provider: &'a MP,
index d764e7d860af678b4432349223b0ac3f802804d2..64d34cb6a19475eac1de3a6cf1a356ddb3c72201 100644 (file)
@@ -3,15 +3,15 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main`
    |
 LL | / #![allow(dead_code)]
 LL | |
-LL | | // error-pattern:`main` function not found in crate
-LL | |
+LL | | struct Tableau<'a, MP> {
+LL | |     provider: &'a MP,
 ...  |
 LL | |
 LL | | }
    | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
 
 error[E0623]: lifetime mismatch
-  --> $DIR/continue-after-missing-main.rs:30:56
+  --> $DIR/continue-after-missing-main.rs:28:56
    |
 LL |     tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>,
    |              ------------------------------------------------------------------ these two types are declared with different lifetimes...
diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs
new file mode 100644 (file)
index 0000000..82bb95f
--- /dev/null
@@ -0,0 +1,16 @@
+// compile-flags: -C debuginfo=2
+
+// no-prefer-dynamic
+#![crate_type = "rlib"]
+
+pub trait Object { fn method(&self) { } }
+
+impl Object for u32 { }
+impl Object for () { }
+impl<T> Object for &T { }
+
+pub fn unused() {
+    let ref u = 0_u32;
+    let _d = &u as &dyn crate::Object;
+    _d.method()
+}
diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs
new file mode 100644 (file)
index 0000000..21c0274
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: -C debuginfo=2 -C prefer-dynamic
+
+#![crate_type="dylib"]
+
+extern crate a_def_obj;
+
+pub use a_def_obj::Object;
diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs
new file mode 100644 (file)
index 0000000..611238f
--- /dev/null
@@ -0,0 +1,12 @@
+// no-prefer-dynamic
+// compile-flags: -C debuginfo=2
+#![crate_type="rlib"]
+
+extern crate b_reexport_obj;
+use b_reexport_obj::Object;
+
+pub fn another_dyn_debug() {
+    let ref u = 1_u32;
+    let _d = &u as &dyn crate::Object;
+    _d.method()
+}
diff --git a/src/test/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs b/src/test/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs
new file mode 100644 (file)
index 0000000..8d73f9b
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: -C debuginfo=2 -C prefer-dynamic
+
+#![crate_type="rlib"]
+
+extern crate c_another_vtable_for_obj;
+
+pub fn chain() {
+    c_another_vtable_for_obj::another_dyn_debug();
+}
diff --git a/src/test/ui/cross-crate/issue-64872/issue-64872.rs b/src/test/ui/cross-crate/issue-64872/issue-64872.rs
new file mode 100644 (file)
index 0000000..20fe205
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+
+// note that these aux-build directives must be in this order: the
+// later crates depend on the earlier ones. (The particular bug that
+// is being exercised here used to exhibit itself during the build of
+// `chain_of_rlibs_and_dylibs.dylib`)
+
+// aux-build:a_def_obj.rs
+// aux-build:b_reexport_obj.rs
+// aux-build:c_another_vtable_for_obj.rs
+// aux-build:d_chain_of_rlibs_and_dylibs.rs
+
+extern crate d_chain_of_rlibs_and_dylibs;
+
+pub fn main() {
+    d_chain_of_rlibs_and_dylibs::chain();
+}
index 010464adf5bce7c441462453bb5301eab4b0209c..0b4c8f3952fcd0f630ed485f823daae8df20b043 100644 (file)
@@ -10,7 +10,7 @@ enum Void {}
 #[derive(Debug)]
 enum Foo {
     Bar(u8),
-    Void(Void), //~ WARN never used
+    Void(Void), //~ WARN never constructed
 }
 
 fn main() {
index bec86d6465ae94e261e9357fb499a82c15bdd38a..91063edf0f6c4badf45a759ad86bcb9722290287 100644 (file)
@@ -5,7 +5,7 @@
 
 // run-pass
 // edition:2018
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(slice_patterns)]
 #![allow(unused)]
index 5a7568fe2cd50fa025c5ad8018da27c56f448d4b..29dcbfe9609a0bf59fe36bea428144cc9c9e8fbe 100644 (file)
@@ -2,7 +2,7 @@
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions)]
 #![feature(slice_patterns)]
index c56853f45a0b0150112d32d1a33a38e1ec8b7f4f..378e5e3630641bdb9a2b68699f30c253dafd8c20 100644 (file)
@@ -5,10 +5,10 @@ LL | fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
    |    ---                         ------------------ required by this bound in `foo`
 ...
 LL |     foo(3_i8);
-   |     ^^^ expected reference, found u32
+   |     ^^^ expected u32, found reference
    |
-   = note: expected type `&'static str`
-              found type `u32`
+   = note: expected type `u32`
+              found type `&'static str`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gate/feature-gate-cfg_doctest.rs b/src/test/ui/feature-gate/feature-gate-cfg_doctest.rs
deleted file mode 100644 (file)
index 308f68b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#[cfg(doctest)] //~ ERROR
-pub struct SomeStruct;
-
-fn main() {}
diff --git a/src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr b/src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr
deleted file mode 100644 (file)
index 5ab45e0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: `cfg(doctest)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg_doctest.rs:1:7
-   |
-LL | #[cfg(doctest)]
-   |       ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62210
-   = help: add `#![feature(cfg_doctest)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index 8c567ece1875b776eb3b1591bd8c26f2ed3cbf0e..0d804f012bcc3dec031460a641b2d03799bf73c3 100644 (file)
@@ -38,6 +38,7 @@
 // Exception, a gated and deprecated attribute.
 
 #![plugin_registrar] //~ WARN unused attribute
+//~| WARN use of deprecated attribute
 
 // UNGATED WHITE-LISTED BUILT-IN ATTRIBUTES
 
@@ -90,7 +91,7 @@
 #![crate_id = "10"] //~ WARN use of deprecated attribute
 
 // FIXME(#44232) we should warn that this isn't used.
-#![feature(rust1)]
+#![feature(rust1)] //~ WARN no longer requires an attribute to enable
 
 #![no_start] //~ WARN use of deprecated attribute
 
@@ -215,20 +216,25 @@ mod inner { #![macro_export] }
 
 #[plugin_registrar]
 //~^ WARN unused attribute
+//~| WARN use of deprecated attribute
 mod plugin_registrar {
     mod inner { #![plugin_registrar] }
     //~^ WARN unused attribute
+    //~| WARN use of deprecated attribute
 
     // for `fn f()` case, see gated-plugin_registrar.rs
 
     #[plugin_registrar] struct S;
     //~^ WARN unused attribute
+    //~| WARN use of deprecated attribute
 
     #[plugin_registrar] type T = S;
     //~^ WARN unused attribute
+    //~| WARN use of deprecated attribute
 
     #[plugin_registrar] impl S { }
     //~^ WARN unused attribute
+    //~| WARN use of deprecated attribute
 }
 
 #[main]
index e78d9840abf7d659f7c7289c0b8f3826bd749650..9ce90d89d22d224a1290d8245267b0abc65e3a8e 100644 (file)
@@ -1,5 +1,5 @@
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:9
    |
 LL | #![warn(x5400)]
    |         ^^^^^
@@ -11,175 +11,175 @@ LL | #![warn(unused_attributes, unknown_lints)]
    |                            ^^^^^^^^^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:10
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:10
    |
 LL | #![allow(x5300)]
    |          ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:11
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:11
    |
 LL | #![forbid(x5200)]
    |           ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:48:9
    |
 LL | #![deny(x5100)]
    |         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:104:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8
    |
 LL | #[warn(x5400)]
    |        ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:107:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:108:25
    |
 LL |     mod inner { #![warn(x5400)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:110:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:12
    |
 LL |     #[warn(x5400)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:12
    |
 LL |     #[warn(x5400)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:12
    |
 LL |     #[warn(x5400)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12
    |
 LL |     #[warn(x5400)] impl S { }
    |            ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:9
    |
 LL | #[allow(x5300)]
    |         ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:26
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:26
    |
 LL |     mod inner { #![allow(x5300)] }
    |                          ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:13
    |
 LL |     #[allow(x5300)] fn f() { }
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:13
    |
 LL |     #[allow(x5300)] struct S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:13
    |
 LL |     #[allow(x5300)] type T = S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13
    |
 LL |     #[allow(x5300)] impl S { }
    |             ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:10
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:10
    |
 LL | #[forbid(x5200)]
    |          ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:27
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:27
    |
 LL |     mod inner { #![forbid(x5200)] }
    |                           ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:14
    |
 LL |     #[forbid(x5200)] fn f() { }
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:14
    |
 LL |     #[forbid(x5200)] struct S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:14
    |
 LL |     #[forbid(x5200)] type T = S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14
    |
 LL |     #[forbid(x5200)] impl S { }
    |              ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:8
    |
 LL | #[deny(x5100)]
    |        ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:25
    |
 LL |     mod inner { #![deny(x5100)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:12
    |
 LL |     #[deny(x5100)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:12
    |
 LL |     #[deny(x5100)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:12
    |
 LL |     #[deny(x5100)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12
    |
 LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: macro_escape is a deprecated synonym for macro_use
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
 
 warning: macro_escape is a deprecated synonym for macro_use
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -187,7 +187,7 @@ LL |     mod inner { #![macro_escape] }
    = help: consider an outer attribute, `#[macro_use]` mod ...
 
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:17
    |
 LL |     mod inner { #![plugin_registrar] }
    |                 ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
@@ -195,25 +195,25 @@ LL |     mod inner { #![plugin_registrar] }
    = note: `#[warn(deprecated)]` on by default
 
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5
    |
 LL |     #[plugin_registrar] struct S;
    |     ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
 
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5
    |
 LL |     #[plugin_registrar] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
 
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:230:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
    |
 LL |     #[plugin_registrar] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
 
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:217:1
    |
 LL | #[plugin_registrar]
    | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
@@ -225,19 +225,19 @@ LL | #![plugin_registrar]
    | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
 
 warning: use of deprecated attribute `crate_id`: no longer used.
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:91:1
    |
 LL | #![crate_id = "10"]
    | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute
 
 warning: use of deprecated attribute `no_start`: no longer used.
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:95:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:96:1
    |
 LL | #![no_start]
    | ^^^^^^^^^^^^ help: remove this attribute
 
 warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:93:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:12
    |
 LL | #![feature(rust1)]
    |            ^^^^^
@@ -245,7 +245,7 @@ LL | #![feature(rust1)]
    = note: `#[warn(stable_features)]` on by default
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:5
    |
 LL |     #[macro_use] fn f() { }
    |     ^^^^^^^^^^^^
@@ -257,913 +257,913 @@ LL | #![warn(unused_attributes, unknown_lints)]
    |         ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:187:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:188:5
    |
 LL |     #[macro_use] struct S;
    |     ^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5
    |
 LL |     #[macro_use] type T = S;
    |     ^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:5
    |
 LL |     #[macro_use] impl S { }
    |     ^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:200:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:17
    |
 LL |     mod inner { #![macro_export] }
    |                 ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5
    |
 LL |     #[macro_export] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:206:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:5
    |
 LL |     #[macro_export] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5
    |
 LL |     #[macro_export] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
    |
 LL |     #[macro_export] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1
    |
 LL | #[macro_export]
    | ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:17
    |
 LL |     mod inner { #![plugin_registrar] }
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5
    |
 LL |     #[plugin_registrar] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5
    |
 LL |     #[plugin_registrar] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:230:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
    |
 LL |     #[plugin_registrar] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:217:1
    |
 LL | #[plugin_registrar]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:243:17
    |
 LL |     mod inner { #![main] }
    |                 ^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:242:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:5
    |
 LL |     #[main] struct S;
    |     ^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:251:5
    |
 LL |     #[main] type T = S;
    |     ^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:254:5
    |
 LL |     #[main] impl S { }
    |     ^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:1
    |
 LL | #[main]
    | ^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:261:17
    |
 LL |     mod inner { #![start] }
    |                 ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:5
    |
 LL |     #[start] struct S;
    |     ^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:5
    |
 LL |     #[start] type T = S;
    |     ^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:272:5
    |
 LL |     #[start] impl S { }
    |     ^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:1
    |
 LL | #[start]
    | ^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:5
    |
 LL |     #[path = "3800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:322:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:328:5
    |
 LL |     #[path = "3800"]  struct S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:5
    |
 LL |     #[path = "3800"] type T = S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:328:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:5
    |
 LL |     #[path = "3800"] impl S { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:17
    |
 LL |     mod inner { #![automatically_derived] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
    |
 LL |     #[automatically_derived] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5
    |
 LL |     #[automatically_derived] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5
    |
 LL |     #[automatically_derived] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:5
    |
 LL |     #[automatically_derived] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:1
    |
 LL | #[automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:17
    |
 LL |     mod inner { #![no_link] }
    |                 ^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5
    |
 LL |     #[no_link] fn f() { }
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5
    |
 LL |     #[no_link] struct S;
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:5
    |
 LL |     #[no_link]type T = S;
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5
    |
 LL |     #[no_link] impl S { }
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:1
    |
 LL | #[no_link]
    | ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:17
    |
 LL |     mod inner { #![should_panic] }
    |                 ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5
    |
 LL |     #[should_panic] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5
    |
 LL |     #[should_panic] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5
    |
 LL |     #[should_panic] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5
    |
 LL |     #[should_panic] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:1
    |
 LL | #[should_panic]
    | ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:17
    |
 LL |     mod inner { #![ignore] }
    |                 ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5
    |
 LL |     #[ignore] fn f() { }
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:5
    |
 LL |     #[ignore] struct S;
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:5
    |
 LL |     #[ignore] type T = S;
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
    |
 LL |     #[ignore] impl S { }
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:1
    |
 LL | #[ignore]
    | ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:17
    |
 LL |     mod inner { #![no_implicit_prelude] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5
    |
 LL |     #[no_implicit_prelude] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:5
    |
 LL |     #[no_implicit_prelude] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:5
    |
 LL |     #[no_implicit_prelude] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
    |
 LL |     #[no_implicit_prelude] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:1
    |
 LL | #[no_implicit_prelude]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:443:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:449:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:449:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:440:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:478:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:17
    |
 LL |     mod inner { #![no_std] }
    |                 ^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:17
    |
 LL |     mod inner { #![no_std] }
    |                 ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:491:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:497:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:491:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:497:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:1
    |
 LL | #[no_std]
    | ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:1
    |
 LL | #[no_std]
    | ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:656:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:656:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:640:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:640:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:677:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:677:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:698:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:698:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:714:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:714:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1175,61 +1175,61 @@ LL | #![plugin_registrar]
    | ^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1
    |
 LL | #![macro_export]
    | ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
    |
 LL | #![main]
    | ^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1
    |
 LL | #![start]
    | ^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:57:1
    |
 LL | #![repr()]
    | ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:58:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
    |
 LL | #![path = "3800"]
    | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
    |
 LL | #![automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
    |
 LL | #![no_link]
    | ^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
 LL | #![should_panic]
    | ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
    |
 LL | #![ignore]
    | ^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1
    |
 LL | #![proc_macro_derive()]
    | ^^^^^^^^^^^^^^^^^^^^^^^
index 00737d8428b3da9c87be6e03aff4de9f15f6074b..0faa9090f4ebcfd898a632a1faf6d6dc6448d5be 100644 (file)
@@ -70,7 +70,3 @@ fn main() {
     // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
     // let _: &dyn Tr1<As1: Copy> = &S1;
 }
-
-macro_rules! accept_path { ($p:path) => {} }
-accept_path!(Iterator<Item: Ord>);
-//~^ ERROR associated type bounds are unstable
index a7ab7614d7b78c646dfc42c044f8e971baef3689..84af2a0163ae44dbc6948aa69624f88e7bfb11bc 100644 (file)
@@ -115,15 +115,6 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = note: for more information, see https://github.com/rust-lang/rust/issues/52662
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
-error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:75:23
-   |
-LL | accept_path!(Iterator<Item: Ord>);
-   |                       ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/52662
-   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
-
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
   --> $DIR/feature-gate-associated_type_bounds.rs:54:14
    |
@@ -148,7 +139,7 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    |
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
 
 Some errors have detailed explanations: E0562, E0658.
 For more information about an error, try `rustc --explain E0562`.
index c5b926d5af28c86c1cc1ade736b83cb358034075..8bec16a974e800930de77eeffc8010469254a8c5 100644 (file)
@@ -2,6 +2,3 @@ fn main() {
     let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
     println!("x: {}", x);
 }
-
-macro_rules! accept_pat { ($p:pat) => {} }
-accept_pat!(box 0); //~ ERROR box pattern syntax is experimental
index 1e47bd41e88705a7cc0f8330877fa5ddcc531cd5..d2dafe93a862fbc0d2291ea747cdf6d8a9718637 100644 (file)
@@ -7,15 +7,6 @@ LL |     let box x = Box::new('c');
    = note: for more information, see https://github.com/rust-lang/rust/issues/29641
    = help: add `#![feature(box_patterns)]` to the crate attributes to enable
 
-error[E0658]: box pattern syntax is experimental
-  --> $DIR/feature-gate-box_patterns.rs:7:13
-   |
-LL | accept_pat!(box 0);
-   |             ^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29641
-   = help: add `#![feature(box_patterns)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
index c23953a9e099e1dfa279390e63506790b6ea8aa9..778660cc0b54991d1b456e33f18095a108f091d3 100644 (file)
@@ -1,9 +1,6 @@
 // Test that the use of the box syntax is gated by `box_syntax` feature gate.
 
-#[cfg(FALSE)]
-fn foo() {
+fn main() {
     let x = box 3;
     //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead
 }
-
-fn main() {}
index cbafa50257706e53cb7efde0f8de5fd1360310ed..61b0534d2dc3ec129e0a193d8c16bc75969e72f5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
-  --> $DIR/feature-gate-box_syntax.rs:5:13
+  --> $DIR/feature-gate-box_syntax.rs:4:13
    |
 LL |     let x = box 3;
    |             ^^^^^
index 790bc33e2683e717e7138ba287ea8f8c35f4af1d..935f84b9163d38f9e599c96985fbefd4c87cbb34 100644 (file)
@@ -1,17 +1,17 @@
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics-ptr.rs:1:16
+  --> $DIR/feature-gate-const_generics-ptr.rs:1:22
    |
 LL | struct ConstFn<const F: fn()>;
-   |                ^^^^^^^^^^^^^
+   |                      ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics-ptr.rs:5:17
+  --> $DIR/feature-gate-const_generics-ptr.rs:5:23
    |
 LL | struct ConstPtr<const P: *const u32>;
-   |                 ^^^^^^^^^^^^^^^^^^^
+   |                       ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
index 0adc9902a6937462f490e2899006484868f81f22..fe1ded1c4bbc4bba7e8b86d954a113a51a1d59ad 100644 (file)
@@ -2,9 +2,4 @@ fn foo<const X: ()>() {} //~ ERROR const generics are unstable
 
 struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
 
-macro_rules! accept_item { ($i:item) => {} }
-accept_item! {
-    impl<const X: ()> A {} //~ ERROR const generics are unstable
-}
-
 fn main() {}
index f0154ed289f140c73d276444f301a4d5f681fabe..468e9c31d37e25a711aea94424e71eb6d77be513 100644 (file)
@@ -1,30 +1,21 @@
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics.rs:1:8
+  --> $DIR/feature-gate-const_generics.rs:1:14
    |
 LL | fn foo<const X: ()>() {}
-   |        ^^^^^^^^^^^
+   |              ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics.rs:3:12
+  --> $DIR/feature-gate-const_generics.rs:3:18
    |
 LL | struct Foo<const X: usize>([(); X]);
-   |            ^^^^^^^^^^^^^^
+   |                  ^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
-error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics.rs:7:10
-   |
-LL |     impl<const X: ()> A {}
-   |          ^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 7517fb280ea785487ba19b2ad2a3d67c40315848..0e3f6b168be6b602b8ced5181e712c7b26b6dde1 100644 (file)
@@ -5,7 +5,4 @@
     water: bool,
 }
 
-macro_rules! accept_vis { ($v:vis) => {} }
-accept_vis!(crate);  //~ ERROR `crate` visibility modifier is experimental
-
 fn main() {}
index b317872cea81729bdb872e7ed4630355f4290aa2..1e061eced3660620d718d3674ba843c628877dc8 100644 (file)
@@ -7,15 +7,6 @@ LL | crate struct Bender {
    = note: for more information, see https://github.com/rust-lang/rust/issues/53120
    = help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable
 
-error[E0658]: `crate` visibility modifier is experimental
-  --> $DIR/feature-gate-crate_visibility_modifier.rs:9:13
-   |
-LL | accept_vis!(crate);
-   |             ^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/53120
-   = help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
index b208a047481a4b35183ab4921e49712127f2bfcf..d002c5dbbd2db60129306fde7cb8ef9e37f3a557 100644 (file)
@@ -2,8 +2,4 @@
 
 macro m() {} //~ ERROR `macro` is experimental
 
-macro_rules! accept_item { ($i:item) => {} }
-accept_item! {
-    macro m() {} //~ ERROR `macro` is experimental
-}
 fn main() {}
index c6690ebd4d91779186143f076e2bf106fe350905..905a1b1531044f593c88ae0f03d2fd06193bda7b 100644 (file)
@@ -7,15 +7,6 @@ LL | macro m() {}
    = note: for more information, see https://github.com/rust-lang/rust/issues/39412
    = help: add `#![feature(decl_macro)]` to the crate attributes to enable
 
-error[E0658]: `macro` is experimental
-  --> $DIR/feature-gate-decl_macro.rs:7:5
-   |
-LL |     macro m() {}
-   |     ^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/39412
-   = help: add `#![feature(decl_macro)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
index 594ec73fe26f7954948392b138944aa7852e3133..ded08b93fe81c525cfa71480c39364fbe8cc84e6 100644 (file)
@@ -1,10 +1,6 @@
-#[cfg(FALSE)]
-fn foo() {
+pub fn main() {
     match 22 {
         0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
-        PATH .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
         _ => {}
     }
 }
-
-fn main() {}
index 075fdbed90d6c7b0c6ae58824c8591a5a28e47f6..ee20408d1781f2262f192e3d0cfa8afbea4cbc18 100644 (file)
@@ -1,21 +1,12 @@
 error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/feature-gate-exclusive-range-pattern.rs:4:11
+  --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9
    |
 LL |         0 .. 3 => {}
-   |           ^^
+   |         ^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/37854
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/feature-gate-exclusive-range-pattern.rs:5:14
-   |
-LL |         PATH .. 3 => {}
-   |              ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
index 8d7ecd27b450fd0e035304515b54674ee8a683b5..6fc38f45517ef74dc38864b8d00e0d4dc2b59548 100644 (file)
@@ -1,8 +1,5 @@
-#[cfg(FALSE)]
-pub fn foo() {
+pub fn main() {
     'a: { //~ ERROR labels on blocks are unstable
         break 'a;
     }
 }
-
-fn main() {}
index 6a861d3e04f92be31a72b983ecdf1564e65dc1f9..a417e0eec22f2fe07b3c16db2bf1cba462088a38 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: labels on blocks are unstable
-  --> $DIR/feature-gate-label_break_value.rs:3:5
+  --> $DIR/feature-gate-label_break_value.rs:2:5
    |
 LL |     'a: {
    |     ^^
index 4b94d7d6d3bdad3f8e879c319b025cd198d42701..819085adddade93a3820ac65550f5f24faf59d2c 100644 (file)
@@ -1,13 +1,4 @@
 trait Foo = Default;
 //~^ ERROR trait aliases are experimental
 
-macro_rules! accept_item {
-    ($i:item) => {}
-}
-
-accept_item! {
-    trait Foo = Ord + Eq;
-    //~^ ERROR trait aliases are experimental
-}
-
 fn main() {}
index b1bf6ad3491293ff9e809ddfbdb946f17e5dc05a..9250e27d15807eaec9a3131dfe62894bafbb6d2d 100644 (file)
@@ -7,15 +7,6 @@ LL | trait Foo = Default;
    = note: for more information, see https://github.com/rust-lang/rust/issues/41517
    = help: add `#![feature(trait_alias)]` to the crate attributes to enable
 
-error[E0658]: trait aliases are experimental
-  --> $DIR/feature-gate-trait-alias.rs:9:5
-   |
-LL |     trait Foo = Ord + Eq;
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/41517
-   = help: add `#![feature(trait_alias)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
index b451ba84a15654eec1efacbb552b8c614098cfc5..06cadd82c0731be8c263206d4e99176ab4bf17af 100644 (file)
@@ -1,12 +1,9 @@
 // compile-flags: --edition 2018
 
-#[cfg(FALSE)]
-fn foo() {
-    let try_result: Option<_> = try { //~ ERROR `try` blocks are unstable
+pub fn main() {
+    let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
         let x = 5;
         x
     };
     assert_eq!(try_result, Some(5));
 }
-
-fn main() {}
index 44a7d9b9043fd352e058e359e2fef94b1f8c550a..565f3610a2e21efdcf0e4448c70e5171a40ef9c9 100644 (file)
@@ -1,5 +1,5 @@
-error[E0658]: `try` blocks are unstable
-  --> $DIR/feature-gate-try_blocks.rs:5:33
+error[E0658]: `try` expression is experimental
+  --> $DIR/feature-gate-try_blocks.rs:4:33
    |
 LL |       let try_result: Option<_> = try {
    |  _________________________________^
index 655891d802c1ceda3cc54331dedd4bd8106e8262..7a597157300eddc32526f9d33c44565104b37b2a 100644 (file)
@@ -1,8 +1,5 @@
 // Type ascription is unstable
 
-#[cfg(FALSE)]
-fn foo() {
+fn main() {
     let a = 10: u8; //~ ERROR type ascription is experimental
 }
-
-fn main() {}
index d63d624c6c112bfd74ac6602f6196778dc51ec72..83f95529f0d9d3b6672be19a6438c45b214ffdf8 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: type ascription is experimental
-  --> $DIR/feature-gate-type_ascription.rs:5:13
+  --> $DIR/feature-gate-type_ascription.rs:4:13
    |
 LL |     let a = 10: u8;
    |             ^^^^^^
index 759fb170f90ddf1d4d925c1b6172a36b07c9d8e0..20c443b63d17532f459ee214223fedcbefe0e98a 100644 (file)
@@ -1,4 +1,4 @@
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals
 
 #![crate_type = "lib"]
index 4f43c2bb53847bddace7107c8529ac4c7a1bd2de..87ba488b5aef2459f3df3d79e0456112cdf5ea3c 100644 (file)
@@ -10,7 +10,7 @@
     |v: &mut u32| *v += 3,
     |v: &mut u32| *v += 4,
 ];
-fn func_specific() -> (fn() -> u32) {
+fn func_specific() -> fn() -> u32 {
     || return 42
 }
 
index b1a5cc67e86b368e4045a9c0768c70e360510f1f..f88687858fd1139b92a5b9a517b384cea2b6239a 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait)]
 
index 06c026180190a08ebb8998815f8e241c09f3277f..5f6778674dce13a5e9fd32e8ff61ff3c2bbef2bb 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait)]
 
index ab18be58155df89db560adfdf37305939c2a206c..71a68ff684af31c6656fb61cc9bd20ecafa0e7fa 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait)]
 
index e120cae7fdd148a822c2b6855de49206d6bb716f..e50ca5f54d19550121ad22bb551d51964a2c36be 100644 (file)
@@ -47,6 +47,6 @@ struct S1M<T> { val: S1k<S1k<T>> }
 
 fn main() {
     let fat: Option<S1M<S1M<S1M<u32>>>> = None;
-    //~^ ERROR the type `S32<S1M<S1M<u32>>>` is too big for the current architecture
+    //~^ ERROR is too big for the current architecture
 
 }
index 3447f358d85f12e393ba9212b02f61d0aef81a42..157eb3863203ae62d72f40e6b8e8ec9122106498 100644 (file)
@@ -4,6 +4,8 @@ fn macros() {
     macro_rules! foo{
         ($p:pat, $e:expr, $b:block) => {{
             if let $p = $e $b
+            //~^ WARN irrefutable if-let
+            //~| WARN irrefutable if-let
         }}
     }
     macro_rules! bar{
@@ -12,10 +14,10 @@ macro_rules! bar{
         }}
     }
 
-    foo!(a, 1, { //~ WARN irrefutable if-let
+    foo!(a, 1, {
         println!("irrefutable pattern");
     });
-    bar!(a, 1, { //~ WARN irrefutable if-let
+    bar!(a, 1, {
         println!("irrefutable pattern");
     });
 }
index f105098b74cf2e76f9d7ef1ba96eb41e99dc7049..83ab234cf04eab45e06933f4acf61e372b727db2 100644 (file)
@@ -23,7 +23,7 @@ LL | |     });
    | |_______- in this macro invocation
 
 warning: irrefutable if-let pattern
-  --> $DIR/if-let.rs:24:5
+  --> $DIR/if-let.rs:26:5
    |
 LL | /     if let a = 1 {
 LL | |         println!("irrefutable pattern");
@@ -31,7 +31,7 @@ LL | |     }
    | |_____^
 
 warning: irrefutable if-let pattern
-  --> $DIR/if-let.rs:28:5
+  --> $DIR/if-let.rs:30:5
    |
 LL | /     if let a = 1 {
 LL | |         println!("irrefutable pattern");
@@ -43,7 +43,7 @@ LL | |     }
    | |_____^
 
 warning: irrefutable if-let pattern
-  --> $DIR/if-let.rs:38:12
+  --> $DIR/if-let.rs:40:12
    |
 LL |       } else if let a = 1 {
    |  ____________^
@@ -52,7 +52,7 @@ LL | |     }
    | |_____^
 
 warning: irrefutable if-let pattern
-  --> $DIR/if-let.rs:44:12
+  --> $DIR/if-let.rs:46:12
    |
 LL |       } else if let a = 1 {
    |  ____________^
index b0a591b08ac897213bd0ae6b696b08e9ffd89664..d76cc41be4e5558bb1eae991c8edb866fef9a4b5 100644 (file)
@@ -1,16 +1,21 @@
+#![warn(unused_imports)]
+
 mod a {
     fn foo() {}
     mod foo {}
 
     mod a {
         pub use super::foo; //~ ERROR cannot be re-exported
-        pub use super::*; //~ ERROR must import something with the glob's visibility
+        pub use super::*;
+        //~^ WARNING glob import doesn't reexport anything because no candidate is public enough
     }
 }
 
 mod b {
     pub fn foo() {}
-    mod foo { pub struct S; }
+    mod foo {
+        pub struct S;
+    }
 
     pub mod a {
         pub use super::foo; // This is OK since the value `foo` is visible enough.
index af2c97e77b9d7ccb61221a2ecd91a63dc74fd372..4388e2c276b8ebbda2cc938f14eee86f1ce75251 100644 (file)
@@ -1,34 +1,40 @@
 error[E0364]: `foo` is private, and cannot be re-exported
-  --> $DIR/reexports.rs:6:17
+  --> $DIR/reexports.rs:8:17
    |
 LL |         pub use super::foo;
    |                 ^^^^^^^^^^
    |
 note: consider marking `foo` as `pub` in the imported module
-  --> $DIR/reexports.rs:6:17
+  --> $DIR/reexports.rs:8:17
    |
 LL |         pub use super::foo;
    |                 ^^^^^^^^^^
 
-error: A non-empty glob must import something with the glob's visibility
-  --> $DIR/reexports.rs:7:17
-   |
-LL |         pub use super::*;
-   |                 ^^^^^^^^
-
 error[E0603]: module `foo` is private
-  --> $DIR/reexports.rs:28:15
+  --> $DIR/reexports.rs:33:15
    |
 LL |     use b::a::foo::S;
    |               ^^^
 
 error[E0603]: module `foo` is private
-  --> $DIR/reexports.rs:29:15
+  --> $DIR/reexports.rs:34:15
    |
 LL |     use b::b::foo::S as T;
    |               ^^^
 
-error: aborting due to 4 previous errors
+warning: glob import doesn't reexport anything because no candidate is public enough
+  --> $DIR/reexports.rs:9:17
+   |
+LL |         pub use super::*;
+   |                 ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/reexports.rs:1:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0364, E0603.
 For more information about an error, try `rustc --explain E0364`.
index d131a944721d01fe7272d50f37736779338e8c19..eca9a67fcb387ec530c223b80b46e51bea192d50 100644 (file)
@@ -1,3 +1,5 @@
+// ignore-x86
+// ^ due to stderr output differences
 use std::ops::Deref;
 trait Trait {}
 
@@ -6,9 +8,9 @@ trait Trait {}
 impl Deref for Struct {
     type Target = dyn Trait;
     fn deref(&self) -> &dyn Trait {
+    //~^ ERROR `impl` item signature doesn't match `trait` item signature
         unimplemented!();
     }
 }
-//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter
 
 fn main() {}
index c1ec536ef43620da3c5a26a89b8caec29d222714..d3862e3d4df6092c366c253d61dc9a18ad4680d2 100644 (file)
@@ -1,21 +1,16 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
-  --> $DIR/mismatched_trait_impl-2.rs:8:5
+error: `impl` item signature doesn't match `trait` item signature
+  --> $DIR/mismatched_trait_impl-2.rs:10:5
    |
 LL |     fn deref(&self) -> &dyn Trait {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait
+   | 
+  ::: $SRC_DIR/libcore/ops/deref.rs:LL:COL
    |
-note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
-  --> $DIR/mismatched_trait_impl-2.rs:8:5
+LL |     fn deref(&self) -> &Self::Target;
+   |     --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static)
    |
-LL | /     fn deref(&self) -> &dyn Trait {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
-   = note: ...but the lifetime must also be valid for the static lifetime...
-   = note: ...so that the method type is compatible with trait:
-           expected fn(&Struct) -> &(dyn Trait + 'static)
-              found fn(&Struct) -> &dyn Trait
+   = note: expected `fn(&Struct) -> &(dyn Trait + 'static)`
+              found `fn(&Struct) -> &dyn Trait`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
index b5287f32a50451b57473e6823c2252c3f68e1e1f..c245d78ae828fc77f3f494a1c348a3fa3414a691 100644 (file)
@@ -1,25 +1,14 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
+error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/mismatched_trait_impl.rs:9:5
    |
+LL |     fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
+   |     ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
+...
 LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
    |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5...
-  --> $DIR/mismatched_trait_impl.rs:9:5
-   |
-LL | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-LL | |         x
-LL | |     }
-   | |_____^
-note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
-  --> $DIR/mismatched_trait_impl.rs:9:32
-   |
-LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-   |                                ^^
-   = note: ...so that the method type is compatible with trait:
-           expected fn(&i32, &'a u32, &u32) -> &'a u32
-              found fn(&i32, &u32, &u32) -> &u32
+   = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
+              found `fn(&i32, &u32, &u32) -> &u32`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
index f2ba81af9b63883185bbc4e6f43eba22f1e3e8c6..b9e02e967c126b6d48974e5a78d9d047709ba465 100644 (file)
@@ -6,7 +6,7 @@ trait Get {
 }
 
 impl Get for i32 {
-    fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
+    fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR `impl` item signature doesn't match
         x //~ ERROR lifetime mismatch
     }
 }
index 734ca0819e4166251a23eb6db5abcfff8bde2afd..bc302e91c1c518f0b0075ea0d4646c083796a79a 100644 (file)
@@ -1,24 +1,14 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
+error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/mismatched_trait_impl.rs:9:5
    |
+LL |     fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
+   |     ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
+...
 LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
    |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5...
-  --> $DIR/mismatched_trait_impl.rs:9:5
-   |
-LL | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-LL | |         x
-LL | |     }
-   | |_____^
-note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
-  --> $DIR/mismatched_trait_impl.rs:9:32
-   |
-LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-   |                                ^^
-   = note: ...so that the method type is compatible with trait:
-           expected fn(&i32, &'a u32, &u32) -> &'a u32
-              found fn(&i32, &u32, &u32) -> &u32
+   = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
+              found `fn(&i32, &u32, &u32) -> &u32`
 
 error[E0623]: lifetime mismatch
   --> $DIR/mismatched_trait_impl.rs:10:9
@@ -32,4 +22,3 @@ LL |         x
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0495`.
index b2dbf8b9190848ef69c0886ebb9becb71be116b7..fd20bd84edc464d7adef9522cbcd279de56df0ec 100644 (file)
@@ -1,4 +1,4 @@
-error: only foreign functions are allowed to be C-variadic
+error[E0743]: only foreign functions are allowed to be C-variadic
   --> $DIR/invalid-variadic-function.rs:1:26
    |
 LL | extern "C" fn foo(x: u8, ...);
@@ -12,3 +12,4 @@ LL | extern "C" fn foo(x: u8, ...);
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0743`.
index 29e974ad83d1e27079a740d0eee6b53a5a7dd294..0d95d168b3db3fdb388dfaa7909e8f570bf8ebc8 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 // Check that values are not leaked when a dtor panics (#14875)
 
index 9658f6980be2f82dea31255fc4d392b5347be572..9c53c1b86ceafd1cadf50aeac223a3445084f277 100644 (file)
@@ -5,10 +5,10 @@ LL | trait Trait: Sized {
    | ------------------ required by `Trait`
 ...
 LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found associated type
    |
-   = note: expected type `<<T as Trait>::A as MultiDispatch<i32>>::O`
-              found type `T`
+   = note: expected type `T`
+              found type `<<T as Trait>::A as MultiDispatch<i32>>::O`
    = note: you might be missing a type parameter or trait bound
 
 error: aborting due to previous error
index 5237a2f67bdd7036d2dd512eb72237b3294287c5..8ede8143ea6572a1b718fb0298ccde7248f6e1b9 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 use std::panic;
 
index 2a932db05af26142c2e2913699fecff765079fef..47c3ab59aa2eb9c2eba273f77eb142336a9cbc48 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 use std::panic;
 
index 40c3117f01ce904b6d03ef3e760464e4e952e0da..cca0995d4ca10bad7d3f33020e88de160fdf8b5a 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // compile-flags:--test -O
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #[test]
 #[should_panic(expected = "creating inhabited type")]
index a9cc99c79d01af7e05a5a8f87999a5c4f338cd1a..ef705946ad4443584af2dbfe722110acd1687187 100644 (file)
@@ -15,7 +15,6 @@ fn bar<'a>() {
     return;
 
     let _x = foo::<Vec<_>>(Vec::<&'a u32>::new());
-    //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477]
 }
 
 fn main() {}
index fdd285dcad2a13334a8484581bfd4fca3ab7a679..d6612035750836e49accc865a8f2d05dcaeb35b3 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 // only-32bit too impatient for 2⁶⁴ items
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C debug_assertions=yes -C opt-level=3
 
 use std::panic;
index b578999af8e948ed6cf29d6fd8b75d77318ad746..f1eded31702c4449d4ebf383127d13b251d84b81 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 // only-32bit too impatient for 2⁶⁴ items
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C debug_assertions=yes -C opt-level=3
 
 use std::panic;
index 3872a03b682592cabce8cf18b7cfc8a7a51d8091..5d67c7cbb42565e00898ee95cb7d5b155a201c7f 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C debug_assertions=yes
 
 use std::panic;
index 4a9e8cdb72e70bb7fac183549d792d85f47cabf7..ee4ab4d24c6ab22da3d6c2579bf01308c144c0cf 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C debug_assertions=yes
 
 use std::panic;
index 6bd1425e32465f05451fbba66d6891fd197c073e..429f8e0bc9648a61aeecc631e91202fce4770891 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: -C overflow-checks
 
 use std::panic;
diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs
new file mode 100644 (file)
index 0000000..2ce1a0f
--- /dev/null
@@ -0,0 +1,12 @@
+trait Foo {
+    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
+}
+
+impl Foo for () {
+    fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
+    //~^ ERROR `impl` item signature doesn't match `trait` item signature
+        if x > y { x } else { y }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
new file mode 100644 (file)
index 0000000..d07f305
--- /dev/null
@@ -0,0 +1,14 @@
+error: `impl` item signature doesn't match `trait` item signature
+  --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
+   |
+LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
+   |     ------------------------------------------- expected fn(&i32, &'a i32) -> &'a i32
+...
+LL |     fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32
+   |
+   = note: expected `fn(&i32, &'a i32) -> &'a i32`
+              found `fn(&i32, &i32) -> &i32`
+
+error: aborting due to previous error
+
index 811bc87eb0e2eee5afe81311b39301f29fa79d37..9f42b855a870d7b4e44abb0e86f4e23c3a6ef5a7 100644 (file)
@@ -13,6 +13,18 @@ fn bar(y: bool) -> X {
     return (X { y }); //~ ERROR unnecessary parentheses around `return` value
 }
 
+fn unused_parens_around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type
+    panic!()
+}
+
+trait Trait {
+    fn test(&self);
+}
+
+fn passes_unused_parens_lint() -> &'static (dyn Trait) {
+    panic!()
+}
+
 fn main() {
     foo();
     bar((true)); //~ ERROR unnecessary parentheses around function argument
index 83b247a4a60534ef7b8bc4aca0a0349367735e19..adc1069b64d62b98d3144f40d9419ba94047af6a 100644 (file)
@@ -16,26 +16,32 @@ error: unnecessary parentheses around `return` value
 LL |     return (X { y });
    |            ^^^^^^^^^ help: remove these parentheses
 
+error: unnecessary parentheses around type
+  --> $DIR/lint-unnecessary-parens.rs:16:42
+   |
+LL | fn unused_parens_around_return_type() -> (u32) {
+   |                                          ^^^^^ help: remove these parentheses
+
 error: unnecessary parentheses around function argument
-  --> $DIR/lint-unnecessary-parens.rs:18:9
+  --> $DIR/lint-unnecessary-parens.rs:30:9
    |
 LL |     bar((true));
    |         ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `if` condition
-  --> $DIR/lint-unnecessary-parens.rs:20:8
+  --> $DIR/lint-unnecessary-parens.rs:32:8
    |
 LL |     if (true) {}
    |        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `while` condition
-  --> $DIR/lint-unnecessary-parens.rs:21:11
+  --> $DIR/lint-unnecessary-parens.rs:33:11
    |
 LL |     while (true) {}
    |           ^^^^^^ help: remove these parentheses
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/lint-unnecessary-parens.rs:21:5
+  --> $DIR/lint-unnecessary-parens.rs:33:5
    |
 LL |     while (true) {}
    |     ^^^^^^^^^^^^ help: use `loop`
@@ -43,46 +49,46 @@ LL |     while (true) {}
    = note: `#[warn(while_true)]` on by default
 
 error: unnecessary parentheses around `match` head expression
-  --> $DIR/lint-unnecessary-parens.rs:23:11
+  --> $DIR/lint-unnecessary-parens.rs:35:11
    |
 LL |     match (true) {
    |           ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:26:16
+  --> $DIR/lint-unnecessary-parens.rs:38:16
    |
 LL |     if let 1 = (1) {}
    |                ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:27:19
+  --> $DIR/lint-unnecessary-parens.rs:39:19
    |
 LL |     while let 1 = (2) {}
    |                   ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around method argument
-  --> $DIR/lint-unnecessary-parens.rs:41:24
+  --> $DIR/lint-unnecessary-parens.rs:53:24
    |
 LL |     X { y: false }.foo((true));
    |                        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:43:18
+  --> $DIR/lint-unnecessary-parens.rs:55:18
    |
 LL |     let mut _a = (0);
    |                  ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:44:10
+  --> $DIR/lint-unnecessary-parens.rs:56:10
    |
 LL |     _a = (0);
    |          ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:45:11
+  --> $DIR/lint-unnecessary-parens.rs:57:11
    |
 LL |     _a += (1);
    |           ^^^ help: remove these parentheses
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
 
index 5320987040afc5818b58fc48d6c0cf5af566c50a..fa9f012c9262ca21575d80209543a4a60f971e1d 100644 (file)
@@ -28,6 +28,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
 fn main() {
     let Social_exchange_psychology = CheaterDetectionMechanism {};
-    //~^ WARN should have a snake case name such as
+    //~^ WARN should have a snake case name
+    //~| NOTE #[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]
     //~| NOTE people shouldn't have to change their usual style habits
+    //~| HELP convert the identifier to snake case
 }
index c145bd256d8f24b69cfd2b77632083b750b9ece9..79ffc82d32963ba83c50d40fe620802815cd6f29 100644 (file)
@@ -2,7 +2,7 @@
 #![warn(overflowing_literals)]
 
 fn main() {
-    let error = 255i8; //~WARNING literal out of range for i8
+    let error = 255i8; //~WARNING literal out of range for `i8`
 
     let ok = 0b1000_0001; // should be ok -> i32
     let ok = 0b0111_1111i8; // should be ok -> 127i8
index 6ec2af068018b11a37ece383424973eda30dd51c..3b00424d2f3fa1c996e912420b0e17f1a9c0fe38 100644 (file)
@@ -1,7 +1,7 @@
 // build-pass (FIXME(62277): could be check-pass?)
 #![warn(unused_imports)]
 
-use crate::foo::Bar; //~ WARNING first import
+use crate::foo::Bar;
 
 mod foo {
     pub type Bar = i32;
@@ -14,14 +14,14 @@ fn baz() -> Bar {
 mod m1 { pub struct S {} }
 mod m2 { pub struct S {} }
 
-use m1::*;
-use m2::*;
+use m1::*; //~ WARNING unused import
+use m2::*; //~ WARNING unused import
 
 fn main() {
-    use crate::foo::Bar; //~ WARNING redundant import
+    use crate::foo::Bar; //~ WARNING imported redundantly
     let _a: Bar = 3;
     baz();
 
-    use m1::S; //~ WARNING redundant import
+    use m1::S;
     let _s = S {};
 }
index 1c791bb1ca3d61f061c6f79668c3db65c620b82b..32cf59294e7603e7fc4d158c4be511a05f09bf24 100644 (file)
@@ -13,7 +13,7 @@
 // compile-flags: --test -C debug_assertions=yes
 // revisions: std core
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![cfg_attr(core, no_std)]
 
index c1a9d04e6d5cbbed68fc5cb2a153af6069570b07..1eca8c739040c64a939c48b8e4feb61d544d2f22 100644 (file)
@@ -1,8 +1,18 @@
 // build-pass (FIXME(62277): could be check-pass?)
 
-#[doc] //~ WARN attribute must be of the form
-#[ignore()] //~ WARN attribute must be of the form
-#[inline = ""] //~ WARN attribute must be of the form
-#[link] //~ WARN attribute must be of the form
-#[link = ""] //~ WARN attribute must be of the form
+#[doc]
+//~^ WARN attribute must be of the form
+//~| WARN this was previously accepted
+#[ignore()]
+//~^ WARN attribute must be of the form
+//~| WARN this was previously accepted
+#[inline = ""]
+//~^ WARN attribute must be of the form
+//~| WARN this was previously accepted
+#[link]
+//~^WARN attribute must be of the form
+//~| WARN this was previously accepted
+#[link = ""]
+//~^ WARN attribute must be of the form
+//~| WARN this was previously accepted
 fn main() {}
index 164668f562ce000db9b3a68d0d7b6afd18c1feb7..8f4e952338f8cb4cf9d25b7d53972c41a07c5f86 100644 (file)
@@ -9,7 +9,7 @@ LL | #[doc]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 warning: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]`
-  --> $DIR/malformed-regressions.rs:4:1
+  --> $DIR/malformed-regressions.rs:6:1
    |
 LL | #[ignore()]
    | ^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | #[ignore()]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 warning: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
-  --> $DIR/malformed-regressions.rs:5:1
+  --> $DIR/malformed-regressions.rs:9:1
    |
 LL | #[inline = ""]
    | ^^^^^^^^^^^^^^
@@ -27,7 +27,7 @@ LL | #[inline = ""]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...")]`
-  --> $DIR/malformed-regressions.rs:6:1
+  --> $DIR/malformed-regressions.rs:12:1
    |
 LL | #[link]
    | ^^^^^^^
@@ -36,7 +36,7 @@ LL | #[link]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...")]`
-  --> $DIR/malformed-regressions.rs:7:1
+  --> $DIR/malformed-regressions.rs:15:1
    |
 LL | #[link = ""]
    | ^^^^^^^^^^^^
index de8d958af45e34a144561acecba37cb6c7db61d4..6f13d5612ce51b93a333eaf4dfbcb558e68f5b17 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(fn_traits)]
 #![feature(never_type)]
index 2bc5cf1c976373b83721ac4a3e0648212bec3312..2949437b1e4b659db6463f812ae0239c8c6fdb5b 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 use std::cell::RefCell;
 use std::panic;
index 3aa5866ebfbeb7ff0114f4910cda46cb63e7bb81..0d7d2c0ed3fa9402eaf9c808572292fba19e3cb7 100644 (file)
@@ -1,7 +1,6 @@
 // Test that a variable of type ! can coerce to another type.
 
-// run-fail
-// error-pattern:explicit
+// check-pass
 
 #![feature(never_type)]
 
index 6218572f8a75651d27b009c6bc2ef8b99bb00c8a..9d355817ee80dc459ad86ebfce4f4a79d3d194ff 100644 (file)
@@ -1,7 +1,6 @@
 // Test that we can use a ! for an argument of type !
 
-// run-fail
-// error-pattern:wowzers!
+// check-pass
 
 #![feature(never_type)]
 #![allow(unreachable_code)]
index 46072e186e0f29e06f89a26fb2611af48918063c..0139ebe4640be6f3d91c0562290813cee17d9bae 100644 (file)
@@ -1,7 +1,6 @@
 // Test that we can explicitly cast ! to another type
 
-// run-fail
-// error-pattern:explicit
+// check-pass
 
 #![feature(never_type)]
 
index 7f0a3fef6a99a49c80fc40e747c13fb09e53e3c5..3bb917c931635299e302860d646009d68d97b207 100644 (file)
@@ -1,7 +1,6 @@
 // Test that we can use ! as an associated type.
 
-// run-fail
-// error-pattern:kapow!
+// check-pass
 
 #![feature(never_type)]
 
index a82d351f6cf2b37b7873428fe3edf98cf2a92e0d..13cd59e6aa9f138e6982af760e32cfe9ecf51eb8 100644 (file)
@@ -1,7 +1,6 @@
 // Test that we can use ! as an argument to a trait impl.
 
-// run-fail
-// error-pattern:oh no!
+// check-pass
 
 #![feature(never_type)]
 
index 72b844d8b4886d366a4a81eea4bc2e2d792365d8..e0c30160b9e94be9ff2ceb286ad6d04151e26029 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results
 // in a runtime panic.
 
index c1959866e5c257ceea998dfd25c57324f2ff7bab..e9927304f23f8c380a0f1c9ea5fa0d76a79e2536 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 // compile-flags: -C debug_assertions=yes
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // ignore-emscripten dies with an LLVM error
 
 use std::panic;
diff --git a/src/test/ui/offset_from.rs b/src/test/ui/offset_from.rs
new file mode 100644 (file)
index 0000000..cbbb2ad
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(ptr_offset_from)]
+
+fn main() {
+    let mut a = [0; 5];
+    let ptr1: *mut i32 = &mut a[1];
+    let ptr2: *mut i32 = &mut a[3];
+    unsafe {
+        assert_eq!(ptr2.offset_from(ptr1), 2);
+        assert_eq!(ptr1.offset_from(ptr2), -2);
+        assert_eq!(ptr1.offset(2), ptr2);
+        assert_eq!(ptr2.offset(-2), ptr1);
+    }
+}
index 9667711242ce61d57d9594051811c1bde10c98fd..5fe72caf9c1ff7a9c3ee401a76dd4f6ab8e86761 100644 (file)
@@ -4,7 +4,6 @@
 // check-pass
 
 #![feature(or_patterns)]
-#![feature(box_patterns)]
 
 fn main() {}
 
index 6dcb852a3669f66f31cf49db429d4ea5f83c9f16..5d72771c2dcff1bdff532ec1214b0acb67daa901 100644 (file)
@@ -4,7 +4,7 @@
 // aux-build:wants-panic-runtime-abort.rs
 // aux-build:panic-runtime-lang-items.rs
 // error-pattern: is not compiled with this crate's panic strategy `unwind`
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![no_std]
 #![no_main]
index e7811d40b5b9a74f1e3bf1be6df673eeaa58c207..4c25c09d6438f3146ca04a355be849481707add5 100644 (file)
@@ -1,7 +1,7 @@
 // error-pattern:is incompatible with this crate's strategy of `unwind`
 // aux-build:panic-runtime-abort.rs
 // aux-build:panic-runtime-lang-items.rs
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![no_std]
 #![no_main]
index 44671796c01a3e37b4cc77f50806e4c4fc189e58..478af451e7f657bbd73ecceb3ca5b180027019ca 100644 (file)
@@ -2,7 +2,7 @@
 // aux-build:panic-runtime-abort.rs
 // aux-build:wants-panic-runtime-abort.rs
 // aux-build:panic-runtime-lang-items.rs
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![no_std]
 #![no_main]
index 6b8c146949aecc5916581e1fe1760d4f55ca480a..2f03160430a22fa4df6befd3495e0f3a5cab158a 100644 (file)
@@ -4,6 +4,7 @@ fn main() {
     match 0 {
         (.. PAT) => {}
         //~^ ERROR `..X` range patterns are not supported
+        //~| ERROR exclusive range pattern syntax is experimental
     }
 }
 
index 1962dc4ff20a87d29016b3894f14dc373e105c62..af3ecce1846497d485d7ad5bf0671d593b79cc9e 100644 (file)
@@ -4,8 +4,17 @@ error: `..X` range patterns are not supported
 LL |         (.. PAT) => {}
    |          ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
 
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/pat-tuple-4.rs:5:10
+   |
+LL |         (.. PAT) => {}
+   |          ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-4.rs:10:30
+  --> $DIR/pat-tuple-4.rs:11:30
    |
 LL | const RECOVERY_WITNESS: () = 0;
    |                              ^ expected (), found integer
@@ -13,6 +22,7 @@ LL | const RECOVERY_WITNESS: () = 0;
    = note: expected type `()`
               found type `{integer}`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
index 17155b4dd49544050eb5772e3d2b4347bde3cc16..09ebdc29a21613cbe0dc25278324d6678f593d2d 100644 (file)
@@ -5,10 +5,10 @@ LL |         (PAT ..) => {}
    |          ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
 
 error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-5.rs:5:14
+  --> $DIR/pat-tuple-5.rs:5:10
    |
 LL |         (PAT ..) => {}
-   |              ^^
+   |          ^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/37854
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
index 8ea4d194396faa0082cd2598cab38d97d9e46829..aeeebdb991483ddcb68249df2f32ee1317431b39 100644 (file)
@@ -1,4 +1,4 @@
-error: only foreign functions are allowed to be C-variadic
+error[E0743]: only foreign functions are allowed to be C-variadic
   --> $DIR/variadic-ffi-3.rs:1:18
    |
 LL | fn foo(x: isize, ...) {
@@ -6,3 +6,4 @@ LL | fn foo(x: isize, ...) {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0743`.
index 69fbf84869c13bf7ad809dc6ab54f6c0bc21fae4..da83276c72dd109f682c5224a20a23e5e64754d9 100644 (file)
@@ -1,4 +1,4 @@
-error: only foreign functions are allowed to be C-variadic
+error[E0743]: only foreign functions are allowed to be C-variadic
   --> $DIR/variadic-ffi-4.rs:1:29
    |
 LL | extern "C" fn foo(x: isize, ...) {
@@ -6,3 +6,4 @@ LL | extern "C" fn foo(x: isize, ...) {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0743`.
index 45b31f6125374254c69dcecb8879fc1c4bebe8f5..9656a0b5de9ce1afa46a4590e271f6e51ec3c5c5 100644 (file)
@@ -3,8 +3,6 @@
 
 // check-pass
 
-#![feature(box_patterns)]
-
 fn main() {}
 
 macro_rules! accept_pat {
index 5c6834459f0d4021538bb4f5f6ca5d4b5f9fe80f..349ba11a7cdffd096166f47a9f1be5080c2b8fbb 100644 (file)
@@ -32,14 +32,14 @@ fn main() {
 
     match 10 {
         1..10 => {},
-        8..=9 => {}, //~ WARNING multiple patterns covering the same range
+        8..=9 => {}, //~ WARNING unreachable pattern
         _ => {},
     }
 
     match 10 {
         5..7 => {},
         6 => {}, //~ WARNING unreachable pattern
-        1..10 => {}, //~ WARNING multiple patterns covering the same range
+        1..10 => {},
         9..=9 => {}, //~ WARNING unreachable pattern
         6 => {}, //~ WARNING unreachable pattern
         _ => {},
index 9741f3b6d0d410e7ee77fe4d297b9cf215c3cae4..40aa47a7246c40455dbf381cd4a6f4a898ba0a1e 100644 (file)
@@ -340,7 +340,10 @@ LL |     pub type Alias<T: PrivTr> = T;
    |                       ^^^^^^
    |
    = note: `#[warn(type_alias_bounds)]` on by default
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL |     pub type Alias<T> = T;
+   |                    --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/private-in-public-warn.rs:75:29
@@ -348,7 +351,10 @@ warning: where clauses are not enforced in type aliases
 LL |     pub type Alias<T> where T: PrivTr = T;
    |                             ^^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL |     pub type Alias<T>  = T;
+   |                      --
 
 error: aborting due to 36 previous errors
 
index 61effc463e98fc76d415a3812b15220fbefb90d1..54fee085ee943dfc7bfd6953b88562f9bf8feb67 100644 (file)
@@ -1,4 +1,4 @@
-error: visibilities can only be restricted to ancestor modules
+error[E0742]: visibilities can only be restricted to ancestor modules
   --> $DIR/relative-2018.rs:7:12
    |
 LL |     pub(in ::core) struct S4;
@@ -14,3 +14,4 @@ LL |     pub(in a::b) struct S5;
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0742`.
index a23973d0853f137f22d999a5706de5f3689363b5..e6a61fbefb0d80dd87ea7195bc2b5a5068dedb02 100644 (file)
@@ -4,7 +4,7 @@ error[E0433]: failed to resolve: maybe a missing crate `bad`?
 LL |     pub(in bad::path) mod m1 {}
    |            ^^^ maybe a missing crate `bad`?
 
-error: visibilities can only be restricted to ancestor modules
+error[E0742]: visibilities can only be restricted to ancestor modules
   --> $DIR/test.rs:51:12
    |
 LL |     pub(in foo) mod m2 {}
@@ -78,5 +78,5 @@ LL |     u.h();
 
 error: aborting due to 12 previous errors
 
-Some errors have detailed explanations: E0364, E0433, E0603, E0616, E0624.
+Some errors have detailed explanations: E0364, E0433, E0603, E0616, E0624, E0742.
 For more information about an error, try `rustc --explain E0364`.
index 690a76ef3e0afe8a0c9531355bfe78db3abd5056..418178d0f0ead071c24efda048d43721ac535eec 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // aux-build:expand-with-a-macro.rs
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![deny(warnings)]
 
index 28c61a2f52fed141c7473be7fc6221c9a31060a6..6b8724457a6a3621bc2b3dd1fdb6795f713aa909 100644 (file)
@@ -1,4 +1,4 @@
-error: visibilities can only be restricted to ancestor modules
+error[E0742]: visibilities can only be restricted to ancestor modules
   --> $DIR/issue-50493.rs:8:12
    |
 LL |     pub(in restricted) field: usize,
@@ -12,4 +12,5 @@ LL | #[derive(Derive)]
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0616`.
+Some errors have detailed explanations: E0616, E0742.
+For more information about an error, try `rustc --explain E0616`.
index 596264ba16b424ef82d282278f86d1d12766e078..56ff104b4fed914a75f97f4ab71d1a759bc227e9 100644 (file)
@@ -53,7 +53,7 @@ LL | pub (xyz) fn xyz() {}
            `pub(super)`: visible only in the current module's parent
            `pub(in path::to::module)`: visible only on the specified path
 
-error: visibilities can only be restricted to ancestor modules
+error[E0742]: visibilities can only be restricted to ancestor modules
   --> $DIR/pub-restricted.rs:25:17
    |
 LL |         pub (in x) non_parent_invalid: usize,
@@ -61,4 +61,5 @@ LL |         pub (in x) non_parent_invalid: usize,
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0704`.
+Some errors have detailed explanations: E0704, E0742.
+For more information about an error, try `rustc --explain E0704`.
index 26c51efea1e1ca8ed7310f741aece8cb5c3bffc4..f1e53a0d8b4266658134f0953db9b546126ee211 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // aux-build:reachable-unnameable-items.rs
 
 extern crate reachable_unnameable_items;
index 7f22ae23b8500a39ecba0b0b89fe3619ab8cda3e..0d59f44584c99c1eb2b2eb290b7dd2f51697aa29 100644 (file)
@@ -13,7 +13,7 @@ struct Foo<'a> {
         x: &'a i32,
     }
     struct Bar<'a,'b> {
-        f: &'a Foo<'b> //~ ERROR reference has a longer lifetime
+        f: &'a Foo<'b>
     }
 }
 
index 367f7a30201577963523e9815fbcfae29d01f5ed..cf0d96ba7ed4a3c03669621f7836e33cf4b6843e 100644 (file)
@@ -13,7 +13,7 @@ struct Foo<T> {
         x: fn(T)
     }
     struct Bar<'a,'b> {
-        f: &'a Foo<&'b i32> //~ ERROR reference has a longer lifetime
+        f: &'a Foo<&'b i32>
     }
 }
 
index f780275b684d18e374eee270d1745f8defb25884..069fc5dd0085abd6cad9a20831215715e3dc41b8 100644 (file)
@@ -13,7 +13,7 @@ struct Foo<T> {
         x: T
     }
     struct Bar<'a,'b> {
-        f: &'a Foo<&'b i32> //~ ERROR reference has a longer lifetime
+        f: &'a Foo<&'b i32>
     }
 }
 
index f047e16bc0b948c642b56c521835cc33e4d3bf4d..b3cb83f94e053c82dd8c4eb97bff0dbe74807ff2 100644 (file)
@@ -52,6 +52,6 @@ impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
 //~^ ERROR Implementations of Drop cannot be specialized
 
 impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
-//~^ ERROR cannot infer an appropriate lifetime
+//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw`
 
 pub fn main() { }
index d2fb7c7a9e69d47ee5b77be962d0c35816aa4e43..197ecf0cb003916b08e785074ec7dbaaae87b02e 100644 (file)
@@ -10,7 +10,7 @@ error[E0577]: expected module, found trait `Tr`
 LL | pub(in Tr) struct Z;
    |        ^^ not a module
 
-error: visibilities can only be restricted to ancestor modules
+error[E0742]: visibilities can only be restricted to ancestor modules
   --> $DIR/resolve-bad-visibility.rs:6:8
    |
 LL | pub(in std::vec) struct F;
@@ -30,4 +30,5 @@ LL | pub(in too_soon) struct H;
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0433`.
+Some errors have detailed explanations: E0433, E0577, E0742.
+For more information about an error, try `rustc --explain E0433`.
index b9678291ee40b2b469ddffb8e1f663077ea477ae..84d82ce8522400f44740b1d49219f25c57e7fe7f 100644 (file)
@@ -12,3 +12,4 @@ LL | foo!();
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0578`.
index c8e8b9dcfc6a7e6788aa2b43c0e73d20b8272214..0bd7bf3d51a78d01db1a8e86ebe49ad811f40c3b 100644 (file)
@@ -1,7 +1,7 @@
 // compile-flags: --test
 // run-pass
 
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(test)]
 
index b10b6ec11b53a346f19d47a7cdb891a5a19664b0..7923aa7c0e22f31affe992fabc45afaa67d844f9 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 
 #![allow(dead_code, unreachable_code)]
 
diff --git a/src/test/ui/save-analysis/issue-65590.rs b/src/test/ui/save-analysis/issue-65590.rs
new file mode 100644 (file)
index 0000000..27874f8
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+// compile-flags: -Zsave-analysis
+// edition:2018
+
+// Async desugaring for return types in (associated) functions introduces a
+// separate definition internally, which we need to take into account
+// (or else we ICE).
+trait Trait { type Assoc; }
+struct Struct;
+
+async fn foobar<T: Trait>() -> T::Assoc {
+    unimplemented!()
+}
+
+impl Struct {
+    async fn foo<T: Trait>(&self) -> T::Assoc {
+        unimplemented!()
+    }
+}
+
+fn main() {}
index 350bc434935b33c5c909f68869b162b06ba69997..dd5551d28441dff26a833527ed9e263f6c50c424 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 // ignore-emscripten
 // min-llvm-version 7.0
-// error-pattern: panicked
 
 // Test that the simd_f{min,max} intrinsics produce the correct results.
 
index 89607af260a5258e795576acac33b085c34204fd..0f26a975a370f30963a4078afc7f8e51433fbfcf 100644 (file)
@@ -15,7 +15,7 @@ fn october<'b, T>(s: &'b T) -> &'b T {
     s
 }
 
-fn november<'a>(s: &'a str) -> (&'a str) {
+fn november<'a>(s: &'a str) -> &'a str {
     //~^ ERROR lifetime parameter `'b` never used
     //~| HELP elide the unused lifetime
     s
index be0bdb9b6285102ea40b2d906e6eec041595ef95..7f9504fe5a90a5f3156c779a9caa141b5254f6df 100644 (file)
@@ -15,7 +15,7 @@ fn october<'a, 'b, T>(s: &'b T) -> &'b T {
     s
 }
 
-fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+fn november<'a, 'b>(s: &'a str) -> &'a str {
     //~^ ERROR lifetime parameter `'b` never used
     //~| HELP elide the unused lifetime
     s
index 2ccba796d4229ebe319526d3280ee26057a72bea..b9c3bd89748fff17879ba018a07cb0bbd2b0e8a3 100644 (file)
@@ -21,7 +21,7 @@ LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T {
 error: lifetime parameter `'b` never used
   --> $DIR/zero-uses-in-fn.rs:18:17
    |
-LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+LL | fn november<'a, 'b>(s: &'a str) -> &'a str {
    |               --^^
    |               |
    |               help: elide the unused lifetime
index c2f0711b0c8665295105b31ab2a187787762b504..d3fa1d7732e726a98ff62306663fcff3de0a9a08 100644 (file)
@@ -18,3 +18,4 @@ LL |     m!{ m<> }
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0577`.
index 55b743ab7c7ea315b3527e0f1002e3d3060356e3..1a478460efc6c8954c6714450b848652cd700a85 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: --test
 #![feature(allow_fail)]
 
index 2284953fbbe947365182df835157d8ce835eee35..9fa759f9eb4837a25ff0b215cba976b78f849412 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// ignore-emscripten compiled with panic=abort by default
+// ignore-wasm32-bare compiled with panic=abort by default
 // compile-flags: --test
 #[test]
 #[should_panic(expected = "foo")]
index 0eb0769c5707103405a16c596145d1260885defe..cb8bad6d9e74dbf227319eb17fa748e64a45f9f6 100644 (file)
@@ -31,7 +31,10 @@ LL | type Y where i32: Foo = ();
    |              ^^^^^^^^
    |
    = note: `#[warn(type_alias_bounds)]` on by default
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type Y  = ();
+   |       --
 
 warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
   --> $DIR/trivial-bounds-inconsistent.rs:22:19
diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-on-option-diagnostics.rs
new file mode 100644 (file)
index 0000000..65d5e29
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(try_trait)]
+// edition:2018
+fn main() {}
+
+fn a_function() -> u32 {
+    let x: Option<u32> = None;
+    x?; //~ ERROR the `?` operator
+    22
+}
+
+fn a_closure() -> u32 {
+    let a_closure = || {
+        let x: Option<u32> = None;
+        x?; //~ ERROR the `?` operator
+        22
+    };
+    a_closure()
+}
diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr
new file mode 100644 (file)
index 0000000..4dd515e
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-diagnostics.rs:7:5
+   |
+LL |     x?;
+   |     ^^ cannot use the `?` operator in a function that returns `u32`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `u32`
+   = note: required by `std::ops::Try::from_error`
+
+error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-diagnostics.rs:14:9
+   |
+LL |         x?;
+   |         ^^ cannot use the `?` operator in a closure that returns `{integer}`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `{integer}`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index dbb7b92563ab86c49dc21cbac28480d0e50a3662..c381d30c64f14326462f178b445cd537fe85c5fa 100644 (file)
@@ -5,7 +5,10 @@ LL | type SVec<T: Send + Send> = Vec<T>;
    |              ^^^^   ^^^^
    |
    = note: `#[warn(type_alias_bounds)]` on by default
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type SVec<T> = Vec<T>;
+   |     --    --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:10:21
@@ -13,7 +16,10 @@ warning: where clauses are not enforced in type aliases
 LL | type S2Vec<T> where T: Send = Vec<T>;
    |                     ^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type S2Vec<T>  = Vec<T>;
+   |              --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:12:19
@@ -21,7 +27,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
    |                   ^^   ^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>);
+   |            --  --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:14:18
@@ -29,7 +38,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
    |                  ^^   ^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type WVec<'b, T> = (&'b u32, Vec<T>);
+   |           --  --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:16:25
@@ -37,7 +49,10 @@ warning: where clauses are not enforced in type aliases
 LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
    |                         ^^^^^  ^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type W2Vec<'b, T>  = (&'b u32, Vec<T>);
+   |                  --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:47:12
@@ -45,12 +60,15 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type T1<U: Bound> = U::Assoc;
    |            ^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
 help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
   --> $DIR/type-alias-bounds.rs:47:21
    |
 LL | type T1<U: Bound> = U::Assoc;
    |                     ^^^^^^^^
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type T1<U> = U::Assoc;
+   |         --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:48:18
@@ -58,12 +76,15 @@ warning: where clauses are not enforced in type aliases
 LL | type T2<U> where U: Bound = U::Assoc;
    |                  ^^^^^^^^
    |
-   = help: the clause will not be checked when the type alias is used, and should be removed
 help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
   --> $DIR/type-alias-bounds.rs:48:29
    |
 LL | type T2<U> where U: Bound = U::Assoc;
    |                             ^^^^^^^^
+help: the clause will not be checked when the type alias is used, and should be removed
+   |
+LL | type T2<U>  = U::Assoc;
+   |           --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:56:12
@@ -71,7 +92,10 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type T5<U: Bound> = <U as Bound>::Assoc;
    |            ^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type T5<U> = <U as Bound>::Assoc;
+   |         --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:57:12
@@ -79,5 +103,8 @@ warning: bounds on generic parameters are not enforced in type aliases
 LL | type T6<U: Bound> = ::std::vec::Vec<U>;
    |            ^^^^^
    |
-   = help: the bound will not be checked when the type alias is used, and should be removed
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | type T6<U> = ::std::vec::Vec<U>;
+   |         --
 
index 53babefae81c09df44a687c4e2c1c0939c43b814..cfbf7565cb6c82d7b8b298f29b835afa795570f3 100644 (file)
@@ -5,6 +5,8 @@ fn macros() {
     macro_rules! foo{
         ($p:pat, $e:expr, $b:block) => {{
             while let $p = $e $b
+            //~^ WARN irrefutable while-let
+            //~| WARN irrefutable while-let
         }}
     }
     macro_rules! bar{
@@ -13,10 +15,10 @@ macro_rules! bar{
         }}
     }
 
-    foo!(_a, 1, { //~ WARN irrefutable while-let
+    foo!(_a, 1, {
         println!("irrefutable pattern");
     });
-    bar!(_a, 1, { //~ WARN irrefutable while-let
+    bar!(_a, 1, {
         println!("irrefutable pattern");
     });
 }
index 30307ecaeadf244faf12bfcd8aa67f7262c54c57..172874ad5fc5c603ea1c3c33585770bf21e3bba6 100644 (file)
@@ -23,7 +23,7 @@ LL | |     });
    | |_______- in this macro invocation
 
 warning: irrefutable while-let pattern
-  --> $DIR/while-let.rs:25:5
+  --> $DIR/while-let.rs:27:5
    |
 LL | /     while let _a = 1 {
 LL | |         println!("irrefutable pattern");
index 2a189a92f4b129825aafed07a8e0103aaf5b9253..fca57eec79fc65029d4fecf73bf58eb20cb813c0 100644 (file)
@@ -91,7 +91,9 @@
     "mips-unknown-linux-gnu",
     "mips-unknown-linux-musl",
     "mips64-unknown-linux-gnuabi64",
+    "mips64-unknown-linux-muslabi64",
     "mips64el-unknown-linux-gnuabi64",
+    "mips64el-unknown-linux-muslabi64",
     "mipsisa32r6-unknown-linux-gnu",
     "mipsisa32r6el-unknown-linux-gnu",
     "mipsisa64r6-unknown-linux-gnuabi64",
index 3ba5f27170db10af7a92f2b682e049397197b8fa..5da4b4d47963868d9878480197581ccbbdaece74 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3ba5f27170db10af7a92f2b682e049397197b8fa
+Subproject commit 5da4b4d47963868d9878480197581ccbbdaece74
index 66df92aeba64547f3e9600635a30df34b12a11d8..c8e3cfbdd997839c771ca32c7ac860fe95149a04 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 66df92aeba64547f3e9600635a30df34b12a11d8
+Subproject commit c8e3cfbdd997839c771ca32c7ac860fe95149a04
index 03094885065847b8a7f9624af9a1d9fe5e9ef647..d750595e272cffa0129cd08479ecbd27a0e47d0c 100644 (file)
@@ -141,10 +141,6 @@ pub fn from_file(config: &Config, testfile: &Path) -> Self {
                 if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) {
                     props.ignore = Ignore::Ignore;
                 }
-                // FIXME: Re-enable run-fail once panics are handled correctly
-                if config.target.contains("emscripten") && config.mode == common::RunFail {
-                    props.ignore = Ignore::Ignore;
-                }
             }
 
             if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) &&
index ea31f37c7a52b7c44a756d088a9c288b39f481d2..a9acc9733c19ead03713f28cd0ab2f5ce448a8cc 100644 (file)
@@ -3137,6 +3137,10 @@ fn run_ui_test(&self) {
                     self.fatal_proc_rec("test run succeeded!", &proc_res);
                 }
             }
+            if !self.props.error_patterns.is_empty() {
+                // "// error-pattern" comments
+                self.check_error_patterns(&proc_res.stderr, &proc_res);
+            }
         }
 
         debug!("run_ui_test: explicit={:?} config.compare_mode={:?} expected_errors={:?} \
@@ -3144,14 +3148,13 @@ fn run_ui_test(&self) {
                explicit, self.config.compare_mode, expected_errors, proc_res.status,
                self.props.error_patterns);
         if !explicit && self.config.compare_mode.is_none() {
-            if !proc_res.status.success() {
-                if !self.props.error_patterns.is_empty() {
-                    // "// error-pattern" comments
-                    self.check_error_patterns(&proc_res.stderr, &proc_res);
-                } else {
-                    // "//~ERROR comments"
-                    self.check_expected_errors(expected_errors, &proc_res);
-                }
+            if !self.should_run() && !self.props.error_patterns.is_empty() {
+                // "// error-pattern" comments
+                self.check_error_patterns(&proc_res.stderr, &proc_res);
+            }
+            if !expected_errors.is_empty() {
+                // "//~ERROR comments"
+                self.check_expected_errors(expected_errors, &proc_res);
             }
         }
 
index d9ae0285169e52050416fb3618f05b5fdf582b6b..d4e4fe71e6a9568f5d081d99f1c621c5a4ddd7db 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d9ae0285169e52050416fb3618f05b5fdf582b6b
+Subproject commit d4e4fe71e6a9568f5d081d99f1c621c5a4ddd7db
index a18df16181947edd5eb593ea0f2321e0035448ee..5db91c7b94ca81eead6b25bcf6196b869a44ece0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a18df16181947edd5eb593ea0f2321e0035448ee
+Subproject commit 5db91c7b94ca81eead6b25bcf6196b869a44ece0
index a7188f0d11eac264ff3eba66eeffe7e05b4bee2a..89bbde4d5a9e3069122aff148bc478c7adb57eca 100644 (file)
@@ -13,6 +13,11 @@ clap = "2.25.0"
 failure = "0.1"
 mdbook-linkcheck = { version = "0.3.0", optional = true }
 
+# A noop dependency that changes in the Rust repository, it's a bit of a hack.
+# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
+# for more information.
+rustc-workspace-hack = "1.0.0"
+
 [dependencies.mdbook]
 version = "0.3.0"
 default-features = false
index a78cbdc2c4c6afb0fa31909496d0a1db949521b1..285af038a1ef45438ae0c14961d59fe286f6e58c 100644 (file)
@@ -64,7 +64,7 @@ serde = { version = "1.0.82", features = ['derive'] }
 serde_json = { version = "1.0.31", features = ["raw_value"] }
 smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
 url = { version = "2.0", features = ['serde'] }
-
+syn = { version = "0.15", features = ['full'] }
 
 [target.'cfg(not(windows))'.dependencies]
 openssl = { version = "0.10.12", optional = true }
index 159baff184d1be900e530cef616243c79c6d6063..bd58de81c778a0287402c77bda52a7248c2f9c8c 100644 (file)
@@ -40,7 +40,6 @@
     "E0514",
     "E0519",
     "E0523",
-    "E0526",
     "E0554",
     "E0570",
     "E0629",