]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #86887 - jyn514:cleanup-clean, r=CraftSpider
authorYuki Okushi <jtitor@2k36.org>
Mon, 12 Jul 2021 23:54:31 +0000 (08:54 +0900)
committerGitHub <noreply@github.com>
Mon, 12 Jul 2021 23:54:31 +0000 (08:54 +0900)
rustdoc: remove dead code in `clean`

Builds on https://github.com/rust-lang/rust/pull/86886 and should not be merged before.

921 files changed:
.mailmap
Cargo.lock
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/util/comments/tests.rs
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_pretty/src/pprust/tests.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_builtin_macros/src/lib.rs
compiler/rustc_codegen_cranelift/.cirrus.yml
compiler/rustc_codegen_cranelift/.github/workflows/main.yml
compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
compiler/rustc_codegen_cranelift/.gitignore
compiler/rustc_codegen_cranelift/.vscode/settings.json
compiler/rustc_codegen_cranelift/Cargo.lock
compiler/rustc_codegen_cranelift/Cargo.toml
compiler/rustc_codegen_cranelift/Readme.md
compiler/rustc_codegen_cranelift/build.sh [deleted file]
compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh [deleted file]
compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh [deleted file]
compiler/rustc_codegen_cranelift/build_system/build_backend.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/config.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/prepare.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/rustc_info.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/utils.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/clean_all.sh
compiler/rustc_codegen_cranelift/config.txt [new file with mode: 0644]
compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch [deleted file]
compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch [deleted file]
compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch [deleted file]
compiler/rustc_codegen_cranelift/docs/usage.md
compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
compiler/rustc_codegen_cranelift/example/std_example.rs
compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch [deleted file]
compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch [deleted file]
compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch [deleted file]
compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/prepare.sh [deleted file]
compiler/rustc_codegen_cranelift/rust-toolchain
compiler/rustc_codegen_cranelift/scripts/cargo.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/scripts/cargo.sh [deleted file]
compiler/rustc_codegen_cranelift/scripts/config.sh
compiler/rustc_codegen_cranelift/scripts/ext_config.sh
compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
compiler/rustc_codegen_cranelift/scripts/rustup.sh
compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
compiler/rustc_codegen_cranelift/scripts/tests.sh
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
compiler/rustc_codegen_cranelift/src/driver/aot.rs
compiler/rustc_codegen_cranelift/src/driver/jit.rs
compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/lib.rs
compiler/rustc_codegen_cranelift/src/optimize/mod.rs
compiler/rustc_codegen_cranelift/src/pretty_clif.rs
compiler/rustc_codegen_cranelift/src/value_and_place.rs
compiler/rustc_codegen_cranelift/src/vtable.rs
compiler/rustc_codegen_cranelift/test.sh
compiler/rustc_codegen_cranelift/y.rs [new file with mode: 0755]
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/context.rs
compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/lib.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/va_arg.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/linker.rs
compiler/rustc_codegen_ssa/src/back/rpath.rs
compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
compiler/rustc_codegen_ssa/src/back/write.rs
compiler/rustc_codegen_ssa/src/base.rs
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/meth.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
compiler/rustc_codegen_ssa/src/mir/operand.rs
compiler/rustc_codegen_ssa/src/mir/place.rs
compiler/rustc_codegen_ssa/src/traits/builder.rs
compiler/rustc_error_codes/src/error_codes/E0542.md
compiler/rustc_error_codes/src/error_codes/E0545.md
compiler/rustc_error_codes/src/error_codes/E0547.md
compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_errors/src/json.rs
compiler/rustc_errors/src/json/tests.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/mut_visit/tests.rs
compiler/rustc_expand/src/parse/tests.rs
compiler/rustc_expand/src/proc_macro.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_expand/src/tests.rs
compiler/rustc_expand/src/tokenstream/tests.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_hir/src/definitions.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir/src/tests.rs
compiler/rustc_incremental/src/persist/fs.rs
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/internal.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/non_fmt_panic.rs
compiler/rustc_lint/src/tests.rs [new file with mode: 0644]
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/dependency_format.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/hir/mod.rs
compiler/rustc_middle/src/ich/hcx.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/cstore.rs
compiler/rustc_middle/src/middle/exported_symbols.rs
compiler/rustc_middle/src/middle/limits.rs
compiler/rustc_middle/src/middle/mod.rs
compiler/rustc_middle/src/middle/stability.rs
compiler/rustc_middle/src/mir/interpret/allocation.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/mono.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/closure.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/query/mod.rs
compiler/rustc_middle/src/ty/query/on_disk_cache.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
compiler/rustc_mir/src/const_eval/eval_queries.rs
compiler/rustc_mir/src/const_eval/machine.rs
compiler/rustc_mir/src/interpret/eval_context.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_mir/src/monomorphize/collector.rs
compiler/rustc_mir/src/transform/check_consts/ops.rs
compiler/rustc_mir/src/transform/check_unsafety.rs
compiler/rustc_mir/src/transform/coverage/spans.rs
compiler/rustc_mir/src/transform/coverage/tests.rs
compiler/rustc_mir/src/transform/inline.rs
compiler/rustc_mir/src/transform/inline/cycle.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_build/src/thir/visit.rs
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/pat.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_parse_format/src/tests.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/lang_items.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/src/stats.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_session/src/lib.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/crate_disambiguator.rs [deleted file]
compiler/rustc_span/src/def_id.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/lev_distance/tests.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/span_encoding.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_span/src/symbol/tests.rs
compiler/rustc_span/src/tests.rs
compiler/rustc_symbol_mangling/src/legacy.rs
compiler/rustc_symbol_mangling/src/lib.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/asm/aarch64.rs
compiler/rustc_target/src/asm/mod.rs
compiler/rustc_target/src/asm/riscv.rs
compiler/rustc_target/src/asm/x86.rs
compiler/rustc_target/src/spec/aarch64_apple_ios.rs
compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
compiler/rustc_target/src/spec/aarch64_fuchsia.rs
compiler/rustc_target/src/spec/aarch64_linux_android.rs
compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
compiler/rustc_target/src/spec/aarch64_unknown_none.rs
compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
compiler/rustc_target/src/spec/abi.rs
compiler/rustc_target/src/spec/arm_base.rs [deleted file]
compiler/rustc_target/src/spec/arm_linux_androideabi.rs
compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs
compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs
compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs
compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs
compiler/rustc_target/src/spec/armv7_apple_ios.rs
compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs
compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs
compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs
compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs
compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs
compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs
compiler/rustc_target/src/spec/armv7a_none_eabi.rs
compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
compiler/rustc_target/src/spec/armv7r_none_eabi.rs
compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
compiler/rustc_target/src/spec/armv7s_apple_ios.rs
compiler/rustc_target/src/spec/bpf_base.rs
compiler/rustc_target/src/spec/mipsel_unknown_none.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
compiler/rustc_target/src/spec/riscv_base.rs [deleted file]
compiler/rustc_target/src/spec/thumb_base.rs
compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs
compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/infer.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_traits/src/dropck_outlives.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/check/callee.rs
compiler/rustc_typeck/src/check/cast.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/intrinsic.rs
compiler/rustc_typeck/src/check/method/prelude2021.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/collect.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/navigate.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/mod.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/macros.rs
library/alloc/src/string.rs
library/alloc/src/vec/mod.rs
library/core/src/array/equality.rs [new file with mode: 0644]
library/core/src/array/mod.rs
library/core/src/bool.rs
library/core/src/intrinsics.rs
library/core/src/iter/traits/collect.rs
library/core/src/iter/traits/exact_size.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/marker.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/num/int_log10.rs [new file with mode: 0644]
library/core/src/num/int_macros.rs
library/core/src/num/mod.rs
library/core/src/num/uint_macros.rs
library/core/src/ops/drop.rs
library/core/src/slice/iter.rs
library/core/src/slice/mod.rs
library/core/src/str/mod.rs
library/core/src/sync/atomic.rs
library/core/tests/lib.rs
library/core/tests/manually_drop.rs
library/core/tests/num/int_log.rs [new file with mode: 0644]
library/core/tests/num/mod.rs
library/std/src/collections/hash/map.rs
library/std/src/collections/hash/set.rs
library/std/src/f32.rs
library/std/src/f64.rs
library/std/src/ffi/os_str.rs
library/std/src/fs.rs
library/std/src/fs/tests.rs
library/std/src/io/cursor.rs
library/std/src/io/mod.rs
library/std/src/io/stdio.rs
library/std/src/io/tests.rs
library/std/src/lib.rs
library/std/src/os/unix/fs.rs
library/std/src/os/windows/process.rs
library/std/src/panic.rs
library/std/src/process.rs
library/std/src/sys/unix/android.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/kernel_copy.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/rand.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unix/weak.rs
library/std/src/sys/windows/process.rs
library/std/src/sys/windows/process/tests.rs
library/std/src/thread/mod.rs
src/bootstrap/doc.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/ci/cpu-usage-over-time.py
src/ci/docker/host-x86_64/mingw-check/Dockerfile
src/ci/scripts/collect-cpu-stats.sh
src/doc/book
src/doc/edition-guide
src/doc/embedded-book
src/doc/nomicon
src/doc/reference
src/doc/reference.md
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/doc/unstable-book/src/language-features/exclusive-range-pattern.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/half-open-range-patterns.md [new file with mode: 0644]
src/doc/unstable-book/src/library-features/asm.md
src/etc/gdb_lookup.py
src/etc/gdb_providers.py
src/etc/lldb_commands
src/etc/natvis/intrinsic.natvis
src/etc/natvis/libcore.natvis
src/etc/rust_types.py
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/cfg/tests.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight/tests.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/static/FiraSans-LICENSE.txt [deleted file]
src/librustdoc/html/static/FiraSans-Medium.woff [deleted file]
src/librustdoc/html/static/FiraSans-Medium.woff2 [deleted file]
src/librustdoc/html/static/FiraSans-Regular.woff [deleted file]
src/librustdoc/html/static/FiraSans-Regular.woff2 [deleted file]
src/librustdoc/html/static/SourceCodePro-It.ttf.woff [deleted file]
src/librustdoc/html/static/SourceCodePro-It.ttf.woff2 [deleted file]
src/librustdoc/html/static/SourceCodePro-LICENSE.txt [deleted file]
src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff [deleted file]
src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff2 [deleted file]
src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff [deleted file]
src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff2 [deleted file]
src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff [deleted file]
src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff2 [deleted file]
src/librustdoc/html/static/SourceSerif4-It.ttf.woff [deleted file]
src/librustdoc/html/static/SourceSerif4-It.ttf.woff2 [deleted file]
src/librustdoc/html/static/SourceSerif4-LICENSE.md [deleted file]
src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff [deleted file]
src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff2 [deleted file]
src/librustdoc/html/static/brush.svg [deleted file]
src/librustdoc/html/static/clipboard.svg [deleted file]
src/librustdoc/html/static/css/normalize.css [new file with mode: 0644]
src/librustdoc/html/static/css/noscript.css [new file with mode: 0644]
src/librustdoc/html/static/css/rustdoc.css [new file with mode: 0644]
src/librustdoc/html/static/css/settings.css [new file with mode: 0644]
src/librustdoc/html/static/css/themes/ayu.css [new file with mode: 0644]
src/librustdoc/html/static/css/themes/dark.css [new file with mode: 0644]
src/librustdoc/html/static/css/themes/light.css [new file with mode: 0644]
src/librustdoc/html/static/down-arrow.svg [deleted file]
src/librustdoc/html/static/favicon-16x16.png [deleted file]
src/librustdoc/html/static/favicon-32x32.png [deleted file]
src/librustdoc/html/static/favicon.svg [deleted file]
src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt [new file with mode: 0644]
src/librustdoc/html/static/fonts/FiraSans-Medium.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/FiraSans-Medium.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/FiraSans-Regular.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/FiraSans-Regular.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-LICENSE.txt [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff [new file with mode: 0644]
src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 [new file with mode: 0644]
src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt [new file with mode: 0644]
src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular.woff [new file with mode: 0644]
src/librustdoc/html/static/images/brush.svg [new file with mode: 0644]
src/librustdoc/html/static/images/clipboard.svg [new file with mode: 0644]
src/librustdoc/html/static/images/down-arrow.svg [new file with mode: 0644]
src/librustdoc/html/static/images/favicon-16x16.png [new file with mode: 0644]
src/librustdoc/html/static/images/favicon-32x32.png [new file with mode: 0644]
src/librustdoc/html/static/images/favicon.svg [new file with mode: 0644]
src/librustdoc/html/static/images/rust-logo.png [new file with mode: 0644]
src/librustdoc/html/static/images/wheel.svg [new file with mode: 0644]
src/librustdoc/html/static/js/main.js [new file with mode: 0644]
src/librustdoc/html/static/js/search.js [new file with mode: 0644]
src/librustdoc/html/static/js/settings.js [new file with mode: 0644]
src/librustdoc/html/static/js/source-script.js [new file with mode: 0644]
src/librustdoc/html/static/js/storage.js [new file with mode: 0644]
src/librustdoc/html/static/main.js [deleted file]
src/librustdoc/html/static/normalize.css [deleted file]
src/librustdoc/html/static/noscript.css [deleted file]
src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt [deleted file]
src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff [deleted file]
src/librustdoc/html/static/rust-logo.png [deleted file]
src/librustdoc/html/static/rustdoc.css [deleted file]
src/librustdoc/html/static/search.js [deleted file]
src/librustdoc/html/static/settings.css [deleted file]
src/librustdoc/html/static/settings.js [deleted file]
src/librustdoc/html/static/source-script.js [deleted file]
src/librustdoc/html/static/storage.js [deleted file]
src/librustdoc/html/static/themes/ayu.css [deleted file]
src/librustdoc/html/static/themes/dark.css [deleted file]
src/librustdoc/html/static/themes/light.css [deleted file]
src/librustdoc/html/static/wheel.svg [deleted file]
src/librustdoc/html/static_files.rs
src/librustdoc/json/conversions.rs
src/librustdoc/json/mod.rs
src/librustdoc/lib.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/passes/doc_test_lints.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/passes/strip_private.rs
src/librustdoc/passes/stripper.rs
src/librustdoc/passes/unindent_comments/tests.rs
src/librustdoc/theme/tests.rs
src/test/codegen/array-equality.rs [new file with mode: 0644]
src/test/codegen/asm-clobbers.rs [new file with mode: 0644]
src/test/codegen/async-fn-debug-msvc.rs
src/test/codegen/generator-debug-msvc.rs
src/test/codegen/slice-ref-equality.rs
src/test/codegen/unwind-abis/stdcall-unwind-abi.rs
src/test/codegen/unwind-abis/thiscall-unwind-abi.rs
src/test/debuginfo/msvc-pretty-enums.rs
src/test/debuginfo/pretty-huge-vec.rs
src/test/debuginfo/pretty-slices.rs [new file with mode: 0644]
src/test/debuginfo/pretty-std.rs
src/test/incremental/issue-86753.rs [new file with mode: 0644]
src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/run-make-fulldeps/rustdoc-themes/Makefile
src/test/run-make/raw-dylib-alt-calling-convention/Makefile [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/driver.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/extern.c [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/lib.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/output.txt [new file with mode: 0644]
src/test/run-make/raw-dylib-c/Makefile [new file with mode: 0644]
src/test/run-make/raw-dylib-c/driver.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-c/extern_1.c [new file with mode: 0644]
src/test/run-make/raw-dylib-c/extern_2.c [new file with mode: 0644]
src/test/run-make/raw-dylib-c/lib.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-c/output.txt [new file with mode: 0644]
src/test/run-make/raw-dylib/Makefile [deleted file]
src/test/run-make/raw-dylib/driver.rs [deleted file]
src/test/run-make/raw-dylib/extern_1.c [deleted file]
src/test/run-make/raw-dylib/extern_2.c [deleted file]
src/test/run-make/raw-dylib/lib.rs [deleted file]
src/test/run-make/raw-dylib/output.txt [deleted file]
src/test/rustdoc/auxiliary/reexports.rs [new file with mode: 0644]
src/test/rustdoc/duplicate-flags.rs [new file with mode: 0644]
src/test/rustdoc/reexports-priv.rs [new file with mode: 0644]
src/test/rustdoc/reexports.rs [new file with mode: 0644]
src/test/ui-fulldeps/mod_dir_path_canonicalized.rs
src/test/ui-fulldeps/pprust-expr-roundtrip.rs
src/test/ui/abi/unsupported.aarch64.stderr [new file with mode: 0644]
src/test/ui/abi/unsupported.i686.stderr [new file with mode: 0644]
src/test/ui/abi/unsupported.rs [new file with mode: 0644]
src/test/ui/abi/unsupported.x64.stderr [new file with mode: 0644]
src/test/ui/asm/bad-reg.rs
src/test/ui/asm/bad-reg.stderr
src/test/ui/attributes/nonterminal-expansion.rs
src/test/ui/attributes/nonterminal-expansion.stderr
src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr
src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr
src/test/ui/borrowck/borrowck-issue-14498.stderr
src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr
src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs
src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr
src/test/ui/borrowck/issue-85765.rs
src/test/ui/borrowck/issue-85765.stderr
src/test/ui/borrowck/mutability-errors.stderr
src/test/ui/c-variadic/variadic-ffi-1.rs
src/test/ui/c-variadic/variadic-ffi-1.stderr
src/test/ui/cast/cast-ptr-to-int-const.mir.stderr [deleted file]
src/test/ui/cast/cast-ptr-to-int-const.rs [deleted file]
src/test/ui/cast/cast-ptr-to-int-const.thir.stderr [deleted file]
src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs [deleted file]
src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/by_value.rs
src/test/ui/closures/2229_closure_analysis/by_value.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs
src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed
src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs
src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/no_migrations.rs
src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed
src/test/ui/closures/2229_closure_analysis/migrations/precise.rs
src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs
src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed
src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs
src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr
src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/move_closure.rs
src/test/ui/closures/2229_closure_analysis/move_closure.stderr
src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr [deleted file]
src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
src/test/ui/const-ptr/ptr_to_usize_cast.rs [deleted file]
src/test/ui/const-ptr/ptr_to_usize_cast.stderr [deleted file]
src/test/ui/consts/const-eval/const_panic.rs
src/test/ui/consts/const-eval/const_panic_track_caller.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/const_panic_track_caller.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs
src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr
src/test/ui/consts/const-eval/issue-52442.rs [deleted file]
src/test/ui/consts/const-eval/issue-52442.stderr [deleted file]
src/test/ui/consts/const-eval/match-test-ptr-null.rs
src/test/ui/consts/const-eval/match-test-ptr-null.stderr
src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs
src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr
src/test/ui/consts/const-unwrap.rs
src/test/ui/consts/const-unwrap.stderr
src/test/ui/consts/issue-17458.rs
src/test/ui/consts/issue-17458.stderr
src/test/ui/consts/issue-51559.rs [deleted file]
src/test/ui/consts/issue-51559.stderr [deleted file]
src/test/ui/consts/issue-52023-array-size-pointer-cast.rs
src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr
src/test/ui/consts/issue-52432.rs [deleted file]
src/test/ui/consts/issue-52432.stderr [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/miri_unleashed/tls.stderr
src/test/ui/consts/rustc-const-stability-require-const.rs [new file with mode: 0644]
src/test/ui/consts/rustc-const-stability-require-const.stderr [new file with mode: 0644]
src/test/ui/consts/rustc-impl-const-stability.rs [new file with mode: 0644]
src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr [deleted file]
src/test/ui/deduplicate-diagnostics-2.duplicate.stderr [deleted file]
src/test/ui/deduplicate-diagnostics-2.rs [deleted file]
src/test/ui/deprecation/deprecation-lint-3.stderr
src/test/ui/deprecation/deprecation-lint.stderr
src/test/ui/deprecation/suggestion.fixed
src/test/ui/deprecation/suggestion.rs
src/test/ui/deprecation/suggestion.stderr
src/test/ui/did_you_mean/issue-39544.rs
src/test/ui/did_you_mean/issue-39544.stderr
src/test/ui/error-codes/E0389.rs
src/test/ui/error-codes/E0389.stderr
src/test/ui/extern/extern-methods.rs
src/test/ui/extern/extern-thiscall.rs
src/test/ui/extern/extern-vectorcall.rs
src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs
src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-abi.rs
src/test/ui/feature-gates/feature-gate-abi.stderr
src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-abi_ptx.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-abi_ptx.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr
src/test/ui/feature-gates/feature-gate-vectorcall.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-vectorcall.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-wasm_abi.rs
src/test/ui/feature-gates/feature-gate-wasm_abi.stderr
src/test/ui/fmt/format-args-capture.rs
src/test/ui/generator/print/generator-print-verbose-1.stderr
src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
src/test/ui/half-open-range-patterns/range_pat_interactions0.rs [new file with mode: 0644]
src/test/ui/half-open-range-patterns/range_pat_interactions1.rs [new file with mode: 0644]
src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr [new file with mode: 0644]
src/test/ui/half-open-range-patterns/range_pat_interactions2.rs [new file with mode: 0644]
src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr [new file with mode: 0644]
src/test/ui/half-open-range-patterns/range_pat_interactions3.rs [new file with mode: 0644]
src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr [new file with mode: 0644]
src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs [new file with mode: 0644]
src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr [new file with mode: 0644]
src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs [new file with mode: 0644]
src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr [new file with mode: 0644]
src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs [new file with mode: 0644]
src/test/ui/hygiene/unpretty-debug.stdout
src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs [new file with mode: 0644]
src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr [new file with mode: 0644]
src/test/ui/intrinsics/intrinsic-raw_eq-const.rs [new file with mode: 0644]
src/test/ui/issues/issue-18294.rs
src/test/ui/issues/issue-18294.stderr
src/test/ui/issues/issue-41255.rs
src/test/ui/issues/issue-41255.stderr
src/test/ui/issues/issue-47412.mir.stderr
src/test/ui/issues/issue-47412.rs
src/test/ui/issues/issue-47412.thir.stderr
src/test/ui/issues/issue-51244.rs
src/test/ui/issues/issue-51244.stderr
src/test/ui/issues/issue-51515.rs
src/test/ui/issues/issue-51515.stderr
src/test/ui/issues/issue-6804.rs
src/test/ui/issues/issue-6804.stderr
src/test/ui/issues/issue-73886.stderr
src/test/ui/lang-items/issue-86238.rs [new file with mode: 0644]
src/test/ui/lang-items/issue-86238.stderr [new file with mode: 0644]
src/test/ui/lint/command-line-register-lint-tool.rs [new file with mode: 0644]
src/test/ui/lint/command-line-register-unknown-lint-tool.rs [new file with mode: 0644]
src/test/ui/lint/command-line-register-unknown-lint-tool.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr [new file with mode: 0644]
src/test/ui/lint/issue-86600-lint-twice.rs [new file with mode: 0644]
src/test/ui/lint/issue-86600-lint-twice.stderr [new file with mode: 0644]
src/test/ui/lint/lint-stability-deprecated.stderr
src/test/ui/lint/lint-stability3.stderr
src/test/ui/lint/missing-doc-private-macro.rs [new file with mode: 0644]
src/test/ui/lint/missing-doc-private-macro.stderr [new file with mode: 0644]
src/test/ui/lto-duplicate-symbols.stderr
src/test/ui/macros/assert-macro-owned.rs
src/test/ui/macros/macro-comma-behavior-rpass.rs
src/test/ui/macros/macro-or-patterns-back-compat.fixed
src/test/ui/macros/macro-or-patterns-back-compat.rs
src/test/ui/macros/macro-or-patterns-back-compat.stderr
src/test/ui/mut/mutable-class-fields-2.stderr
src/test/ui/nll/issue-47388.stderr
src/test/ui/nll/issue-51244.rs
src/test/ui/nll/issue-51244.stderr
src/test/ui/nll/issue-57989.rs
src/test/ui/nll/issue-57989.stderr
src/test/ui/non-fmt-panic.stderr
src/test/ui/panics/explicit-panic-msg.rs
src/test/ui/panics/panic-macro-any-wrapped.rs
src/test/ui/panics/panic-macro-any.rs
src/test/ui/parser/issue-86895.rs [new file with mode: 0644]
src/test/ui/parser/issue-86895.stderr [new file with mode: 0644]
src/test/ui/parser/recover-ref-dyn-mut.rs [new file with mode: 0644]
src/test/ui/parser/recover-ref-dyn-mut.stderr [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs
src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
src/test/ui/proc-macro/meta-macro-hygiene.stdout
src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
src/test/ui/proc-macro/span-from-proc-macro.stderr
src/test/ui/recursion_limit/empty.rs
src/test/ui/recursion_limit/empty.stderr
src/test/ui/recursion_limit/invalid_digit.rs
src/test/ui/recursion_limit/invalid_digit.stderr
src/test/ui/recursion_limit/overflow.rs
src/test/ui/recursion_limit/overflow.stderr
src/test/ui/repr/issue-83921-ice.rs [new file with mode: 0644]
src/test/ui/repr/issue-83921-ice.stderr [new file with mode: 0644]
src/test/ui/repr/issue-83921-pretty.normal.stderr [new file with mode: 0644]
src/test/ui/repr/issue-83921-pretty.pretty.stdout [new file with mode: 0644]
src/test/ui/repr/issue-83921-pretty.rs [new file with mode: 0644]
src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs
src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
src/test/ui/rfc-2005-default-binding-mode/enum.rs
src/test/ui/rfc-2005-default-binding-mode/enum.stderr
src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs
src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr
src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs
src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-imported.fixed
src/test/ui/rust-2021/future-prelude-collision-imported.rs
src/test/ui/rust-2021/future-prelude-collision-imported.stderr
src/test/ui/rust-2021/future-prelude-collision-shadow.rs
src/test/ui/rust-2021/future-prelude-collision-unneeded.rs
src/test/ui/rust-2021/future-prelude-collision.fixed
src/test/ui/rust-2021/future-prelude-collision.rs
src/test/ui/rust-2021/future-prelude-collision.stderr
src/test/ui/rust-2021/generic-type-collision.fixed
src/test/ui/rust-2021/generic-type-collision.rs
src/test/ui/rust-2021/generic-type-collision.stderr
src/test/ui/rust-2021/inherent-dyn-collision.fixed
src/test/ui/rust-2021/inherent-dyn-collision.rs
src/test/ui/rust-2021/inherent-dyn-collision.stderr
src/test/ui/rust-2021/inherent-method-collision.rs
src/test/ui/rust-2021/reserved-prefixes-migration.fixed
src/test/ui/rust-2021/reserved-prefixes-migration.rs
src/test/ui/rust-2021/reserved-prefixes-migration.stderr
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
src/test/ui/stability-attribute/generics-default-stability.stderr
src/test/ui/suggestions/issue-68049-1.stderr
src/test/ui/suggestions/issue-68049-2.stderr
src/test/ui/suggestions/suggest-mut-method-for-loop.stderr
src/test/ui/suggestions/suggest-ref-mut.stderr
src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs [new file with mode: 0644]
src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr [new file with mode: 0644]
src/test/ui/symbol-names/basic.legacy.stderr
src/test/ui/symbol-names/basic.rs
src/test/ui/symbol-names/basic.v0.stderr
src/test/ui/symbol-names/const-generics-demangling.rs
src/test/ui/symbol-names/const-generics-demangling.stderr
src/test/ui/symbol-names/impl1.rs
src/test/ui/symbol-names/impl1.v0.stderr
src/test/ui/symbol-names/issue-60925.legacy.stderr
src/test/ui/symbol-names/issue-60925.rs
src/test/ui/symbol-names/issue-60925.v0.stderr
src/test/ui/symbol-names/issue-75326.rs
src/test/ui/symbol-names/issue-75326.v0.stderr
src/test/ui/symbol-names/trait-objects.v0.stderr
src/test/ui/union/union-align.rs
src/test/ui/union/union-backcomp.rs
src/test/ui/union/union-basic.rs
src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-borrow-move-parent-sibling.rs
src/test/ui/union/union-borrow-move-parent-sibling.stderr [deleted file]
src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-const-codegen.rs
src/test/ui/union/union-const-eval-field.rs
src/test/ui/union/union-const-eval.rs
src/test/ui/union/union-deref.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-deref.rs
src/test/ui/union/union-deref.stderr [deleted file]
src/test/ui/union/union-deref.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-clone.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-clone.rs
src/test/ui/union/union-derive-clone.stderr [deleted file]
src/test/ui/union/union-derive-clone.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-eq.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-eq.rs
src/test/ui/union/union-derive-eq.stderr [deleted file]
src/test/ui/union/union-derive-eq.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-rpass.rs
src/test/ui/union/union-drop.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-1.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-1.rs
src/test/ui/union/union-fields-1.stderr [deleted file]
src/test/ui/union/union-fields-1.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-2.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-2.rs
src/test/ui/union/union-fields-2.stderr [deleted file]
src/test/ui/union/union-fields-2.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-generic-rpass.rs
src/test/ui/union/union-generic.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-generic.rs
src/test/ui/union/union-generic.stderr [deleted file]
src/test/ui/union/union-generic.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-inherent-method.rs
src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-lint-dead-code.rs
src/test/ui/union/union-lint-dead-code.stderr [deleted file]
src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-macro.rs
src/test/ui/union/union-manuallydrop-rpass.rs
src/test/ui/union/union-move.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-move.rs
src/test/ui/union/union-move.stderr [deleted file]
src/test/ui/union/union-move.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-nodrop.rs
src/test/ui/union/union-nonzero.rs
src/test/ui/union/union-overwrite.rs
src/test/ui/union/union-packed.rs
src/test/ui/union/union-pat-refutability.rs
src/test/ui/union/union-suggest-field.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-suggest-field.rs
src/test/ui/union/union-suggest-field.stderr [deleted file]
src/test/ui/union/union-suggest-field.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-trait-impl.rs
src/test/ui/union/union-transmute.rs
src/test/ui/union/union-unsafe.mir.stderr [new file with mode: 0644]
src/test/ui/union/union-unsafe.rs
src/test/ui/union/union-unsafe.stderr [deleted file]
src/test/ui/union/union-unsafe.thir.stderr [new file with mode: 0644]
src/test/ui/union/union-unsized.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-unsized.rs
src/test/ui/union/union-unsized.stderr [deleted file]
src/test/ui/union/union-unsized.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-with-drop-fields.rs
src/test/ui/union/union-with-drop-fields.stderr [deleted file]
src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/access_union_field.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/access_union_field.rs [new file with mode: 0644]
src/test/ui/unsafe/access_union_field.thir.stderr [new file with mode: 0644]
src/test/ui/unsafe/union.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/union.rs [new file with mode: 0644]
src/test/ui/unsafe/union_access_through_block.rs [new file with mode: 0644]
src/test/ui/unsafe/union_destructure.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/union_destructure.rs [new file with mode: 0644]
src/test/ui/unsafe/union_wild_or_wild.rs [new file with mode: 0644]
src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs
src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr
src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs
src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr
src/tools/clippy/CHANGELOG.md
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/misc.rs
src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/ty.rs
src/tools/clippy/tests/ui/assertions_on_constants.rs
src/tools/clippy/tests/ui/deprecated.stderr
src/tools/compiletest/src/runtest.rs
src/tools/error_index_generator/main.rs
src/tools/lint-docs/src/lib.rs
src/tools/miri
src/tools/rust-analyzer
src/tools/rustfmt/src/formatting.rs
src/tools/tidy/src/deps.rs
src/tools/tidy/src/error_codes_check.rs

index 5d9bc173364da64107d2b975fda7f74be34e6bd6..d6b7ab51a48c66d18c6d61ac0ee09ae0ef3d4878 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -113,9 +113,14 @@ Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
 Heather <heather@cynede.net> <Cynede@Gentoo.org>
 Heather <heather@cynede.net> <Heather@cynede.net>
 Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtke@gmail.com>
+Ian Jackson <ijackson@chiark.greenend.org.uk> <ian.jackson@citrix.com>
+Ian Jackson <ijackson@chiark.greenend.org.uk> <ijackson+github@slimy.greenend.org.uk>
+Ian Jackson <ijackson@chiark.greenend.org.uk> <iwj@xenproject.org>
 Ilyong Cho <ilyoan@gmail.com>
+inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com>
 Ivan Ivaschenko <defuz.net@gmail.com>
 J. J. Weber <jjweber@gmail.com>
+Jacob Pratt <jacob@jhpratt.dev> <the.z.cuber@gmail.com>
 Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
 Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc>
 Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net>
index f8f1331579406dfb1f7651a727c3018eb78c259a..b432f9ae2272a8fdaa5b3a6d51518be575606b15 100644 (file)
@@ -3044,31 +3044,29 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.4.3"
+version = "1.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
+checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
 dependencies = [
  "aho-corasick",
  "memchr",
  "regex-syntax",
- "thread_local",
 ]
 
 [[package]]
 name = "regex-automata"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 dependencies = [
- "byteorder",
  "regex-syntax",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.22"
+version = "0.6.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
 [[package]]
 name = "remote-test-client"
index 03282fd51649650121a5679a23113fd17285f3e6..f851725058d4b689a4d9f6a037dee81889036d76 100644 (file)
@@ -677,7 +677,9 @@ pub enum BindingMode {
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum RangeEnd {
+    /// `..=` or `...`
     Included(RangeSyntax),
+    /// `..`
     Excluded,
 }
 
@@ -689,6 +691,7 @@ pub enum RangeSyntax {
     DotDotEq,
 }
 
+/// All the different flavors of pattern that Rust recognizes.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum PatKind {
     /// Represents a wildcard pattern (`_`).
@@ -729,7 +732,7 @@ pub enum PatKind {
     /// A literal.
     Lit(P<Expr>),
 
-    /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
+    /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
     Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
 
     /// A slice pattern `[a, b, c]`.
index 98ab653e45f70e740da4226366cd194676986d14..6d137f3774fe76a6fe801557956602223e4a3963 100644 (file)
@@ -1,9 +1,9 @@
 use super::*;
-use rustc_span::with_default_session_globals;
+use rustc_span::create_default_session_globals_then;
 
 #[test]
 fn test_block_doc_comment_1() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let comment = "\n * Test \n **  Test\n *   Test\n";
         let stripped = beautify_doc_string(Symbol::intern(comment));
         assert_eq!(stripped.as_str(), " Test \n*  Test\n   Test");
@@ -12,7 +12,7 @@ fn test_block_doc_comment_1() {
 
 #[test]
 fn test_block_doc_comment_2() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let comment = "\n * Test\n *  Test\n";
         let stripped = beautify_doc_string(Symbol::intern(comment));
         assert_eq!(stripped.as_str(), " Test\n  Test");
@@ -21,7 +21,7 @@ fn test_block_doc_comment_2() {
 
 #[test]
 fn test_block_doc_comment_3() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let comment = "\n let a: *i32;\n *a = 5;\n";
         let stripped = beautify_doc_string(Symbol::intern(comment));
         assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
@@ -30,7 +30,7 @@ fn test_block_doc_comment_3() {
 
 #[test]
 fn test_line_doc_comment() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let stripped = beautify_doc_string(Symbol::intern(" test"));
         assert_eq!(stripped.as_str(), " test");
         let stripped = beautify_doc_string(Symbol::intern("! test"));
index 1c3fae2afe71f2af5304cc7654434940082f744f..9ea09a2cf31a15f46d50abc8418346d923b5868f 100644 (file)
@@ -199,6 +199,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                 );
 
+                // Some register classes can only be used as clobbers. This
+                // means that we disallow passing a value in/out of the asm and
+                // require that the operand name an explicit register, not a
+                // register class.
+                if reg_class.is_clobber_only(asm_arch.unwrap())
+                    && !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
+                {
+                    let msg = format!(
+                        "register class `{}` can only be used as a clobber, \
+                             not as an input or output",
+                        reg_class.name()
+                    );
+                    sess.struct_span_err(op_sp, &msg).emit();
+                    continue;
+                }
+
                 if !is_clobber {
                     // Validate register classes against currently enabled target
                     // features. We check that at least one type is available for
index b9dcd083c0b8c9b176883851952e7cbdd3007cd9..eb8e92f07eacc180ceb0e5bd060c6918be404146 100644 (file)
@@ -1559,13 +1559,14 @@ fn lower_expr_for(
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
     /// ```rust
-    /// match Try::into_result(<expr>) {
-    ///     Ok(val) => #[allow(unreachable_code)] val,
-    ///     Err(err) => #[allow(unreachable_code)]
-    ///                 // If there is an enclosing `try {...}`:
-    ///                 break 'catch_target Try::from_error(From::from(err)),
-    ///                 // Otherwise:
-    ///                 return Try::from_error(From::from(err)),
+    /// match Try::branch(<expr>) {
+    ///     ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
+    ///     ControlFlow::Break(residual) =>
+    ///         #[allow(unreachable_code)]
+    ///         // If there is an enclosing `try {...}`:
+    ///         break 'catch_target Try::from_residual(residual),
+    ///         // Otherwise:
+    ///         return Try::from_residual(residual),
     /// }
     /// ```
     fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
index 3f98944d850e7991f01393e0062da1984dcb0441..3e757e3843e38425d4d2b163b17ed13cbff31e6e 100644 (file)
@@ -565,6 +565,22 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
 
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match &pattern.kind {
+            PatKind::Slice(pats) => {
+                for pat in pats {
+                    let inner_pat = match &pat.kind {
+                        PatKind::Ident(.., Some(pat)) => pat,
+                        _ => pat,
+                    };
+                    if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
+                        gate_feature_post!(
+                            &self,
+                            half_open_range_patterns,
+                            pat.span,
+                            "`X..` patterns in slices are experimental"
+                        );
+                    }
+                }
+            }
             PatKind::Box(..) => {
                 gate_feature_post!(
                     &self,
@@ -573,7 +589,7 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
                     "box pattern syntax is experimental"
                 );
             }
-            PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
+            PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
                 gate_feature_post!(
                     &self,
                     exclusive_range_pattern,
index 8abd85a5a5214e9f9c20e429fc5ce0272e37560f..6c8d42f33eb5a74de15756cff7fbf760b3c60adf 100644 (file)
@@ -1,8 +1,8 @@
 use super::*;
 
 use rustc_ast as ast;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::symbol::Ident;
-use rustc_span::with_default_session_globals;
 
 fn fun_to_string(
     decl: &ast::FnDecl,
@@ -24,7 +24,7 @@ fn variant_to_string(var: &ast::Variant) -> String {
 
 #[test]
 fn test_fun_to_string() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let abba_ident = Ident::from_str("abba");
 
         let decl =
@@ -39,7 +39,7 @@ fn test_fun_to_string() {
 
 #[test]
 fn test_variant_to_string() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let ident = Ident::from_str("principal_skinner");
 
         let var = ast::Variant {
index 20971ebb95748888568d994fbf31286e33ea2282..b7b053cd5ddb7a910f24f795abb0ddac2ecb1044 100644 (file)
@@ -870,6 +870,23 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         sym::simd => Some(ReprSimd),
                         sym::transparent => Some(ReprTransparent),
                         sym::no_niche => Some(ReprNoNiche),
+                        sym::align => {
+                            let mut err = struct_span_err!(
+                                diagnostic,
+                                item.span(),
+                                E0589,
+                                "invalid `repr(align)` attribute: `align` needs an argument"
+                            );
+                            err.span_suggestion(
+                                item.span(),
+                                "supply an argument here",
+                                "align(...)".to_string(),
+                                Applicability::HasPlaceholders,
+                            );
+                            err.emit();
+                            recognised = true;
+                            None
+                        }
                         name => int_type_of_word(name).map(ReprInt),
                     };
 
@@ -891,33 +908,47 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                             Ok(literal) => acc.push(ReprPacked(literal)),
                             Err(message) => literal_error = Some(message),
                         };
+                    } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche)
+                        || int_type_of_word(name).is_some()
+                    {
+                        recognised = true;
+                        struct_span_err!(
+                                diagnostic,
+                                item.span(),
+                                E0552,
+                                "invalid representation hint: `{}` does not take a parenthesized argument list",
+                                name.to_ident_string(),
+                            ).emit();
                     }
                     if let Some(literal_error) = literal_error {
                         struct_span_err!(
                             diagnostic,
                             item.span(),
                             E0589,
-                            "invalid `repr(align)` attribute: {}",
+                            "invalid `repr({})` attribute: {}",
+                            name.to_ident_string(),
                             literal_error
                         )
                         .emit();
                     }
                 } else if let Some(meta_item) = item.meta_item() {
-                    if meta_item.has_name(sym::align) {
-                        if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+                    if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+                        if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
+                            let name = meta_item.name_or_empty().to_ident_string();
                             recognised = true;
                             let mut err = struct_span_err!(
                                 diagnostic,
                                 item.span(),
                                 E0693,
-                                "incorrect `repr(align)` attribute format"
+                                "incorrect `repr({})` attribute format",
+                                name,
                             );
                             match value.kind {
                                 ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
                                     err.span_suggestion(
                                         item.span(),
                                         "use parentheses instead",
-                                        format!("align({})", int),
+                                        format!("{}({})", name, int),
                                         Applicability::MachineApplicable,
                                     );
                                 }
@@ -925,19 +956,76 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                                     err.span_suggestion(
                                         item.span(),
                                         "use parentheses instead",
-                                        format!("align({})", s),
+                                        format!("{}({})", name, s),
                                         Applicability::MachineApplicable,
                                     );
                                 }
                                 _ => {}
                             }
                             err.emit();
+                        } else {
+                            if matches!(
+                                meta_item.name_or_empty(),
+                                sym::C | sym::simd | sym::transparent | sym::no_niche
+                            ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                            {
+                                recognised = true;
+                                struct_span_err!(
+                                    diagnostic,
+                                    meta_item.span,
+                                    E0552,
+                                    "invalid representation hint: `{}` does not take a value",
+                                    meta_item.name_or_empty().to_ident_string(),
+                                )
+                                .emit();
+                            }
+                        }
+                    } else if let MetaItemKind::List(_) = meta_item.kind {
+                        if meta_item.has_name(sym::align) {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0693,
+                                "incorrect `repr(align)` attribute format: \
+                                 `align` takes exactly one argument in parentheses"
+                            )
+                            .emit();
+                        } else if meta_item.has_name(sym::packed) {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0552,
+                                "incorrect `repr(packed)` attribute format: \
+                                 `packed` takes exactly one parenthesized argument, \
+                                 or no parentheses at all"
+                            )
+                            .emit();
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent | sym::no_niche
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0552,
+                                "invalid representation hint: `{}` does not take a parenthesized argument list",
+                                meta_item.name_or_empty().to_ident_string(),
+                            ).emit();
                         }
                     }
                 }
                 if !recognised {
-                    // Not a word we recognize
-                    diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+                    // Not a word we recognize. This will be caught and reported by
+                    // the `check_mod_attrs` pass, but this pass doesn't always run
+                    // (e.g. if we only pretty-print the source), so we have to gate
+                    // the `delay_span_bug` call as follows:
+                    if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
+                        diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+                    }
                 }
             }
         }
index 2393e0b9ebfac662e8b744d9b920f1190cdc1e76..ba27f1033092807402f6a470e21efd051563cf32 100644 (file)
@@ -19,7 +19,6 @@
 
 use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
 use rustc_expand::proc_macro::BangProcMacro;
-use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::sym;
 
 mod asm;
@@ -113,8 +112,5 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
     }
 
     let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
-    register(
-        sym::quote,
-        SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client, krate: LOCAL_CRATE })),
-    );
+    register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })));
 }
index e173df423a76523f092160e138d648ea64c29651..61da6a2491c52fcd3270195db5fb441e89c0a496 100644 (file)
@@ -14,7 +14,7 @@ task:
     - . $HOME/.cargo/env
     - git config --global user.email "user@example.com"
     - git config --global user.name "User"
-    - ./prepare.sh
+    - ./y.rs prepare
   test_script:
     - . $HOME/.cargo/env
     - # Enable backtraces for easier debugging
index 4d45e36c956c908f5ee1f0f295a00b0dc6c95ec7..f81ac87726052c7c16e78869bd4baf2866be1fa1 100644 (file)
@@ -19,6 +19,9 @@ jobs:
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: x86_64-pc-windows-gnu
+          - os: ubuntu-latest
+            env:
+              TARGET_TRIPLE: aarch64-unknown-linux-gnu
 
     steps:
     - uses: actions/checkout@v2
@@ -49,11 +52,19 @@ jobs:
         sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
         rustup target add x86_64-pc-windows-gnu
 
+    - name: Install AArch64 toolchain and qemu
+      if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu'
+      run: |
+        sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
+
     - name: Prepare dependencies
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
-        ./prepare.sh
+        ./y.rs prepare
+
+    - name: Build
+      run: ./y.rs build --sysroot none
 
     - name: Test
       env:
@@ -87,3 +98,63 @@ jobs:
       with:
         name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
         path: cg_clif.tar.xz
+
+  build_windows:
+    runs-on: windows-latest
+    timeout-minutes: 60
+
+    steps:
+    - uses: actions/checkout@v2
+
+    #- name: Cache cargo installed crates
+    #  uses: actions/cache@v2
+    #  with:
+    #    path: ~/.cargo/bin
+    #    key: ${{ runner.os }}-cargo-installed-crates
+
+    #- name: Cache cargo registry and index
+    #  uses: actions/cache@v2
+    #  with:
+    #    path: |
+    #        ~/.cargo/registry
+    #        ~/.cargo/git
+    #    key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
+
+    #- name: Cache cargo target dir
+    #  uses: actions/cache@v2
+    #  with:
+    #    path: target
+    #    key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+    - name: Prepare dependencies
+      run: |
+        git config --global user.email "user@example.com"
+        git config --global user.name "User"
+        git config --global core.autocrlf false
+        rustup set default-host x86_64-pc-windows-gnu
+        rustc y.rs -o y.exe -g
+        ./y.exe prepare
+
+    - name: Build
+      #name: Test
+      run: |
+        # Enable backtraces for easier debugging
+        #export RUST_BACKTRACE=1
+
+        # Reduce amount of benchmark runs as they are slow
+        #export COMPILE_RUNS=2
+        #export RUN_RUNS=2
+
+        # Enable extra checks
+        #export CG_CLIF_ENABLE_VERIFIER=1
+
+        ./y.exe build
+
+    #- name: Package prebuilt cg_clif
+    #  run: tar cvfJ cg_clif.tar.xz build
+
+    #- name: Upload prebuilt cg_clif
+    #  uses: actions/upload-artifact@v2
+    #  with:
+    #    name: cg_clif-${{ runner.os }}
+    #    path: cg_clif.tar.xz
index e01a92598bab745b4df24ef41bb5e50ccfef4701..1c08e5ece33d27e67fc01b5012f1ac237f2fc51c 100644 (file)
@@ -34,7 +34,7 @@ jobs:
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
-        ./prepare.sh
+        ./y.rs prepare
 
     - name: Test
       run: |
@@ -72,7 +72,7 @@ jobs:
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
-        ./prepare.sh
+        ./y.rs prepare
 
     - name: Test
       run: |
index b241bef9d1e7ff6c03aa98ee03abe04252823a6c..12e779fe7c7d7b8bb050611e643a6355776ed518 100644 (file)
@@ -6,9 +6,11 @@ perf.data
 perf.data.old
 *.events
 *.string*
+/y.bin
 /build
 /build_sysroot/sysroot_src
 /build_sysroot/compiler-builtins
+/build_sysroot/rustc_version
 /rust
 /rand
 /regex
index 9009a532c54dcc91ac5ea9943a48ba63f0803bc9..f62e59cefc2414c23ecb8a3ca3418d87d4e7f7c5 100644 (file)
@@ -1,7 +1,9 @@
 {
     // source for rustc_* is not included in the rust-src component; disable the errors about this
     "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"],
-    "rust-analyzer.assist.importMergeBehavior": "last",
+    "rust-analyzer.assist.importGranularity": "module",
+    "rust-analyzer.assist.importEnforceGranularity": true,
+    "rust-analyzer.assist.importPrefix": "crate",
     "rust-analyzer.cargo.runBuildScripts": true,
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
                     "cfg": [],
                 },
             ]
+        },
+        {
+            "roots": ["./y.rs"],
+            "crates": [
+                {
+                    "root_module": "./y.rs",
+                    "edition": "2018",
+                    "deps": [{ "crate": 1, "name": "std" }],
+                    "cfg": [],
+                },
+                {
+                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
+                    "edition": "2018",
+                    "deps": [],
+                    "cfg": [],
+                },
+            ]
         }
     ]
 }
index a6f5925149b925a59fab9c83719be9c2aefd7a13..56d0974b25371b6e2abef4451c5eefef3879668c 100644 (file)
@@ -33,16 +33,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "cranelift-bforest",
  "cranelift-codegen-meta",
@@ -57,8 +57,8 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "cranelift-codegen-shared",
  "cranelift-entity",
@@ -66,18 +66,18 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 
 [[package]]
 name = "cranelift-entity"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -87,8 +87,8 @@ dependencies = [
 
 [[package]]
 name = "cranelift-jit"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -104,8 +104,8 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -115,17 +115,18 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "cranelift-codegen",
+ "libc",
  "target-lexicon",
 ]
 
 [[package]]
 name = "cranelift-object"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -171,9 +172,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.86"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
 
 [[package]]
 name = "libloading"
@@ -203,14 +204,21 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "memchr"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+
 [[package]]
 name = "object"
-version = "0.24.0"
+version = "0.25.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170"
+checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7"
 dependencies = [
  "crc32fast",
  "indexmap",
+ "memchr",
 ]
 
 [[package]]
index fd149af454735e528277b2290fd4c4258e64374c..ef68d7ee532dd3a7561ef0539f326959e3e0857c 100644 (file)
@@ -9,7 +9,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind"] }
+cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind", "all-arch"] }
 cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
 cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
 cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
@@ -17,7 +17,7 @@ cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", bran
 cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.24.0", default-features = false, features = ["write"]}
-object = { version = "0.24.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
+object = { version = "0.25.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
 
 ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
 indexmap = "1.0.2"
index 08f9373be6262ba35226ceb02fb0a3f5aba22be8..dad8ed90b53b8307fb1c4b72d40b15a59c2878bd 100644 (file)
@@ -10,8 +10,8 @@ If not please open an issue.
 ```bash
 $ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git
 $ cd rustc_codegen_cranelift
-$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking
-$ ./build.sh
+$ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking
+$ ./y.rs build
 ```
 
 To run the test suite replace the last command with:
@@ -20,7 +20,7 @@ To run the test suite replace the last command with:
 $ ./test.sh
 ```
 
-This will implicitly build cg_clif too. Both `build.sh` and `test.sh` accept a `--debug` argument to
+This will implicitly build cg_clif too. Both `y.rs build` and `test.sh` accept a `--debug` argument to
 build in debug mode.
 
 Alternatively you can download a pre built version from [GHA]. It is listed in the artifacts section
@@ -32,12 +32,12 @@ of workflow runs. Unfortunately due to GHA restrictions you need to be logged in
 
 rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
 
-Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`).
+Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`).
 
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo.sh build
+$ $cg_clif_dir/build/cargo build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
diff --git a/compiler/rustc_codegen_cranelift/build.sh b/compiler/rustc_codegen_cranelift/build.sh
deleted file mode 100755 (executable)
index 76bc188..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-# Settings
-export CHANNEL="release"
-build_sysroot="clif"
-target_dir='build'
-while [[ $# != 0 ]]; do
-    case $1 in
-        "--debug")
-            export CHANNEL="debug"
-            ;;
-        "--sysroot")
-            build_sysroot=$2
-            shift
-            ;;
-        "--target-dir")
-            target_dir=$2
-            shift
-            ;;
-        *)
-            echo "Unknown flag '$1'"
-            echo "Usage: ./build.sh [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]"
-            exit 1
-            ;;
-    esac
-    shift
-done
-
-# Build cg_clif
-unset CARGO_TARGET_DIR
-unamestr=$(uname)
-if [[ "$unamestr" == 'Linux' || "$unamestr" == "FreeBSD" ]]; then
-   export RUSTFLAGS='-Clink-arg=-Wl,-rpath=$ORIGIN/../lib '$RUSTFLAGS
-elif [[ "$unamestr" == 'Darwin' ]]; then
-   export RUSTFLAGS='-Csplit-debuginfo=unpacked -Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS
-   dylib_ext='dylib'
-else
-   echo "Unsupported os $unamestr"
-   exit 1
-fi
-if [[ "$CHANNEL" == "release" ]]; then
-    cargo build --release
-else
-    cargo build
-fi
-
-source scripts/ext_config.sh
-
-rm -rf "$target_dir"
-mkdir "$target_dir"
-mkdir "$target_dir"/bin "$target_dir"/lib
-ln target/$CHANNEL/cg_clif{,_build_sysroot} "$target_dir"/bin
-ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib
-ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir"
-
-mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
-mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/"
-if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
-    cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
-fi
-
-case "$build_sysroot" in
-    "none")
-        ;;
-    "llvm")
-        cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/"
-        if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
-            cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/"
-        fi
-        ;;
-    "clif")
-        echo "[BUILD] sysroot"
-        dir=$(pwd)
-        cd "$target_dir"
-        time "$dir/build_sysroot/build_sysroot.sh"
-        if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
-            time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh"
-        fi
-        cp lib/rustlib/*/lib/libstd-* lib/
-        ;;
-    *)
-        echo "Unknown sysroot kind \`$build_sysroot\`."
-        echo "The allowed values are:"
-        echo "    none A sysroot that doesn't contain the standard library"
-        echo "    llvm Copy the sysroot from rustc compiled by cg_llvm"
-        echo "    clif Build a new sysroot using cg_clif"
-        exit 1
-esac
index 923deb9aec4c082e357f9c2bc3425a14fbe8c8e8..46f661107e73b43ab0b9a2713e51661a60a64708 100644 (file)
@@ -56,7 +56,7 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.43"
+version = "0.1.46"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -121,9 +121,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -132,9 +132,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.95"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
+checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -195,9 +195,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.19"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce"
+checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh
deleted file mode 100755 (executable)
index 0354304..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-
-# Requires the CHANNEL env var to be set to `debug` or `release.`
-
-set -e
-
-source ./config.sh
-
-dir=$(pwd)
-
-# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that
-# build scripts are still compiled using cg_llvm.
-export RUSTC=$dir"/bin/cg_clif_build_sysroot"
-export RUSTFLAGS=$RUSTFLAGS" --clif"
-
-cd "$(dirname "$0")"
-
-# Cleanup for previous run
-#     v Clean target dir except for build scripts and incremental cache
-rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true
-
-# We expect the target dir in the default location. Guard against the user changing it.
-export CARGO_TARGET_DIR=target
-
-# Build libs
-export RUSTFLAGS="$RUSTFLAGS -Zforce-unstable-if-unmarked -Cpanic=abort"
-export __CARGO_DEFAULT_LIB_METADATA="cg_clif"
-if [[ "$1" != "--debug" ]]; then
-    sysroot_channel='release'
-    # FIXME Enable incremental again once rust-lang/rust#74946 is fixed
-    CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release
-else
-    sysroot_channel='debug'
-    cargo build --target "$TARGET_TRIPLE"
-fi
-
-# Copy files to sysroot
-ln "target/$TARGET_TRIPLE/$sysroot_channel/deps/"* "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"
-rm "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"*.{rmeta,d}
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh
deleted file mode 100755 (executable)
index 54b7a94..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-set -e
-cd "$(dirname "$0")"
-
-SRC_DIR="$(dirname "$(rustup which rustc)")/../lib/rustlib/src/rust/"
-DST_DIR="sysroot_src"
-
-if [ ! -e "$SRC_DIR" ]; then
-    echo "Please install rust-src component"
-    exit 1
-fi
-
-rm -rf $DST_DIR
-mkdir -p $DST_DIR/library
-cp -a "$SRC_DIR/library" $DST_DIR/
-
-pushd $DST_DIR
-echo "[GIT] init"
-git init
-echo "[GIT] add"
-git add .
-echo "[GIT] commit"
-git commit -m "Initial commit" -q
-for file in $(ls ../../patches/ | grep -v patcha); do
-echo "[GIT] apply" "$file"
-git apply ../../patches/"$file"
-git add -A
-git commit --no-gpg-sign -m "Patch $file"
-done
-popd
-
-git clone https://github.com/rust-lang/compiler-builtins.git || echo "rust-lang/compiler-builtins has already been cloned"
-pushd compiler-builtins
-git checkout -- .
-git checkout 0.1.43
-git apply ../../crate_patches/000*-compiler-builtins-*.patch
-popd
-
-echo "Successfully prepared sysroot source for building"
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
new file mode 100644 (file)
index 0000000..1df2bcc
--- /dev/null
@@ -0,0 +1,40 @@
+use std::env;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf {
+    let mut cmd = Command::new("cargo");
+    cmd.arg("build").arg("--target").arg(host_triple);
+
+    match channel {
+        "debug" => {}
+        "release" => {
+            cmd.arg("--release");
+        }
+        _ => unreachable!(),
+    }
+
+    if cfg!(unix) {
+        if cfg!(target_os = "macos") {
+            cmd.env(
+                "RUSTFLAGS",
+                "-Csplit-debuginfo=unpacked \
+                -Clink-arg=-Wl,-rpath,@loader_path/../lib \
+                -Zosx-rpath-install-name"
+                    .to_string()
+                    + env::var("RUSTFLAGS").as_deref().unwrap_or(""),
+            );
+        } else {
+            cmd.env(
+                "RUSTFLAGS",
+                "-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string()
+                    + env::var("RUSTFLAGS").as_deref().unwrap_or(""),
+            );
+        }
+    }
+
+    eprintln!("[BUILD] rustc_codegen_cranelift");
+    crate::utils::spawn_and_wait(cmd);
+
+    Path::new("target").join(host_triple).join(channel)
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
new file mode 100644 (file)
index 0000000..9fb88c2
--- /dev/null
@@ -0,0 +1,216 @@
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::process::{self, Command};
+
+use crate::rustc_info::{get_file_name, get_rustc_version};
+use crate::utils::{spawn_and_wait, try_hard_link};
+use crate::SysrootKind;
+
+pub(crate) fn build_sysroot(
+    channel: &str,
+    sysroot_kind: SysrootKind,
+    target_dir: &Path,
+    cg_clif_build_dir: PathBuf,
+    host_triple: &str,
+    target_triple: &str,
+) {
+    if target_dir.exists() {
+        fs::remove_dir_all(target_dir).unwrap();
+    }
+    fs::create_dir_all(target_dir.join("bin")).unwrap();
+    fs::create_dir_all(target_dir.join("lib")).unwrap();
+
+    // Copy the backend
+    for file in ["cg_clif", "cg_clif_build_sysroot"] {
+        try_hard_link(
+            cg_clif_build_dir.join(get_file_name(file, "bin")),
+            target_dir.join("bin").join(get_file_name(file, "bin")),
+        );
+    }
+
+    let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib");
+    try_hard_link(
+        cg_clif_build_dir.join(&cg_clif_dylib),
+        target_dir
+            .join(if cfg!(windows) {
+                // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
+                // binaries.
+                "bin"
+            } else {
+                "lib"
+            })
+            .join(cg_clif_dylib),
+    );
+
+    // Build and copy cargo wrapper
+    let mut build_cargo_wrapper_cmd = Command::new("rustc");
+    build_cargo_wrapper_cmd
+        .arg("scripts/cargo.rs")
+        .arg("-o")
+        .arg(target_dir.join("cargo"))
+        .arg("-g");
+    spawn_and_wait(build_cargo_wrapper_cmd);
+
+    let default_sysroot = crate::rustc_info::get_default_sysroot();
+
+    let rustlib = target_dir.join("lib").join("rustlib");
+    let host_rustlib_lib = rustlib.join(host_triple).join("lib");
+    let target_rustlib_lib = rustlib.join(target_triple).join("lib");
+    fs::create_dir_all(&host_rustlib_lib).unwrap();
+    fs::create_dir_all(&target_rustlib_lib).unwrap();
+
+    if target_triple == "x86_64-pc-windows-gnu" {
+        if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() {
+            eprintln!(
+                "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \
+                to compile a sysroot for it.",
+            );
+            process::exit(1);
+        }
+        for file in fs::read_dir(
+            default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
+        )
+        .unwrap()
+        {
+            let file = file.unwrap().path();
+            if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") {
+                continue; // only copy object files
+            }
+            try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
+        }
+    }
+
+    match sysroot_kind {
+        SysrootKind::None => {} // Nothing to do
+        SysrootKind::Llvm => {
+            for file in fs::read_dir(
+                default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"),
+            )
+            .unwrap()
+            {
+                let file = file.unwrap().path();
+                let file_name_str = file.file_name().unwrap().to_str().unwrap();
+                if file_name_str.contains("rustc_")
+                    || file_name_str.contains("chalk")
+                    || file_name_str.contains("tracing")
+                    || file_name_str.contains("regex")
+                {
+                    // These are large crates that are part of the rustc-dev component and are not
+                    // necessary to run regular programs.
+                    continue;
+                }
+                try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap()));
+            }
+
+            if target_triple != host_triple {
+                for file in fs::read_dir(
+                    default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
+                )
+                .unwrap()
+                {
+                    let file = file.unwrap().path();
+                    try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
+                }
+            }
+        }
+        SysrootKind::Clif => {
+            build_clif_sysroot_for_triple(channel, target_dir, host_triple, None);
+
+            if host_triple != target_triple {
+                // When cross-compiling it is often necessary to manually pick the right linker
+                let linker = if target_triple == "aarch64-unknown-linux-gnu" {
+                    Some("aarch64-linux-gnu-gcc")
+                } else {
+                    None
+                };
+                build_clif_sysroot_for_triple(channel, target_dir, target_triple, linker);
+            }
+
+            // Copy std for the host to the lib dir. This is necessary for the jit mode to find
+            // libstd.
+            for file in fs::read_dir(host_rustlib_lib).unwrap() {
+                let file = file.unwrap().path();
+                if file.file_name().unwrap().to_str().unwrap().contains("std-") {
+                    try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
+                }
+            }
+        }
+    }
+}
+
+fn build_clif_sysroot_for_triple(
+    channel: &str,
+    target_dir: &Path,
+    triple: &str,
+    linker: Option<&str>,
+) {
+    match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
+        Err(e) => {
+            eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
+            eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
+            process::exit(1);
+        }
+        Ok(source_version) => {
+            let rustc_version = get_rustc_version();
+            if source_version != rustc_version {
+                eprintln!("The patched sysroot source is outdated");
+                eprintln!("Source version: {}", source_version.trim());
+                eprintln!("Rustc version:  {}", rustc_version.trim());
+                eprintln!("Hint: Try `./y.rs prepare` to update the patched sysroot source");
+                process::exit(1);
+            }
+        }
+    }
+
+    let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
+
+    if !crate::config::get_bool("keep_sysroot") {
+        // Cleanup the target dir with the exception of build scripts and the incremental cache
+        for dir in ["build", "deps", "examples", "native"] {
+            if build_dir.join(dir).exists() {
+                fs::remove_dir_all(build_dir.join(dir)).unwrap();
+            }
+        }
+    }
+
+    // Build sysroot
+    let mut build_cmd = Command::new("cargo");
+    build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot");
+    let mut rustflags = "--clif -Zforce-unstable-if-unmarked".to_string();
+    if channel == "release" {
+        build_cmd.arg("--release");
+        rustflags.push_str(" -Zmir-opt-level=3");
+    }
+    if let Some(linker) = linker {
+        use std::fmt::Write;
+        write!(rustflags, " -Clinker={}", linker).unwrap();
+    }
+    build_cmd.env("RUSTFLAGS", rustflags);
+    build_cmd.env(
+        "RUSTC",
+        env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"),
+    );
+    // FIXME Enable incremental again once rust-lang/rust#74946 is fixed
+    build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
+    spawn_and_wait(build_cmd);
+
+    // Copy all relevant files to the sysroot
+    for entry in
+        fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
+            .unwrap()
+    {
+        let entry = entry.unwrap();
+        if let Some(ext) = entry.path().extension() {
+            if ext == "rmeta" || ext == "d" || ext == "dSYM" {
+                continue;
+            }
+        } else {
+            continue;
+        };
+        try_hard_link(
+            entry.path(),
+            target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
+        );
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs
new file mode 100644 (file)
index 0000000..ef540cf
--- /dev/null
@@ -0,0 +1,55 @@
+use std::{fs, process};
+
+fn load_config_file() -> Vec<(String, Option<String>)> {
+    fs::read_to_string("config.txt")
+        .unwrap()
+        .lines()
+        .map(|line| if let Some((line, _comment)) = line.split_once('#') { line } else { line })
+        .map(|line| line.trim())
+        .filter(|line| !line.is_empty())
+        .map(|line| {
+            if let Some((key, val)) = line.split_once('=') {
+                (key.trim().to_owned(), Some(val.trim().to_owned()))
+            } else {
+                (line.to_owned(), None)
+            }
+        })
+        .collect()
+}
+
+pub(crate) fn get_bool(name: &str) -> bool {
+    let values = load_config_file()
+        .into_iter()
+        .filter(|(key, _)| key == name)
+        .map(|(_, val)| val)
+        .collect::<Vec<_>>();
+    if values.is_empty() {
+        false
+    } else {
+        if values.iter().any(|val| val.is_some()) {
+            eprintln!("Boolean config `{}` has a value", name);
+            process::exit(1);
+        }
+        true
+    }
+}
+
+pub(crate) fn get_value(name: &str) -> Option<String> {
+    let values = load_config_file()
+        .into_iter()
+        .filter(|(key, _)| key == name)
+        .map(|(_, val)| val)
+        .collect::<Vec<_>>();
+    if values.is_empty() {
+        None
+    } else if values.len() == 1 {
+        if values[0].is_none() {
+            eprintln!("Config `{}` missing value", name);
+            process::exit(1);
+        }
+        values.into_iter().next().unwrap()
+    } else {
+        eprintln!("Config `{}` given multiple values: {:?}", name, values);
+        process::exit(1);
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
new file mode 100644 (file)
index 0000000..401b827
--- /dev/null
@@ -0,0 +1,133 @@
+use std::env;
+use std::ffi::OsStr;
+use std::ffi::OsString;
+use std::fs;
+use std::path::Path;
+use std::process::Command;
+
+use crate::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
+use crate::utils::{copy_dir_recursively, spawn_and_wait};
+
+pub(crate) fn prepare() {
+    prepare_sysroot();
+
+    eprintln!("[INSTALL] hyperfine");
+    Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
+
+    clone_repo(
+        "rand",
+        "https://github.com/rust-random/rand.git",
+        "0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
+    );
+    apply_patches("rand", Path::new("rand"));
+
+    clone_repo(
+        "regex",
+        "https://github.com/rust-lang/regex.git",
+        "341f207c1071f7290e3f228c710817c280c8dca1",
+    );
+
+    clone_repo(
+        "simple-raytracer",
+        "https://github.com/ebobby/simple-raytracer",
+        "804a7a21b9e673a482797aa289a18ed480e4d813",
+    );
+
+    eprintln!("[LLVM BUILD] simple-raytracer");
+    let mut build_cmd = Command::new("cargo");
+    build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer");
+    spawn_and_wait(build_cmd);
+    fs::copy(
+        Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")),
+        // FIXME use get_file_name here too once testing is migrated to rust
+        "simple-raytracer/raytracer_cg_llvm",
+    )
+    .unwrap();
+}
+
+fn prepare_sysroot() {
+    let rustc_path = get_rustc_path();
+    let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
+    let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
+
+    assert!(sysroot_src_orig.exists());
+
+    if sysroot_src.exists() {
+        fs::remove_dir_all(&sysroot_src).unwrap();
+    }
+    fs::create_dir_all(sysroot_src.join("library")).unwrap();
+    eprintln!("[COPY] sysroot src");
+    copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
+
+    let rustc_version = get_rustc_version();
+    fs::write(
+        Path::new("build_sysroot").join("rustc_version"),
+        &rustc_version,
+    )
+    .unwrap();
+
+    eprintln!("[GIT] init");
+    let mut git_init_cmd = Command::new("git");
+    git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
+    spawn_and_wait(git_init_cmd);
+
+    let mut git_add_cmd = Command::new("git");
+    git_add_cmd.arg("add").arg(".").current_dir(&sysroot_src);
+    spawn_and_wait(git_add_cmd);
+
+    let mut git_commit_cmd = Command::new("git");
+    git_commit_cmd
+        .arg("commit")
+        .arg("-m")
+        .arg("Initial commit")
+        .arg("-q")
+        .current_dir(&sysroot_src);
+    spawn_and_wait(git_commit_cmd);
+
+    apply_patches("sysroot", &sysroot_src);
+
+    clone_repo(
+        "build_sysroot/compiler-builtins",
+        "https://github.com/rust-lang/compiler-builtins.git",
+        "0.1.46",
+    );
+    apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins"));
+}
+
+fn clone_repo(target_dir: &str, repo: &str, rev: &str) {
+    eprintln!("[CLONE] {}", repo);
+    // Ignore exit code as the repo may already have been checked out
+    Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap();
+
+    let mut clean_cmd = Command::new("git");
+    clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir);
+    spawn_and_wait(clean_cmd);
+
+    let mut checkout_cmd = Command::new("git");
+    checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir);
+    spawn_and_wait(checkout_cmd);
+}
+
+fn get_patches(crate_name: &str) -> Vec<OsString> {
+    let mut patches: Vec<_> = fs::read_dir("patches")
+        .unwrap()
+        .map(|entry| entry.unwrap().path())
+        .filter(|path| path.extension() == Some(OsStr::new("patch")))
+        .map(|path| path.file_name().unwrap().to_owned())
+        .filter(|file_name| {
+            file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name)
+        })
+        .collect();
+    patches.sort();
+    patches
+}
+
+fn apply_patches(crate_name: &str, target_dir: &Path) {
+    for patch in get_patches(crate_name) {
+        eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch);
+        let patch_arg = env::current_dir().unwrap().join("patches").join(patch);
+        let mut apply_patch_cmd = Command::new("git");
+        apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir);
+        spawn_and_wait(apply_patch_cmd);
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
new file mode 100644 (file)
index 0000000..9206bb0
--- /dev/null
@@ -0,0 +1,65 @@
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+
+pub(crate) fn get_rustc_version() -> String {
+    let version_info =
+        Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
+    String::from_utf8(version_info).unwrap()
+}
+
+pub(crate) fn get_host_triple() -> String {
+    let version_info =
+        Command::new("rustc").stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout;
+    String::from_utf8(version_info)
+        .unwrap()
+        .lines()
+        .to_owned()
+        .find(|line| line.starts_with("host"))
+        .unwrap()
+        .split(":")
+        .nth(1)
+        .unwrap()
+        .trim()
+        .to_owned()
+}
+
+pub(crate) fn get_rustc_path() -> PathBuf {
+    let rustc_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "rustc"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
+}
+
+pub(crate) fn get_default_sysroot() -> PathBuf {
+    let default_sysroot = Command::new("rustc")
+        .stderr(Stdio::inherit())
+        .args(&["--print", "sysroot"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned()
+}
+
+pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
+    let file_name = Command::new("rustc")
+        .stderr(Stdio::inherit())
+        .args(&[
+            "--crate-name",
+            crate_name,
+            "--crate-type",
+            crate_type,
+            "--print",
+            "file-names",
+            "-",
+        ])
+        .output()
+        .unwrap()
+        .stdout;
+    let file_name = String::from_utf8(file_name).unwrap().trim().to_owned();
+    assert!(!file_name.contains('\n'));
+    assert!(file_name.contains(crate_name));
+    file_name
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
new file mode 100644 (file)
index 0000000..12b5d70
--- /dev/null
@@ -0,0 +1,35 @@
+use std::fs;
+use std::path::Path;
+use std::process::{self, Command};
+
+#[track_caller]
+pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+    if let Err(_) = fs::hard_link(src, dst) {
+        fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed
+    }
+}
+
+#[track_caller]
+pub(crate) fn spawn_and_wait(mut cmd: Command) {
+    if !cmd.spawn().unwrap().wait().unwrap().success() {
+        process::exit(1);
+    }
+}
+
+pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
+    for entry in fs::read_dir(from).unwrap() {
+        let entry = entry.unwrap();
+        let filename = entry.file_name();
+        if filename == "." || filename == ".." {
+            continue;
+        }
+        if entry.metadata().unwrap().is_dir() {
+            fs::create_dir(to.join(&filename)).unwrap();
+            copy_dir_recursively(&from.join(&filename), &to.join(&filename));
+        } else {
+            fs::copy(from.join(&filename), to.join(&filename)).unwrap();
+        }
+    }
+}
index a7bbeb05cac5a094bc0103d5f676452cef77f8a5..f4f8c82d69f10814a052af9e45b7e79bfc61d301 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/env bash
 set -e
 
-rm -rf target/ build/ build_sysroot/{sysroot_src/,target/,compiler-builtins/} perf.data{,.old}
+rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
+rm -rf target/ build/ perf.data{,.old}
 rm -rf rand/ regex/ simple-raytracer/
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
new file mode 100644 (file)
index 0000000..b14db27
--- /dev/null
@@ -0,0 +1,17 @@
+# This file allows configuring the build system.
+
+# Which triple to produce a compiler toolchain for.
+#
+# Defaults to the default triple of rustc on the host system.
+#host = x86_64-unknown-linux-gnu
+
+# Which triple to build libraries (core/alloc/std/test/proc_macro) for.
+#
+# Defaults to `host`.
+#target = x86_64-unknown-linux-gnu
+
+# Disables cleaning of the sysroot dir. This will cause old compiled artifacts to be re-used when
+# the sysroot source hasn't changed. This is useful when the codegen backend hasn't been modified.
+# This option can be changed while the build system is already running for as long as sysroot
+# building hasn't started yet.
+#keep_sysroot
diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch
deleted file mode 100644 (file)
index 7daea99..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 1d574bf5e32d51641dcacaf8ef777e95b44f6f2a Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Thu, 18 Feb 2021 18:30:55 +0100
-Subject: [PATCH] Disable 128bit atomic operations
-
-Cranelift doesn't support them yet
----
- src/mem/mod.rs | 12 ------------
- 1 file changed, 12 deletions(-)
-
-diff --git a/src/mem/mod.rs b/src/mem/mod.rs
-index 107762c..2d1ae10 100644
---- a/src/mem/mod.rs
-+++ b/src/mem/mod.rs
-@@ -137,10 +137,6 @@ intrinsics! {
-     pub extern "C" fn __llvm_memcpy_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
-         memcpy_element_unordered_atomic(dest, src, bytes);
-     }
--    #[cfg(target_has_atomic_load_store = "128")]
--    pub extern "C" fn __llvm_memcpy_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
--        memcpy_element_unordered_atomic(dest, src, bytes);
--    }
-     #[cfg(target_has_atomic_load_store = "8")]
-     pub extern "C" fn __llvm_memmove_element_unordered_atomic_1(dest: *mut u8, src: *const u8, bytes: usize) -> () {
-@@ -158,10 +154,6 @@ intrinsics! {
-     pub extern "C" fn __llvm_memmove_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
-         memmove_element_unordered_atomic(dest, src, bytes);
-     }
--    #[cfg(target_has_atomic_load_store = "128")]
--    pub extern "C" fn __llvm_memmove_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
--        memmove_element_unordered_atomic(dest, src, bytes);
--    }
-     #[cfg(target_has_atomic_load_store = "8")]
-     pub extern "C" fn __llvm_memset_element_unordered_atomic_1(s: *mut u8, c: u8, bytes: usize) -> () {
-@@ -179,8 +171,4 @@ intrinsics! {
-     pub extern "C" fn __llvm_memset_element_unordered_atomic_8(s: *mut u64, c: u8, bytes: usize) -> () {
-         memset_element_unordered_atomic(s, c, bytes);
-     }
--    #[cfg(target_has_atomic_load_store = "128")]
--    pub extern "C" fn __llvm_memset_element_unordered_atomic_16(s: *mut u128, c: u8, bytes: usize) -> () {
--        memset_element_unordered_atomic(s, c, bytes);
--    }
- }
--- 
-2.26.2.7.g19db9cfb68
-
diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch b/compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch
deleted file mode 100644 (file)
index 01dc0fc..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 9c5663e36391fa20becf84f3af2e82afa5bb720b Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sat, 15 Aug 2020 19:56:03 +0200
-Subject: [PATCH] [rand] Enable c2-chacha simd feature
-
----
- rand_chacha/Cargo.toml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/rand_chacha/Cargo.toml b/rand_chacha/Cargo.toml
-index 9190b7f..872cca2 100644
---- a/rand_chacha/Cargo.toml
-+++ b/rand_chacha/Cargo.toml
-@@ -24,5 +24,5 @@ ppv-lite86 = { version = "0.2.8", default-features = false }
- [features]
- default = ["std"]
--std = ["ppv-lite86/std"]
-+std = ["ppv-lite86/std", "ppv-lite86/simd"]
- simd = [] # deprecated
--- 
-2.20.1
-
diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch b/compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch
deleted file mode 100644 (file)
index 19fd20d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sat, 15 Aug 2020 20:04:38 +0200
-Subject: [PATCH] [rand] Disable failing test
-
----
- src/distributions/uniform.rs | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs
-index 480b859..c80bb6f 100644
---- a/src/distributions/uniform.rs
-+++ b/src/distributions/uniform.rs
-@@ -1085,7 +1085,7 @@ mod tests {
-             _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
-         }
-     }
--    
-+
-     #[test]
-     #[cfg(feature = "serde1")]
-     fn test_uniform_serialization() {
-@@ -1314,6 +1314,7 @@ mod tests {
-         not(target_arch = "wasm32"),
-         not(target_arch = "asmjs")
-     ))]
-+    #[ignore] // FIXME
-     fn test_float_assertions() {
-         use super::SampleUniform;
-         use std::panic::catch_unwind;
--- 
-2.20.1
-
index 3eee3b554e3b62ccd06db4acbb819c5c760983e4..956d5905a97adfbf460676559a73b32728b06b00 100644 (file)
@@ -2,14 +2,14 @@
 
 rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
 
-Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`).
+Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`).
 
 ## Cargo
 
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo.sh build
+$ $cg_clif_dir/build/cargo build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
@@ -30,7 +30,7 @@ In jit mode cg_clif will immediately execute your code without creating an execu
 > The jit mode will probably need cargo integration to make this possible.
 
 ```bash
-$ $cg_clif_dir/build/cargo.sh jit
+$ $cg_clif_dir/build/cargo jit
 ```
 
 or
@@ -40,11 +40,10 @@ $ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.
 ```
 
 There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
-first called. It currently does not work with multi-threaded programs. When a not yet compiled
-function is called from another thread than the main thread, you will get an ICE.
+first called.
 
 ```bash
-$ $cg_clif_dir/build/cargo.sh lazy-jit
+$ $cg_clif_dir/build/cargo lazy-jit
 ```
 
 ## Shell
index 6570f2bf9f297fbccf66a4681d639a91f266a18f..d997ce6d1b379044fd3675420e9837739ef0aa10 100644 (file)
@@ -292,7 +292,7 @@ struct ExternTypeWrapper {
     #[cfg(not(any(jit, windows)))]
     test_tls();
 
-    #[cfg(all(not(jit), target_os = "linux"))]
+    #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
     unsafe {
         global_asm_test();
     }
@@ -303,12 +303,12 @@ struct ExternTypeWrapper {
     assert_eq!(*REF1, *REF2);
 }
 
-#[cfg(all(not(jit), target_os = "linux"))]
+#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
 extern "C" {
     fn global_asm_test();
 }
 
-#[cfg(all(not(jit), target_os = "linux"))]
+#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
 global_asm! {
     "
     .global global_asm_test
index 7d608df9253df85fe72e5c38bfb438b29bc267ab..5bc51a541b58c7d63b0939976ab2d8869983d24b 100644 (file)
@@ -15,8 +15,6 @@ fn main() {
     let stderr = ::std::io::stderr();
     let mut stderr = stderr.lock();
 
-    // FIXME support lazy jit when multi threading
-    #[cfg(not(lazy_jit))]
     std::thread::spawn(move || {
         println!("Hello from another thread!");
     });
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch
new file mode 100644 (file)
index 0000000..7daea99
--- /dev/null
@@ -0,0 +1,48 @@
+From 1d574bf5e32d51641dcacaf8ef777e95b44f6f2a Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Thu, 18 Feb 2021 18:30:55 +0100
+Subject: [PATCH] Disable 128bit atomic operations
+
+Cranelift doesn't support them yet
+---
+ src/mem/mod.rs | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/src/mem/mod.rs b/src/mem/mod.rs
+index 107762c..2d1ae10 100644
+--- a/src/mem/mod.rs
++++ b/src/mem/mod.rs
+@@ -137,10 +137,6 @@ intrinsics! {
+     pub extern "C" fn __llvm_memcpy_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
+         memcpy_element_unordered_atomic(dest, src, bytes);
+     }
+-    #[cfg(target_has_atomic_load_store = "128")]
+-    pub extern "C" fn __llvm_memcpy_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
+-        memcpy_element_unordered_atomic(dest, src, bytes);
+-    }
+     #[cfg(target_has_atomic_load_store = "8")]
+     pub extern "C" fn __llvm_memmove_element_unordered_atomic_1(dest: *mut u8, src: *const u8, bytes: usize) -> () {
+@@ -158,10 +154,6 @@ intrinsics! {
+     pub extern "C" fn __llvm_memmove_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
+         memmove_element_unordered_atomic(dest, src, bytes);
+     }
+-    #[cfg(target_has_atomic_load_store = "128")]
+-    pub extern "C" fn __llvm_memmove_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
+-        memmove_element_unordered_atomic(dest, src, bytes);
+-    }
+     #[cfg(target_has_atomic_load_store = "8")]
+     pub extern "C" fn __llvm_memset_element_unordered_atomic_1(s: *mut u8, c: u8, bytes: usize) -> () {
+@@ -179,8 +171,4 @@ intrinsics! {
+     pub extern "C" fn __llvm_memset_element_unordered_atomic_8(s: *mut u64, c: u8, bytes: usize) -> () {
+         memset_element_unordered_atomic(s, c, bytes);
+     }
+-    #[cfg(target_has_atomic_load_store = "128")]
+-    pub extern "C" fn __llvm_memset_element_unordered_atomic_16(s: *mut u128, c: u8, bytes: usize) -> () {
+-        memset_element_unordered_atomic(s, c, bytes);
+-    }
+ }
+-- 
+2.26.2.7.g19db9cfb68
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch b/compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch
new file mode 100644 (file)
index 0000000..01dc0fc
--- /dev/null
@@ -0,0 +1,23 @@
+From 9c5663e36391fa20becf84f3af2e82afa5bb720b Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sat, 15 Aug 2020 19:56:03 +0200
+Subject: [PATCH] [rand] Enable c2-chacha simd feature
+
+---
+ rand_chacha/Cargo.toml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rand_chacha/Cargo.toml b/rand_chacha/Cargo.toml
+index 9190b7f..872cca2 100644
+--- a/rand_chacha/Cargo.toml
++++ b/rand_chacha/Cargo.toml
+@@ -24,5 +24,5 @@ ppv-lite86 = { version = "0.2.8", default-features = false }
+ [features]
+ default = ["std"]
+-std = ["ppv-lite86/std"]
++std = ["ppv-lite86/std", "ppv-lite86/simd"]
+ simd = [] # deprecated
+-- 
+2.20.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch b/compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch
new file mode 100644 (file)
index 0000000..19fd20d
--- /dev/null
@@ -0,0 +1,33 @@
+From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sat, 15 Aug 2020 20:04:38 +0200
+Subject: [PATCH] [rand] Disable failing test
+
+---
+ src/distributions/uniform.rs | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs
+index 480b859..c80bb6f 100644
+--- a/src/distributions/uniform.rs
++++ b/src/distributions/uniform.rs
+@@ -1085,7 +1085,7 @@ mod tests {
+             _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
+         }
+     }
+-    
++
+     #[test]
+     #[cfg(feature = "serde1")]
+     fn test_uniform_serialization() {
+@@ -1314,6 +1314,7 @@ mod tests {
+         not(target_arch = "wasm32"),
+         not(target_arch = "asmjs")
+     ))]
++    #[ignore] // FIXME
+     fn test_float_assertions() {
+         use super::SampleUniform;
+         use std::panic::catch_unwind;
+-- 
+2.20.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch
deleted file mode 100644 (file)
index ba0eaac..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sun, 24 Nov 2019 15:10:23 +0100
-Subject: [PATCH] [core] Disable not compiling tests
-
----
- library/core/tests/Cargo.toml         | 8 ++++++++
- library/core/tests/num/flt2dec/mod.rs | 1 -
- library/core/tests/num/int_macros.rs  | 2 ++
- library/core/tests/num/uint_macros.rs | 2 ++
- library/core/tests/ptr.rs             | 2 ++
- library/core/tests/slice.rs           | 2 ++
- 6 files changed, 16 insertions(+), 1 deletion(-)
- create mode 100644 library/core/tests/Cargo.toml
-
-diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
-new file mode 100644
-index 0000000..46fd999
---- /dev/null
-+++ b/library/core/tests/Cargo.toml
-@@ -0,0 +1,8 @@
-+[package]
-+name = "core"
-+version = "0.0.0"
-+edition = "2018"
-+
-+[lib]
-+name = "coretests"
-+path = "lib.rs"
-diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
-index a35897e..f0bf645 100644
---- a/library/core/tests/num/flt2dec/mod.rs
-+++ b/library/core/tests/num/flt2dec/mod.rs
-@@ -13,7 +13,6 @@ mod strategy {
-     mod dragon;
-     mod grisu;
- }
--mod random;
- pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
-     match decode(v).1 {
-diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
-index 1a6be3a..42dbd59 100644
---- a/library/core/tests/ptr.rs
-+++ b/library/core/tests/ptr.rs
-@@ -250,6 +250,7 @@ fn test_unsized_nonnull() {
-     assert!(ys == zs);
- }
-+/*
- #[test]
- #[allow(warnings)]
- // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
-@@ -289,6 +290,7 @@ fn write_unaligned_drop() {
-     }
-     DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
- }
-+*/
- #[test]
- fn align_offset_zst() {
-diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
-index 6609bc3..241b497 100644
---- a/library/core/tests/slice.rs
-+++ b/library/core/tests/slice.rs
-@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() {
-     }
- }
-+/*
- #[test]
- #[cfg(not(target_arch = "wasm32"))]
- fn sort_unstable() {
-@@ -1394,6 +1395,7 @@ fn partition_at_index() {
-     v.select_nth_unstable(0);
-     assert!(v == [0xDEADBEEF]);
- }
-+*/
- #[test]
- #[should_panic(expected = "index 0 greater than length of slice")]
---
-2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch
new file mode 100644 (file)
index 0000000..ba0eaac
--- /dev/null
@@ -0,0 +1,83 @@
+From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sun, 24 Nov 2019 15:10:23 +0100
+Subject: [PATCH] [core] Disable not compiling tests
+
+---
+ library/core/tests/Cargo.toml         | 8 ++++++++
+ library/core/tests/num/flt2dec/mod.rs | 1 -
+ library/core/tests/num/int_macros.rs  | 2 ++
+ library/core/tests/num/uint_macros.rs | 2 ++
+ library/core/tests/ptr.rs             | 2 ++
+ library/core/tests/slice.rs           | 2 ++
+ 6 files changed, 16 insertions(+), 1 deletion(-)
+ create mode 100644 library/core/tests/Cargo.toml
+
+diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
+new file mode 100644
+index 0000000..46fd999
+--- /dev/null
++++ b/library/core/tests/Cargo.toml
+@@ -0,0 +1,8 @@
++[package]
++name = "core"
++version = "0.0.0"
++edition = "2018"
++
++[lib]
++name = "coretests"
++path = "lib.rs"
+diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
+index a35897e..f0bf645 100644
+--- a/library/core/tests/num/flt2dec/mod.rs
++++ b/library/core/tests/num/flt2dec/mod.rs
+@@ -13,7 +13,6 @@ mod strategy {
+     mod dragon;
+     mod grisu;
+ }
+-mod random;
+ pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+     match decode(v).1 {
+diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
+index 1a6be3a..42dbd59 100644
+--- a/library/core/tests/ptr.rs
++++ b/library/core/tests/ptr.rs
+@@ -250,6 +250,7 @@ fn test_unsized_nonnull() {
+     assert!(ys == zs);
+ }
++/*
+ #[test]
+ #[allow(warnings)]
+ // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
+@@ -289,6 +290,7 @@ fn write_unaligned_drop() {
+     }
+     DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
+ }
++*/
+ #[test]
+ fn align_offset_zst() {
+diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
+index 6609bc3..241b497 100644
+--- a/library/core/tests/slice.rs
++++ b/library/core/tests/slice.rs
+@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() {
+     }
+ }
++/*
+ #[test]
+ #[cfg(not(target_arch = "wasm32"))]
+ fn sort_unstable() {
+@@ -1394,6 +1395,7 @@ fn partition_at_index() {
+     v.select_nth_unstable(0);
+     assert!(v == [0xDEADBEEF]);
+ }
++*/
+ #[test]
+ #[should_panic(expected = "index 0 greater than length of slice")]
+--
+2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch
deleted file mode 100644 (file)
index 5d2c304..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sun, 24 Nov 2019 15:34:06 +0100
-Subject: [PATCH] [core] Ignore failing tests
-
----
- library/core/tests/iter.rs       |  4 ++++
- library/core/tests/num/bignum.rs | 10 ++++++++++
- library/core/tests/num/mod.rs    |  5 +++--
- library/core/tests/time.rs       |  1 +
- 4 files changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
-index 4bc44e9..8e3c7a4 100644
---- a/library/core/tests/array.rs
-+++ b/library/core/tests/array.rs
-@@ -242,6 +242,7 @@ fn iterator_drops() {
-     assert_eq!(i.get(), 5);
- }
-+/*
- // This test does not work on targets without panic=unwind support.
- // To work around this problem, test is marked is should_panic, so it will
- // be automagically skipped on unsuitable targets, such as
-@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
-     assert_eq!(COUNTER.load(Relaxed), 0);
-     panic!("test succeeded")
- }
-+*/
- #[test]
- fn empty_array_is_always_default() {
-@@ -304,6 +304,7 @@ fn array_map() {
-     assert_eq!(b, [1, 2, 3]);
- }
-+/*
- // See note on above test for why `should_panic` is used.
- #[test]
- #[should_panic(expected = "test succeeded")]
-@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
-     assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
-     panic!("test succeeded")
- }
-+*/
- #[test]
- fn cell_allows_array_cycle() {
-diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
-index a17c094..5bb11d2 100644
---- a/library/core/tests/num/mod.rs
-+++ b/library/core/tests/num/mod.rs
-@@ -651,11 +651,12 @@ macro_rules! test_float {
-                 assert_eq!((9.0 as $fty).min($neginf), $neginf);
-                 assert_eq!(($neginf as $fty).min(-9.0), $neginf);
-                 assert_eq!((-9.0 as $fty).min($neginf), $neginf);
--                assert_eq!(($nan as $fty).min(9.0), 9.0);
--                assert_eq!(($nan as $fty).min(-9.0), -9.0);
--                assert_eq!((9.0 as $fty).min($nan), 9.0);
--                assert_eq!((-9.0 as $fty).min($nan), -9.0);
--                assert!(($nan as $fty).min($nan).is_nan());
-+                // Cranelift fmin has NaN propagation
-+                //assert_eq!(($nan as $fty).min(9.0), 9.0);
-+                //assert_eq!(($nan as $fty).min(-9.0), -9.0);
-+                //assert_eq!((9.0 as $fty).min($nan), 9.0);
-+                //assert_eq!((-9.0 as $fty).min($nan), -9.0);
-+                //assert!(($nan as $fty).min($nan).is_nan());
-             }
-             #[test]
-             fn max() {
-@@ -673,11 +674,12 @@ macro_rules! test_float {
-                 assert_eq!((9.0 as $fty).max($neginf), 9.0);
-                 assert_eq!(($neginf as $fty).max(-9.0), -9.0);
-                 assert_eq!((-9.0 as $fty).max($neginf), -9.0);
--                assert_eq!(($nan as $fty).max(9.0), 9.0);
--                assert_eq!(($nan as $fty).max(-9.0), -9.0);
--                assert_eq!((9.0 as $fty).max($nan), 9.0);
--                assert_eq!((-9.0 as $fty).max($nan), -9.0);
--                assert!(($nan as $fty).max($nan).is_nan());
-+                // Cranelift fmax has NaN propagation
-+                //assert_eq!(($nan as $fty).max(9.0), 9.0);
-+                //assert_eq!(($nan as $fty).max(-9.0), -9.0);
-+                //assert_eq!((9.0 as $fty).max($nan), 9.0);
-+                //assert_eq!((-9.0 as $fty).max($nan), -9.0);
-+                //assert!(($nan as $fty).max($nan).is_nan());
-             }
-             #[test]
-             fn rem_euclid() {
--- 
-2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch
new file mode 100644 (file)
index 0000000..5d2c304
--- /dev/null
@@ -0,0 +1,90 @@
+From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sun, 24 Nov 2019 15:34:06 +0100
+Subject: [PATCH] [core] Ignore failing tests
+
+---
+ library/core/tests/iter.rs       |  4 ++++
+ library/core/tests/num/bignum.rs | 10 ++++++++++
+ library/core/tests/num/mod.rs    |  5 +++--
+ library/core/tests/time.rs       |  1 +
+ 4 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
+index 4bc44e9..8e3c7a4 100644
+--- a/library/core/tests/array.rs
++++ b/library/core/tests/array.rs
+@@ -242,6 +242,7 @@ fn iterator_drops() {
+     assert_eq!(i.get(), 5);
+ }
++/*
+ // This test does not work on targets without panic=unwind support.
+ // To work around this problem, test is marked is should_panic, so it will
+ // be automagically skipped on unsuitable targets, such as
+@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
+     assert_eq!(COUNTER.load(Relaxed), 0);
+     panic!("test succeeded")
+ }
++*/
+ #[test]
+ fn empty_array_is_always_default() {
+@@ -304,6 +304,7 @@ fn array_map() {
+     assert_eq!(b, [1, 2, 3]);
+ }
++/*
+ // See note on above test for why `should_panic` is used.
+ #[test]
+ #[should_panic(expected = "test succeeded")]
+@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
+     assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
+     panic!("test succeeded")
+ }
++*/
+ #[test]
+ fn cell_allows_array_cycle() {
+diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
+index a17c094..5bb11d2 100644
+--- a/library/core/tests/num/mod.rs
++++ b/library/core/tests/num/mod.rs
+@@ -651,11 +651,12 @@ macro_rules! test_float {
+                 assert_eq!((9.0 as $fty).min($neginf), $neginf);
+                 assert_eq!(($neginf as $fty).min(-9.0), $neginf);
+                 assert_eq!((-9.0 as $fty).min($neginf), $neginf);
+-                assert_eq!(($nan as $fty).min(9.0), 9.0);
+-                assert_eq!(($nan as $fty).min(-9.0), -9.0);
+-                assert_eq!((9.0 as $fty).min($nan), 9.0);
+-                assert_eq!((-9.0 as $fty).min($nan), -9.0);
+-                assert!(($nan as $fty).min($nan).is_nan());
++                // Cranelift fmin has NaN propagation
++                //assert_eq!(($nan as $fty).min(9.0), 9.0);
++                //assert_eq!(($nan as $fty).min(-9.0), -9.0);
++                //assert_eq!((9.0 as $fty).min($nan), 9.0);
++                //assert_eq!((-9.0 as $fty).min($nan), -9.0);
++                //assert!(($nan as $fty).min($nan).is_nan());
+             }
+             #[test]
+             fn max() {
+@@ -673,11 +674,12 @@ macro_rules! test_float {
+                 assert_eq!((9.0 as $fty).max($neginf), 9.0);
+                 assert_eq!(($neginf as $fty).max(-9.0), -9.0);
+                 assert_eq!((-9.0 as $fty).max($neginf), -9.0);
+-                assert_eq!(($nan as $fty).max(9.0), 9.0);
+-                assert_eq!(($nan as $fty).max(-9.0), -9.0);
+-                assert_eq!((9.0 as $fty).max($nan), 9.0);
+-                assert_eq!((-9.0 as $fty).max($nan), -9.0);
+-                assert!(($nan as $fty).max($nan).is_nan());
++                // Cranelift fmax has NaN propagation
++                //assert_eq!(($nan as $fty).max(9.0), 9.0);
++                //assert_eq!(($nan as $fty).max(-9.0), -9.0);
++                //assert_eq!((9.0 as $fty).max($nan), 9.0);
++                //assert_eq!((-9.0 as $fty).max($nan), -9.0);
++                //assert!(($nan as $fty).max($nan).is_nan());
+             }
+             #[test]
+             fn rem_euclid() {
+-- 
+2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch
deleted file mode 100644 (file)
index 32e5930..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-From 894e07dfec2624ba539129b1c1d63e1d7d812bda Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Thu, 18 Feb 2021 18:45:28 +0100
-Subject: [PATCH] Disable 128bit atomic operations
-
-Cranelift doesn't support them yet
----
- library/core/src/sync/atomic.rs | 38 ---------------------------------
- library/core/tests/atomic.rs    |  4 ----
- library/std/src/panic.rs        |  6 ------
- 3 files changed, 48 deletions(-)
-
-diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
-index 81c9e1d..65c9503 100644
---- a/library/core/src/sync/atomic.rs
-+++ b/library/core/src/sync/atomic.rs
-@@ -2228,44 +2228,6 @@ atomic_int! {
-     "AtomicU64::new(0)",
-     u64 AtomicU64 ATOMIC_U64_INIT
- }
--#[cfg(target_has_atomic_load_store = "128")]
--atomic_int! {
--    cfg(target_has_atomic = "128"),
--    cfg(target_has_atomic_equal_alignment = "128"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    "i128",
--    "#![feature(integer_atomics)]\n\n",
--    atomic_min, atomic_max,
--    16,
--    "AtomicI128::new(0)",
--    i128 AtomicI128 ATOMIC_I128_INIT
--}
--#[cfg(target_has_atomic_load_store = "128")]
--atomic_int! {
--    cfg(target_has_atomic = "128"),
--    cfg(target_has_atomic_equal_alignment = "128"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
--    unstable(feature = "integer_atomics", issue = "32976"),
--    "u128",
--    "#![feature(integer_atomics)]\n\n",
--    atomic_umin, atomic_umax,
--    16,
--    "AtomicU128::new(0)",
--    u128 AtomicU128 ATOMIC_U128_INIT
--}
- macro_rules! atomic_int_ptr_sized {
-     ( $($target_pointer_width:literal $align:literal)* ) => { $(
-diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs
-index 2d1e449..cb6da5d 100644
---- a/library/core/tests/atomic.rs
-+++ b/library/core/tests/atomic.rs
-@@ -145,10 +145,6 @@ fn atomic_alignment() {
-     assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
-     #[cfg(target_has_atomic = "64")]
-     assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>());
--    #[cfg(target_has_atomic = "128")]
--    assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>());
--    #[cfg(target_has_atomic = "128")]
--    assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>());
-     #[cfg(target_has_atomic = "ptr")]
-     assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
-     #[cfg(target_has_atomic = "ptr")]
-diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
-index 89a822a..779fd88 100644
---- a/library/std/src/panic.rs
-+++ b/library/std/src/panic.rs
-@@ -279,9 +279,6 @@ impl RefUnwindSafe for atomic::AtomicI32 {}
- #[cfg(target_has_atomic_load_store = "64")]
- #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
- impl RefUnwindSafe for atomic::AtomicI64 {}
--#[cfg(target_has_atomic_load_store = "128")]
--#[unstable(feature = "integer_atomics", issue = "32976")]
--impl RefUnwindSafe for atomic::AtomicI128 {}
- #[cfg(target_has_atomic_load_store = "ptr")]
- #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
-@@ -298,9 +295,6 @@ impl RefUnwindSafe for atomic::AtomicU32 {}
- #[cfg(target_has_atomic_load_store = "64")]
- #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
- impl RefUnwindSafe for atomic::AtomicU64 {}
--#[cfg(target_has_atomic_load_store = "128")]
--#[unstable(feature = "integer_atomics", issue = "32976")]
--impl RefUnwindSafe for atomic::AtomicU128 {}
- #[cfg(target_has_atomic_load_store = "8")]
- #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
--- 
-2.26.2.7.g19db9cfb68
-
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch
new file mode 100644 (file)
index 0000000..32e5930
--- /dev/null
@@ -0,0 +1,103 @@
+From 894e07dfec2624ba539129b1c1d63e1d7d812bda Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Thu, 18 Feb 2021 18:45:28 +0100
+Subject: [PATCH] Disable 128bit atomic operations
+
+Cranelift doesn't support them yet
+---
+ library/core/src/sync/atomic.rs | 38 ---------------------------------
+ library/core/tests/atomic.rs    |  4 ----
+ library/std/src/panic.rs        |  6 ------
+ 3 files changed, 48 deletions(-)
+
+diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
+index 81c9e1d..65c9503 100644
+--- a/library/core/src/sync/atomic.rs
++++ b/library/core/src/sync/atomic.rs
+@@ -2228,44 +2228,6 @@ atomic_int! {
+     "AtomicU64::new(0)",
+     u64 AtomicU64 ATOMIC_U64_INIT
+ }
+-#[cfg(target_has_atomic_load_store = "128")]
+-atomic_int! {
+-    cfg(target_has_atomic = "128"),
+-    cfg(target_has_atomic_equal_alignment = "128"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    "i128",
+-    "#![feature(integer_atomics)]\n\n",
+-    atomic_min, atomic_max,
+-    16,
+-    "AtomicI128::new(0)",
+-    i128 AtomicI128 ATOMIC_I128_INIT
+-}
+-#[cfg(target_has_atomic_load_store = "128")]
+-atomic_int! {
+-    cfg(target_has_atomic = "128"),
+-    cfg(target_has_atomic_equal_alignment = "128"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
+-    unstable(feature = "integer_atomics", issue = "32976"),
+-    "u128",
+-    "#![feature(integer_atomics)]\n\n",
+-    atomic_umin, atomic_umax,
+-    16,
+-    "AtomicU128::new(0)",
+-    u128 AtomicU128 ATOMIC_U128_INIT
+-}
+ macro_rules! atomic_int_ptr_sized {
+     ( $($target_pointer_width:literal $align:literal)* ) => { $(
+diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs
+index 2d1e449..cb6da5d 100644
+--- a/library/core/tests/atomic.rs
++++ b/library/core/tests/atomic.rs
+@@ -145,10 +145,6 @@ fn atomic_alignment() {
+     assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
+     #[cfg(target_has_atomic = "64")]
+     assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>());
+-    #[cfg(target_has_atomic = "128")]
+-    assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>());
+-    #[cfg(target_has_atomic = "128")]
+-    assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>());
+     #[cfg(target_has_atomic = "ptr")]
+     assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
+     #[cfg(target_has_atomic = "ptr")]
+diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
+index 89a822a..779fd88 100644
+--- a/library/std/src/panic.rs
++++ b/library/std/src/panic.rs
+@@ -279,9 +279,6 @@ impl RefUnwindSafe for atomic::AtomicI32 {}
+ #[cfg(target_has_atomic_load_store = "64")]
+ #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
+ impl RefUnwindSafe for atomic::AtomicI64 {}
+-#[cfg(target_has_atomic_load_store = "128")]
+-#[unstable(feature = "integer_atomics", issue = "32976")]
+-impl RefUnwindSafe for atomic::AtomicI128 {}
+ #[cfg(target_has_atomic_load_store = "ptr")]
+ #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+@@ -298,9 +295,6 @@ impl RefUnwindSafe for atomic::AtomicU32 {}
+ #[cfg(target_has_atomic_load_store = "64")]
+ #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
+ impl RefUnwindSafe for atomic::AtomicU64 {}
+-#[cfg(target_has_atomic_load_store = "128")]
+-#[unstable(feature = "integer_atomics", issue = "32976")]
+-impl RefUnwindSafe for atomic::AtomicU128 {}
+ #[cfg(target_has_atomic_load_store = "8")]
+ #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+-- 
+2.26.2.7.g19db9cfb68
+
diff --git a/compiler/rustc_codegen_cranelift/prepare.sh b/compiler/rustc_codegen_cranelift/prepare.sh
deleted file mode 100755 (executable)
index 64c0972..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-./build_sysroot/prepare_sysroot_src.sh
-cargo install hyperfine || echo "Skipping hyperfine install"
-
-git clone https://github.com/rust-random/rand.git || echo "rust-random/rand has already been cloned"
-pushd rand
-git checkout -- .
-git checkout 0f933f9c7176e53b2a3c7952ded484e1783f0bf1
-git am ../crate_patches/*-rand-*.patch
-popd
-
-git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned"
-pushd regex
-git checkout -- .
-git checkout 341f207c1071f7290e3f228c710817c280c8dca1
-popd
-
-git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned"
-pushd simple-raytracer
-git checkout -- .
-git checkout 804a7a21b9e673a482797aa289a18ed480e4d813
-
-# build with cg_llvm for perf comparison
-unset CARGO_TARGET_DIR
-cargo build
-mv target/debug/main raytracer_cg_llvm
-popd
index 9fe6e093a7b81f6577d1fb822692c77508e0ac88..f806f7bdcd98a72e2c858d5b4f915be04e396bd1 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-05-26"
+channel = "nightly-2021-07-07"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.rs b/compiler/rustc_codegen_cranelift/scripts/cargo.rs
new file mode 100644 (file)
index 0000000..b7e8dd4
--- /dev/null
@@ -0,0 +1,70 @@
+use std::env;
+#[cfg(unix)]
+use std::os::unix::process::CommandExt;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+    if env::var("RUSTC_WRAPPER").map_or(false, |wrapper| wrapper.contains("sccache")) {
+        eprintln!(
+            "\x1b[1;93m=== Warning: Unsetting RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m"
+        );
+        env::remove_var("RUSTC_WRAPPER");
+    }
+
+    let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
+
+    env::set_var("RUSTC", sysroot.join("bin/cg_clif".to_string() + env::consts::EXE_SUFFIX));
+
+    let mut rustdoc_flags = env::var("RUSTDOCFLAGS").unwrap_or(String::new());
+    rustdoc_flags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend=");
+    rustdoc_flags.push_str(
+        sysroot
+            .join(if cfg!(windows) { "bin" } else { "lib" })
+            .join(
+                env::consts::DLL_PREFIX.to_string()
+                    + "rustc_codegen_cranelift"
+                    + env::consts::DLL_SUFFIX,
+            )
+            .to_str()
+            .unwrap(),
+    );
+    rustdoc_flags.push_str(" --sysroot ");
+    rustdoc_flags.push_str(sysroot.to_str().unwrap());
+    env::set_var("RUSTDOCFLAGS", rustdoc_flags);
+
+    // Ensure that the right toolchain is used
+    env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+
+    let args: Vec<_> = match env::args().nth(1).as_deref() {
+        Some("jit") => {
+            env::set_var(
+                "RUSTFLAGS",
+                env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
+            );
+            std::array::IntoIter::new(["rustc".to_string()])
+                .chain(env::args().skip(2))
+                .chain(["--".to_string(), "-Cllvm-args=mode=jit".to_string()])
+                .collect()
+        }
+        Some("lazy-jit") => {
+            env::set_var(
+                "RUSTFLAGS",
+                env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
+            );
+            std::array::IntoIter::new(["rustc".to_string()])
+                .chain(env::args().skip(2))
+                .chain(["--".to_string(), "-Cllvm-args=mode=jit-lazy".to_string()])
+                .collect()
+        }
+        _ => env::args().skip(1).collect(),
+    };
+
+    #[cfg(unix)]
+    Command::new("cargo").args(args).exec();
+
+    #[cfg(not(unix))]
+    std::process::exit(
+        Command::new("cargo").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
+    );
+}
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.sh b/compiler/rustc_codegen_cranelift/scripts/cargo.sh
deleted file mode 100755 (executable)
index 1daa5a7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-
-dir=$(dirname "$0")
-source "$dir/config.sh"
-
-# read nightly compiler from rust-toolchain file
-TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/")
-
-cmd=$1
-shift || true
-
-if [[ "$cmd" = "jit" ]]; then
-cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit -Cprefer-dynamic
-elif [[ "$cmd" = "lazy-jit" ]]; then
-cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit-lazy -Cprefer-dynamic
-else
-cargo "+${TOOLCHAIN}" "$cmd" "$@"
-fi
index 99b302ee1d94b3cf044132fccd3401031b9c2c42..53ada369b089a28ee63b3c183603a36153239821 100644 (file)
@@ -2,26 +2,5 @@
 
 set -e
 
-dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -)
-
-if echo "$RUSTC_WRAPPER" | grep sccache; then
-echo
-echo -e "\x1b[1;93m=== Warning: Unset RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m"
-echo
-export RUSTC_WRAPPER=
-fi
-
-dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
-
-export RUSTC=$dir"/bin/cg_clif"
-
-export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\
-'-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir
-
-# FIXME fix `#[linkage = "extern_weak"]` without this
-if [[ "$(uname)" == 'Darwin' ]]; then
-   export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
-fi
-
-export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:"$dir"/lib"
-export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH"
+export DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH"
index 3f98d77d76cad82fe2d7546f64f7b0407b576de4..11d6c4c83186743f2751a2403c2996eab66746be 100644 (file)
@@ -1,6 +1,6 @@
 # Note to people running shellcheck: this file should only be sourced, not executed directly.
 
-# Various env vars that should only be set for the build system but not for cargo.sh
+# Various env vars that should only be set for the build system
 
 set -e
 
@@ -25,3 +25,8 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
       echo "Unknown non-native platform"
    fi
 fi
+
+# FIXME fix `#[linkage = "extern_weak"]` without this
+if [[ "$(uname)" == 'Darwin' ]]; then
+   export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
+fi
index 15388926ec9ec62ddb5c707cc64c926317f75f09..9e196afbe4f57c38b36576fb9621f4cee56373b5 100755 (executable)
@@ -2,9 +2,10 @@
 #![forbid(unsafe_code)]/* This line is ignored by bash
 # This block is ignored by rustc
 pushd $(dirname "$0")/../
-source build/config.sh
+source scripts/config.sh
+RUSTC="$(pwd)/build/bin/cg_clif"
 popd
-PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS -Cllvm-args=mode=jit -Cprefer-dynamic $0
+PROFILE=$1 OUTPUT=$2 exec $RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic $0
 #*/
 
 //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
index fa7557653d879a161e77afdaddb0dc1822fc374f..cc34c08088665bc19cdea842e961593052c28e50 100755 (executable)
@@ -17,7 +17,7 @@ case $1 in
         done
 
         ./clean_all.sh
-        ./prepare.sh
+        ./y.rs prepare
 
         (cd build_sysroot && cargo update)
 
index 43c4887669cf6a0512a87fbe8e045b359c66a14d..52adaaa8de673d3661903b9353ed96ec1bbbb5dc 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/bash
 set -e
 
-./build.sh
-source build/config.sh
+./y.rs build
+source scripts/config.sh
 
 echo "[SETUP] Rust fork"
 git clone https://github.com/rust-lang/rust.git || true
@@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644
  [dependencies]
  core = { path = "../core" }
 -compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "0.1.43", features = ['rustc-dep-of-std', 'no-asm'] }
++compiler_builtins = { version = "0.1.45", features = ['rustc-dep-of-std', 'no-asm'] }
 
  [dev-dependencies]
  rand = "0.7"
index 347fb40e6f9e7bbf0999157ba046d052e6ab8f75..2f5c2cf737b056be7560f2caa6d6c7d0d6160a8c 100755 (executable)
@@ -38,7 +38,8 @@ rm src/test/ui/threads-sendsync/task-stderr.rs
 rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs
 rm src/test/ui/drop/drop-trait-enum.rs
 rm src/test/ui/numbers-arithmetic/issue-8460.rs
-rm src/test/incremental/change_crate_dep_kind.rs # requires -Cpanic=unwind
+rm src/test/ui/rt-explody-panic-payloads.rs
+rm src/test/incremental/change_crate_dep_kind.rs
 
 rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations
 rm src/test/ui/init-large-type.rs # same
@@ -64,6 +65,7 @@ rm src/test/incremental/lto.rs # requires lto
 
 rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/
 rm -r src/test/run-make/unstable-flag-required # same
+rm -r src/test/run-make/emit-named-files # requires full --emit support
 
 rm src/test/pretty/asm.rs # inline asm
 rm src/test/pretty/raw-str-nonexpr.rs # same
index 0d99d2c507c95af6819f7b8decfeb0dfbcc7bf4e..5df04c533a70e38fb009dec4ec62f337e0a87a38 100755 (executable)
@@ -2,9 +2,10 @@
 
 set -e
 
-source build/config.sh
+source scripts/config.sh
 source scripts/ext_config.sh
-MY_RUSTC="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
+export RUSTC=false # ensure that cg_llvm isn't accidentally used
+MY_RUSTC="$(pwd)/build/bin/cg_clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
 
 function no_sysroot_tests() {
     echo "[BUILD] mini_core"
@@ -46,7 +47,7 @@ function base_sysroot_tests() {
         $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
 
         echo "[JIT-lazy] std_example"
-        $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --cfg lazy_jit --target "$HOST_TRIPLE"
+        $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
     else
         echo "[JIT] std_example (skipped)"
     fi
@@ -75,63 +76,64 @@ function base_sysroot_tests() {
 
 function extended_sysroot_tests() {
     pushd rand
-    cargo clean
+    ../build/cargo clean
     if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
         echo "[TEST] rust-random/rand"
-        ../build/cargo.sh test --workspace
+        ../build/cargo test --workspace
     else
         echo "[AOT] rust-random/rand"
-        ../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests
+        ../build/cargo build --workspace --target $TARGET_TRIPLE --tests
     fi
     popd
 
     pushd simple-raytracer
     if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
         echo "[BENCH COMPILE] ebobby/simple-raytracer"
-        hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \
+        hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo clean" \
         "RUSTC=rustc RUSTFLAGS='' cargo build" \
-        "../build/cargo.sh build"
+        "../build/cargo build"
 
         echo "[BENCH RUN] ebobby/simple-raytracer"
         cp ./target/debug/main ./raytracer_cg_clif
         hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif
     else
+        ../build/cargo clean
         echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
         echo "[COMPILE] ebobby/simple-raytracer"
-        ../build/cargo.sh build --target $TARGET_TRIPLE
+        ../build/cargo build --target $TARGET_TRIPLE
         echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
     fi
     popd
 
     pushd build_sysroot/sysroot_src/library/core/tests
     echo "[TEST] libcore"
-    cargo clean
+    ../../../../../build/cargo clean
     if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        ../../../../../build/cargo.sh test
+        ../../../../../build/cargo test
     else
-        ../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests
+        ../../../../../build/cargo build --target $TARGET_TRIPLE --tests
     fi
     popd
 
     pushd regex
     echo "[TEST] rust-lang/regex example shootout-regex-dna"
-    cargo clean
+    ../build/cargo clean
     export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning
     # Make sure `[codegen mono items] start` doesn't poison the diff
-    ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE
+    ../build/cargo build --example shootout-regex-dna --target $TARGET_TRIPLE
     if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
         cat examples/regexdna-input.txt \
-            | ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \
+            | ../build/cargo run --example shootout-regex-dna --target $TARGET_TRIPLE \
             | grep -v "Spawned thread" > res.txt
         diff -u res.txt examples/regexdna-output.txt
     fi
 
     if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
         echo "[TEST] rust-lang/regex tests"
-        ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
+        ../build/cargo test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
     else
         echo "[AOT] rust-lang/regex tests"
-        ../build/cargo.sh build --tests --target $TARGET_TRIPLE
+        ../build/cargo build --tests --target $TARGET_TRIPLE
     fi
     popd
 }
index ec3e17e5b758d6929cae190f6c51b92645cab5d1..3d78eed77b94c373cfe533920501dbabb6f99470 100644 (file)
@@ -21,6 +21,11 @@ pub(crate) fn codegen_fn<'tcx>(
     debug_assert!(!instance.substs.needs_infer());
 
     let mir = tcx.instance_mir(instance.def);
+    let _mir_guard = crate::PrintOnPanic(|| {
+        let mut buf = Vec::new();
+        rustc_mir::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap();
+        String::from_utf8_lossy(&buf).into_owned()
+    });
 
     // Declare function
     let symbol_name = tcx.symbol_name(instance);
@@ -52,7 +57,6 @@ pub(crate) fn codegen_fn<'tcx>(
         module,
         tcx,
         pointer_type,
-        vtables: FxHashMap::default(),
         constants_cx: ConstantCx::new(),
 
         instance,
@@ -105,7 +109,14 @@ pub(crate) fn codegen_fn<'tcx>(
     let context = &mut cx.cached_context;
     context.func = func;
 
-    crate::pretty_clif::write_clif_file(tcx, "unopt", None, instance, &context, &clif_comments);
+    crate::pretty_clif::write_clif_file(
+        tcx,
+        "unopt",
+        module.isa(),
+        instance,
+        &context,
+        &clif_comments,
+    );
 
     // Verify function
     verify_func(tcx, &clif_comments, &context.func);
@@ -122,7 +133,13 @@ pub(crate) fn codegen_fn<'tcx>(
 
     // Perform rust specific optimizations
     tcx.sess.time("optimize clif ir", || {
-        crate::optimize::optimize_function(tcx, instance, context, &mut clif_comments);
+        crate::optimize::optimize_function(
+            tcx,
+            module.isa(),
+            instance,
+            context,
+            &mut clif_comments,
+        );
     });
 
     // Define function
@@ -137,7 +154,7 @@ pub(crate) fn codegen_fn<'tcx>(
     crate::pretty_clif::write_clif_file(
         tcx,
         "opt",
-        Some(module.isa()),
+        module.isa(),
         instance,
         &context,
         &clif_comments,
index 2643fae0a810af7d3630ed01e4ae704c6b42f173..a044b43b86470a3c3e83f99ea5eb0cec9d4ea92e 100644 (file)
@@ -6,8 +6,8 @@
 extern crate rustc_session;
 extern crate rustc_target;
 
-use std::panic;
 use std::lazy::SyncLazy;
+use std::panic;
 
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
 use rustc_interface::interface;
index a8a0bb52a246e728041afe7ba14593b76db0cafb..892ccf27f6df893f713a62e9cf387f951848da98 100644 (file)
@@ -233,7 +233,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
     pub(crate) module: &'m mut dyn Module,
     pub(crate) tcx: TyCtxt<'tcx>,
     pub(crate) pointer_type: Type, // Cached from module
-    pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer>,
     pub(crate) constants_cx: ConstantCx,
 
     pub(crate) instance: Instance<'tcx>,
index a87b3703949f9aebc5ec69e6e3a2bbb4cfd9b3fe..2a2573aad295025f14f1d743c63b64845d9412db 100644 (file)
@@ -1,16 +1,13 @@
 //! Handling of `static`s, `const`s and promoted allocations
 
-use rustc_span::DUMMY_SP;
-
-use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::ErrorReported;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{
-    alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc,
-    Scalar,
+    read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
 };
 use rustc_middle::ty::ConstKind;
+use rustc_span::DUMMY_SP;
 
 use cranelift_codegen::ir::GlobalValueData;
 use cranelift_module::*;
@@ -171,66 +168,74 @@ pub(crate) fn codegen_const_value<'tcx>(
     }
 
     match const_val {
-        ConstValue::Scalar(x) => {
-            if fx.clif_type(layout.ty).is_none() {
-                let (size, align) = (layout.size, layout.align.pref);
-                let mut alloc = Allocation::from_bytes(
-                    std::iter::repeat(0).take(size.bytes_usize()).collect::<Vec<u8>>(),
-                    align,
-                    Mutability::Not,
-                );
-                alloc.write_scalar(fx, alloc_range(Size::ZERO, size), x.into()).unwrap();
-                let alloc = fx.tcx.intern_const_alloc(alloc);
-                return CValue::by_ref(pointer_for_allocation(fx, alloc), layout);
-            }
-
-            match x {
-                Scalar::Int(int) => CValue::const_val(fx, layout, int),
-                Scalar::Ptr(ptr) => {
-                    let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
-                    let base_addr = match alloc_kind {
-                        Some(GlobalAlloc::Memory(alloc)) => {
-                            fx.constants_cx.todo.push(TodoItem::Alloc(ptr.alloc_id));
-                            let data_id = data_id_for_alloc_id(
-                                &mut fx.constants_cx,
-                                fx.module,
-                                ptr.alloc_id,
-                                alloc.mutability,
-                            );
-                            let local_data_id =
-                                fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
-                            if fx.clif_comments.enabled() {
-                                fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
-                            }
-                            fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
-                        }
-                        Some(GlobalAlloc::Function(instance)) => {
-                            let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
-                            let local_func_id =
-                                fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
-                            fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
-                        }
-                        Some(GlobalAlloc::Static(def_id)) => {
-                            assert!(fx.tcx.is_static(def_id));
-                            let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
-                            let local_data_id =
-                                fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
-                            if fx.clif_comments.enabled() {
-                                fx.add_comment(local_data_id, format!("{:?}", def_id));
-                            }
-                            fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
+        ConstValue::Scalar(x) => match x {
+            Scalar::Int(int) => {
+                if fx.clif_type(layout.ty).is_some() {
+                    return CValue::const_val(fx, layout, int);
+                } else {
+                    let raw_val = int.to_bits(int.size()).unwrap();
+                    let val = match int.size().bytes() {
+                        1 => fx.bcx.ins().iconst(types::I8, raw_val as i64),
+                        2 => fx.bcx.ins().iconst(types::I16, raw_val as i64),
+                        4 => fx.bcx.ins().iconst(types::I32, raw_val as i64),
+                        8 => fx.bcx.ins().iconst(types::I64, raw_val as i64),
+                        16 => {
+                            let lsb = fx.bcx.ins().iconst(types::I64, raw_val as u64 as i64);
+                            let msb =
+                                fx.bcx.ins().iconst(types::I64, (raw_val >> 64) as u64 as i64);
+                            fx.bcx.ins().iconcat(lsb, msb)
                         }
-                        None => bug!("missing allocation {:?}", ptr.alloc_id),
-                    };
-                    let val = if ptr.offset.bytes() != 0 {
-                        fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap())
-                    } else {
-                        base_addr
+                        _ => unreachable!(),
                     };
-                    CValue::by_val(val, layout)
+
+                    let place = CPlace::new_stack_slot(fx, layout);
+                    place.to_ptr().store(fx, val, MemFlags::trusted());
+                    place.to_cvalue(fx)
                 }
             }
-        }
+            Scalar::Ptr(ptr) => {
+                let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
+                let base_addr = match alloc_kind {
+                    Some(GlobalAlloc::Memory(alloc)) => {
+                        let data_id = data_id_for_alloc_id(
+                            &mut fx.constants_cx,
+                            fx.module,
+                            ptr.alloc_id,
+                            alloc.mutability,
+                        );
+                        let local_data_id =
+                            fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+                        if fx.clif_comments.enabled() {
+                            fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
+                        }
+                        fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
+                    }
+                    Some(GlobalAlloc::Function(instance)) => {
+                        let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
+                        let local_func_id =
+                            fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
+                        fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
+                    }
+                    Some(GlobalAlloc::Static(def_id)) => {
+                        assert!(fx.tcx.is_static(def_id));
+                        let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
+                        let local_data_id =
+                            fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+                        if fx.clif_comments.enabled() {
+                            fx.add_comment(local_data_id, format!("{:?}", def_id));
+                        }
+                        fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
+                    }
+                    None => bug!("missing allocation {:?}", ptr.alloc_id),
+                };
+                let val = if ptr.offset.bytes() != 0 {
+                    fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap())
+                } else {
+                    base_addr
+                };
+                CValue::by_val(val, layout)
+            }
+        },
         ConstValue::ByRef { alloc, offset } => CValue::by_ref(
             pointer_for_allocation(fx, alloc)
                 .offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
@@ -254,7 +259,6 @@ pub(crate) fn pointer_for_allocation<'tcx>(
     alloc: &'tcx Allocation,
 ) -> crate::pointer::Pointer {
     let alloc_id = fx.tcx.create_memory_alloc(alloc);
-    fx.constants_cx.todo.push(TodoItem::Alloc(alloc_id));
     let data_id =
         data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, alloc.mutability);
 
@@ -266,12 +270,13 @@ pub(crate) fn pointer_for_allocation<'tcx>(
     crate::pointer::Pointer::new(global_ptr)
 }
 
-fn data_id_for_alloc_id(
+pub(crate) fn data_id_for_alloc_id(
     cx: &mut ConstantCx,
     module: &mut dyn Module,
     alloc_id: AllocId,
     mutability: rustc_hir::Mutability,
 ) -> DataId {
+    cx.todo.push(TodoItem::Alloc(alloc_id));
     *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
         module.declare_anonymous_data(mutability == rustc_hir::Mutability::Mut, false).unwrap()
     })
@@ -352,7 +357,14 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                     GlobalAlloc::Memory(alloc) => alloc,
                     GlobalAlloc::Function(_) | GlobalAlloc::Static(_) => unreachable!(),
                 };
-                let data_id = data_id_for_alloc_id(cx, module, alloc_id, alloc.mutability);
+                let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
+                    module
+                        .declare_anonymous_data(
+                            alloc.mutability == rustc_hir::Mutability::Mut,
+                            false,
+                        )
+                        .unwrap()
+                });
                 (data_id, alloc, None)
             }
             TodoItem::Static(def_id) => {
@@ -415,7 +427,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                     continue;
                 }
                 GlobalAlloc::Memory(target_alloc) => {
-                    cx.todo.push(TodoItem::Alloc(reloc));
                     data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability)
                 }
                 GlobalAlloc::Static(def_id) => {
index 9eb067706309e12cebc5a06146d24e433da1f6e0..c7e15f81e030104c33ff6663ca8806307dcbf7ed 100644 (file)
@@ -10,7 +10,7 @@
 };
 
 use cranelift_codegen::binemit::CodeOffset;
-use cranelift_codegen::machinst::MachSrcLoc;
+use cranelift_codegen::MachSrcLoc;
 
 use gimli::write::{
     Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,
index 61e54a76f29ba514956cb25c6066ef6182190e79..c67336eb3f2c3125ee0427511991fbd3d01d2e09 100644 (file)
@@ -61,9 +61,11 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self {
 
         let mut dwarf = DwarfUnit::new(encoding);
 
-        // FIXME: how to get version when building out of tree?
-        // Normally this would use option_env!("CFG_VERSION").
-        let producer = format!("cg_clif (rustc {})", "unknown version");
+        let producer = format!(
+            "cg_clif (rustc {}, cranelift {})",
+            rustc_interface::util::version_str().unwrap_or("unknown version"),
+            cranelift_codegen::VERSION,
+        );
         let comp_dir = tcx.sess.working_dir.to_string_lossy(false).into_owned();
         let (name, file_info) = match tcx.sess.local_crate_source_file.clone() {
             Some(path) => {
index 6676d88602c45d9e34991e80ce25e6cf158077e5..a8b802f449437622770ff9426fd524ac4273c1f2 100644 (file)
@@ -4,7 +4,6 @@
 use std::path::PathBuf;
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_codegen_ssa::back::linker::LinkerInfo;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -290,14 +289,16 @@ pub(crate) fn run_aot(
         None
     };
 
+    // FIXME handle `-Ctarget-cpu=native`
+    let target_cpu =
+        tcx.sess.opts.cg.target_cpu.as_ref().unwrap_or(&tcx.sess.target.cpu).to_owned();
     Box::new((
         CodegenResults {
             modules,
             allocator_module,
             metadata_module,
             metadata,
-            linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
-            crate_info: CrateInfo::new(tcx),
+            crate_info: CrateInfo::new(tcx, target_cpu),
         },
         work_products,
     ))
index 4a99cb727c8306be349da798407d5da139b31828..76fbc9ad51e8ec8af1b9665ed2194a4b18f145a4 100644 (file)
@@ -3,11 +3,14 @@
 
 use std::cell::RefCell;
 use std::ffi::CString;
+use std::lazy::{Lazy, SyncOnceCell};
 use std::os::raw::{c_char, c_int};
+use std::sync::{mpsc, Mutex};
 
 use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
 use rustc_codegen_ssa::CrateInfo;
 use rustc_middle::mir::mono::MonoItem;
+use rustc_session::Session;
 
 use cranelift_jit::{JITBuilder, JITModule};
 
@@ -23,12 +26,48 @@ struct JitState {
     static LAZY_JIT_STATE: RefCell<Option<JitState>> = RefCell::new(None);
 }
 
+/// The Sender owned by the rustc thread
+static GLOBAL_MESSAGE_SENDER: SyncOnceCell<Mutex<mpsc::Sender<UnsafeMessage>>> =
+    SyncOnceCell::new();
+
+/// A message that is sent from the jitted runtime to the rustc thread.
+/// Senders are responsible for upholding `Send` semantics.
+enum UnsafeMessage {
+    /// Request that the specified `Instance` be lazily jitted.
+    ///
+    /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after
+    /// this message is sent.
+    JitFn {
+        instance_ptr: *const Instance<'static>,
+        trampoline_ptr: *const u8,
+        tx: mpsc::Sender<*const u8>,
+    },
+}
+unsafe impl Send for UnsafeMessage {}
+
+impl UnsafeMessage {
+    /// Send the message.
+    fn send(self) -> Result<(), mpsc::SendError<UnsafeMessage>> {
+        thread_local! {
+            /// The Sender owned by the local thread
+            static LOCAL_MESSAGE_SENDER: Lazy<mpsc::Sender<UnsafeMessage>> = Lazy::new(||
+                GLOBAL_MESSAGE_SENDER
+                    .get().unwrap()
+                    .lock().unwrap()
+                    .clone()
+            );
+        }
+        LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self))
+    }
+}
+
 fn create_jit_module<'tcx>(
     tcx: TyCtxt<'tcx>,
     backend_config: &BackendConfig,
     hotswap: bool,
 ) -> (JITModule, CodegenCx<'tcx>) {
-    let imported_symbols = load_imported_symbols_for_jit(tcx);
+    let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
+    let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info);
 
     let isa = crate::build_isa(tcx.sess, backend_config);
     let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
@@ -116,11 +155,6 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         .chain(backend_config.jit_args.iter().map(|arg| &**arg))
         .map(|arg| CString::new(arg).unwrap())
         .collect::<Vec<_>>();
-    let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
-
-    // Push a null pointer as a terminating argument. This is required by POSIX and
-    // useful as some dynamic linkers use it as a marker to jump over.
-    argv.push(std::ptr::null());
 
     let start_sig = Signature {
         params: vec![
@@ -128,7 +162,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
             AbiParam::new(jit_module.target_config().pointer_type()),
         ],
         returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)],
-        call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
+        call_conv: jit_module.target_config().default_call_conv,
     };
     let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
     let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);
@@ -141,12 +175,51 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
 
     let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
         unsafe { ::std::mem::transmute(finalized_start) };
-    let ret = f(args.len() as c_int, argv.as_ptr());
-    std::process::exit(ret);
+
+    let (tx, rx) = mpsc::channel();
+    GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap();
+
+    // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages
+    // (eg to lazily JIT further functions as required)
+    std::thread::spawn(move || {
+        let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
+
+        // Push a null pointer as a terminating argument. This is required by POSIX and
+        // useful as some dynamic linkers use it as a marker to jump over.
+        argv.push(std::ptr::null());
+
+        let ret = f(args.len() as c_int, argv.as_ptr());
+        std::process::exit(ret);
+    });
+
+    // Handle messages
+    loop {
+        match rx.recv().unwrap() {
+            // lazy JIT compilation request - compile requested instance and return pointer to result
+            UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => {
+                tx.send(jit_fn(instance_ptr, trampoline_ptr))
+                    .expect("jitted runtime hung up before response to lazy JIT request was sent");
+            }
+        }
+    }
 }
 
 #[no_mangle]
-extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 {
+extern "C" fn __clif_jit_fn(
+    instance_ptr: *const Instance<'static>,
+    trampoline_ptr: *const u8,
+) -> *const u8 {
+    // send the JIT request to the rustc thread, with a channel for the response
+    let (tx, rx) = mpsc::channel();
+    UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }
+        .send()
+        .expect("rustc thread hung up before lazy JIT request was sent");
+
+    // block on JIT compilation result
+    rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request")
+}
+
+fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 {
     rustc_middle::ty::tls::with(|tcx| {
         // lift is used to ensure the correct lifetime for instance.
         let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();
@@ -160,6 +233,17 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8
             let name = tcx.symbol_name(instance).name;
             let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
             let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
+
+            let current_ptr = jit_module.read_got_entry(func_id);
+
+            // If the function's GOT entry has already been updated to point at something other
+            // than the shim trampoline, don't re-jit but just return the new pointer instead.
+            // This does not need synchronization as this code is executed only by a sole rustc
+            // thread.
+            if current_ptr != trampoline_ptr {
+                return current_ptr;
+            }
+
             jit_module.prepare_for_function_redefine(func_id).unwrap();
 
             let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false);
@@ -173,26 +257,27 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8
     })
 }
 
-fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
+fn load_imported_symbols_for_jit(
+    sess: &Session,
+    crate_info: CrateInfo,
+) -> Vec<(String, *const u8)> {
     use rustc_middle::middle::dependency_format::Linkage;
 
     let mut dylib_paths = Vec::new();
 
-    let crate_info = CrateInfo::new(tcx);
-    let formats = tcx.dependency_formats(());
-    let data = &formats
+    let data = &crate_info
+        .dependency_formats
         .iter()
         .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
         .unwrap()
         .1;
-    for &(cnum, _) in &crate_info.used_crates_dynamic {
+    for &cnum in &crate_info.used_crates {
         let src = &crate_info.used_crate_source[&cnum];
         match data[cnum.as_usize() - 1] {
             Linkage::NotLinked | Linkage::IncludedFromDylib => {}
             Linkage::Static => {
-                let name = tcx.crate_name(cnum);
-                let mut err =
-                    tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
+                let name = &crate_info.crate_name[&cnum];
+                let mut err = sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
                 err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
                 err.emit();
             }
@@ -232,7 +317,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
         std::mem::forget(lib)
     }
 
-    tcx.sess.abort_if_errors();
+    sess.abort_if_errors();
 
     imported_symbols
 }
@@ -254,7 +339,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
             Linkage::Import,
             &Signature {
                 call_conv: module.target_config().default_call_conv,
-                params: vec![AbiParam::new(pointer_type)],
+                params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)],
                 returns: vec![AbiParam::new(pointer_type)],
             },
         )
@@ -267,6 +352,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
     let mut builder_ctx = FunctionBuilderContext::new();
     let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);
 
+    let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func);
     let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
     let sig_ref = trampoline_builder.func.import_signature(sig);
 
@@ -276,7 +362,8 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
 
     trampoline_builder.switch_to_block(entry_block);
     let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
-    let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr]);
+    let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn);
+    let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]);
     let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
     let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
     let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
index ba4ed2162cd5d1397c38fa210e1c36445a0226a3..be3704ca2768e0377a579c8206adf25c8d499fa6 100644 (file)
@@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
             let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
             dest.write_cvalue(fx, a);
         };
+        "llvm.x86.addcarry.64", (v c_in, c a, c b) {
+            llvm_add_sub(
+                fx,
+                BinOp::Add,
+                ret,
+                c_in,
+                a,
+                b
+            );
+        };
+        "llvm.x86.subborrow.64", (v b_in, c a, c b) {
+            llvm_add_sub(
+                fx,
+                BinOp::Sub,
+                ret,
+                b_in,
+                a,
+                b
+            );
+        };
     }
 
     if let Some((_, dest)) = destination {
@@ -121,3 +141,41 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
 // llvm.x86.avx2.pshuf.b
 // llvm.x86.avx2.psrli.w
 // llvm.x86.sse2.psrli.w
+
+fn llvm_add_sub<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    bin_op: BinOp,
+    ret: CPlace<'tcx>,
+    cb_in: Value,
+    a: CValue<'tcx>,
+    b: CValue<'tcx>,
+) {
+    assert_eq!(
+        a.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
+    );
+    assert_eq!(
+        b.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
+    );
+
+    // c + carry -> c + first intermediate carry or borrow respectively
+    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
+    let c = int0.value_field(fx, mir::Field::new(0));
+    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
+
+    // c + carry -> c + second intermediate carry or borrow respectively
+    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
+    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
+    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
+    let (c, cb1) = int1.load_scalar_pair(fx);
+
+    // carry0 | carry1 -> carry or borrow respectively
+    let cb_out = fx.bcx.ins().bor(cb0, cb1);
+
+    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+    let val = CValue::by_val_pair(cb_out, c, layout);
+    ret.write_cvalue(fx, val);
+}
index 52896fc7127e8a32fffbef7ae7f4ed4a9880adc2..3979886e10cfc17997d1a30362860cdb85adf6c1 100644 (file)
@@ -1115,6 +1115,40 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
             );
             ret.write_cvalue(fx, CValue::by_val(res, ret.layout()));
         };
+
+        raw_eq, <T>(v lhs_ref, v rhs_ref) {
+            fn type_by_size(size: Size) -> Option<Type> {
+                Type::int(size.bits().try_into().ok()?)
+            }
+
+            let size = fx.layout_of(T).layout.size;
+            let is_eq_value =
+                if size == Size::ZERO {
+                    // No bytes means they're trivially equal
+                    fx.bcx.ins().iconst(types::I8, 1)
+                } else if let Some(clty) = type_by_size(size) {
+                    // Can't use `trusted` for these loads; they could be unaligned.
+                    let mut flags = MemFlags::new();
+                    flags.set_notrap();
+                    let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
+                    let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
+                    let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val);
+                    fx.bcx.ins().bint(types::I8, eq)
+                } else {
+                    // Just call `memcmp` (like slices do in core) when the
+                    // size is too large or it's not a power-of-two.
+                    let ptr_ty = pointer_ty(fx.tcx);
+                    let signed_bytes = i64::try_from(size.bytes()).unwrap();
+                    let bytes_val = fx.bcx.ins().iconst(ptr_ty, signed_bytes);
+                    let params = vec![AbiParam::new(ptr_ty); 3];
+                    let returns = vec![AbiParam::new(types::I32)];
+                    let args = &[lhs_ref, rhs_ref, bytes_val];
+                    let cmp = fx.lib_call("memcmp", params, returns, args)[0];
+                    let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0);
+                    fx.bcx.ins().bint(types::I8, eq)
+                };
+            ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
+        };
     }
 
     if let Some((_, dest)) = destination {
index b817bf4aff7718c89e424c14c6039457287ff251..cb1cb3c74dbb5981317ceb4b7e677516d98ceb43 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
+#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
 #![warn(unreachable_pub)]
@@ -14,7 +14,9 @@
 extern crate rustc_hir;
 extern crate rustc_incremental;
 extern crate rustc_index;
+extern crate rustc_interface;
 extern crate rustc_metadata;
+extern crate rustc_mir;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
@@ -219,7 +221,6 @@ fn link(
             sess,
             &codegen_results,
             outputs,
-            &codegen_results.crate_info.local_crate_name.as_str(),
         );
 
         Ok(())
@@ -285,10 +286,12 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
         }
         None => {
             let mut builder =
-                cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
-            // Don't use "haswell" as the default, as it implies `has_lzcnt`.
-            // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
-            builder.enable("nehalem").unwrap();
+                cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant).unwrap();
+            if target_triple.architecture == target_lexicon::Architecture::X86_64 {
+                // Don't use "haswell" as the default, as it implies `has_lzcnt`.
+                // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
+                builder.enable("nehalem").unwrap();
+            }
             builder
         }
     };
index 137fb5f77313cbae7d39c54291a383fa9e7e2357..61033d85a12740a827d1f443c7e76e567dfd54e9 100644 (file)
@@ -1,17 +1,20 @@
 //! Various optimizations specific to cg_clif
 
+use cranelift_codegen::isa::TargetIsa;
+
 use crate::prelude::*;
 
 pub(crate) mod peephole;
 
 pub(crate) fn optimize_function<'tcx>(
     tcx: TyCtxt<'tcx>,
+    isa: &dyn TargetIsa,
     instance: Instance<'tcx>,
     ctx: &mut Context,
     clif_comments: &mut crate::pretty_clif::CommentWriter,
 ) {
     // FIXME classify optimizations over opt levels once we have more
 
-    crate::pretty_clif::write_clif_file(tcx, "preopt", None, instance, &ctx, &*clif_comments);
+    crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx, &*clif_comments);
     crate::base::verify_func(tcx, &*clif_comments, &ctx.func);
 }
index cd8c5b516083611ee316c93c816c523d29863fa3..05db74745a1c0583bb5598e885ac04e8eda37c64 100644 (file)
@@ -233,7 +233,7 @@ pub(crate) fn write_ir_file(
 pub(crate) fn write_clif_file<'tcx>(
     tcx: TyCtxt<'tcx>,
     postfix: &str,
-    isa: Option<&dyn cranelift_codegen::isa::TargetIsa>,
+    isa: &dyn cranelift_codegen::isa::TargetIsa,
     instance: Instance<'tcx>,
     context: &cranelift_codegen::Context,
     mut clif_comments: &CommentWriter,
@@ -242,22 +242,23 @@ pub(crate) fn write_clif_file<'tcx>(
         tcx,
         || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix),
         |file| {
-            let value_ranges = isa
-                .map(|isa| context.build_value_labels_ranges(isa).expect("value location ranges"));
-
             let mut clif = String::new();
             cranelift_codegen::write::decorate_function(
                 &mut clif_comments,
                 &mut clif,
                 &context.func,
-                &DisplayFunctionAnnotations { isa, value_ranges: value_ranges.as_ref() },
+                &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None },
             )
             .unwrap();
 
-            writeln!(file, "test compile")?;
-            writeln!(file, "set is_pic")?;
-            writeln!(file, "set enable_simd")?;
-            writeln!(file, "target {} haswell", crate::target_triple(tcx.sess))?;
+            for flag in isa.flags().iter() {
+                writeln!(file, "set {}", flag)?;
+            }
+            write!(file, "target {}", isa.triple().architecture.to_string())?;
+            for isa_flag in isa.isa_flags().iter() {
+                write!(file, " {}", isa_flag)?;
+            }
+            writeln!(file, "\n")?;
             writeln!(file)?;
             file.write_all(clif.as_bytes())?;
             Ok(())
index 171f39805f8963ffaad26ce92566cb3f369111d6..ae8ccc626b47089e09a8f75672c9893659ef21fa 100644 (file)
@@ -453,6 +453,10 @@ fn transmute_value<'tcx>(
                     ptr.store(fx, data, MemFlags::trusted());
                     ptr.load(fx, dst_ty, MemFlags::trusted())
                 }
+
+                // `CValue`s should never contain SSA-only types, so if you ended
+                // up here having seen an error like `B1 -> I8`, then before
+                // calling `write_cvalue` you need to add a `bint` instruction.
                 _ => unreachable!("write_cvalue_transmute: {:?} -> {:?}", src_ty, dst_ty),
             };
             //fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::new(var.index()));
index 12f7092d935a33732d858ddad42e2eff87f93b66..4a5f9f133a2bbc8e2168fd4668036fb46f3d091f 100644 (file)
@@ -1,10 +1,9 @@
 //! Codegen vtables and vtable accesses.
 //!
 //! See `rustc_codegen_ssa/src/meth.rs` for reference.
-// FIXME dedup this logic between miri, cg_llvm and cg_clif
 
+use crate::constant::data_id_for_alloc_id;
 use crate::prelude::*;
-use super::constant::pointer_for_allocation;
 
 fn vtable_memflags() -> MemFlags {
     let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap.
@@ -38,7 +37,7 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -
         pointer_ty(fx.tcx),
         vtable_memflags(),
         vtable,
-        (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
+        (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32,
     )
 }
 
@@ -69,16 +68,12 @@ pub(crate) fn get_vtable<'tcx>(
     ty: Ty<'tcx>,
     trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
 ) -> Value {
-    let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) {
-        *vtable_ptr
-    } else {
-        let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
-        let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory();
-        let vtable_ptr = pointer_for_allocation(fx, vtable_allocation);
-
-        fx.vtables.insert((ty, trait_ref), vtable_ptr);
-        vtable_ptr
-    };
-
-    vtable_ptr.get_addr(fx)
+    let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
+    let data_id =
+        data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
+    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+    if fx.clif_comments.enabled() {
+        fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id));
+    }
+    fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
 }
index e222adc7b80582ec7169a0c65f2fd9d34af00341..a10924628bb0eba9350b56f5603ead5b068b75f4 100755 (executable)
@@ -1,13 +1,13 @@
 #!/usr/bin/env bash
 set -e
 
-./build.sh --sysroot none "$@"
+./y.rs build --sysroot none "$@"
 
 rm -r target/out || true
 
 scripts/tests.sh no_sysroot
 
-./build.sh "$@"
+./y.rs build "$@"
 
 scripts/tests.sh base_sysroot
 scripts/tests.sh extended_sysroot
diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs
new file mode 100755 (executable)
index 0000000..4393758
--- /dev/null
@@ -0,0 +1,153 @@
+#!/usr/bin/env bash
+#![allow()] /*This line is ignored by bash
+# This block is ignored by rustc
+set -e
+echo "[BUILD] y.rs" 1>&2
+rustc $0 -o ${0/.rs/.bin} -g
+exec ${0/.rs/.bin} $@
+*/
+
+//! The build system for cg_clif
+//!
+//! # Manual compilation
+//!
+//! If your system doesn't support shell scripts you can manually compile and run this file using
+//! for example:
+//!
+//! ```shell
+//! $ rustc y.rs -o build/y.bin
+//! $ build/y.bin
+//! ```
+//!
+//! # Naming
+//!
+//! The name `y.rs` was chosen to not conflict with rustc's `x.py`.
+
+use std::env;
+use std::path::PathBuf;
+use std::process;
+
+#[path = "build_system/build_backend.rs"]
+mod build_backend;
+#[path = "build_system/build_sysroot.rs"]
+mod build_sysroot;
+#[path = "build_system/config.rs"]
+mod config;
+#[path = "build_system/prepare.rs"]
+mod prepare;
+#[path = "build_system/rustc_info.rs"]
+mod rustc_info;
+#[path = "build_system/utils.rs"]
+mod utils;
+
+fn usage() {
+    eprintln!("Usage:");
+    eprintln!("  ./y.rs prepare");
+    eprintln!("  ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]");
+}
+
+macro_rules! arg_error {
+    ($($err:tt)*) => {{
+        eprintln!($($err)*);
+        usage();
+        std::process::exit(1);
+    }};
+}
+
+enum Command {
+    Build,
+}
+
+#[derive(Copy, Clone)]
+enum SysrootKind {
+    None,
+    Clif,
+    Llvm,
+}
+
+fn main() {
+    env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
+    env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
+    // The target dir is expected in the default location. Guard against the user changing it.
+    env::set_var("CARGO_TARGET_DIR", "target");
+
+    let mut args = env::args().skip(1);
+    let command = match args.next().as_deref() {
+        Some("prepare") => {
+            if args.next().is_some() {
+                arg_error!("./x.rs prepare doesn't expect arguments");
+            }
+            prepare::prepare();
+            process::exit(0);
+        }
+        Some("build") => Command::Build,
+        Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
+        Some(command) => arg_error!("Unknown command {}", command),
+        None => {
+            usage();
+            process::exit(0);
+        }
+    };
+
+    let mut target_dir = PathBuf::from("build");
+    let mut channel = "release";
+    let mut sysroot_kind = SysrootKind::Clif;
+    while let Some(arg) = args.next().as_deref() {
+        match arg {
+            "--target-dir" => {
+                target_dir = PathBuf::from(args.next().unwrap_or_else(|| {
+                    arg_error!("--target-dir requires argument");
+                }))
+            }
+            "--debug" => channel = "debug",
+            "--sysroot" => {
+                sysroot_kind = match args.next().as_deref() {
+                    Some("none") => SysrootKind::None,
+                    Some("clif") => SysrootKind::Clif,
+                    Some("llvm") => SysrootKind::Llvm,
+                    Some(arg) => arg_error!("Unknown sysroot kind {}", arg),
+                    None => arg_error!("--sysroot requires argument"),
+                }
+            }
+            flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag),
+            arg => arg_error!("Unexpected argument {}", arg),
+        }
+    }
+
+    let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
+        host_triple
+    } else if let Some(host_triple) = crate::config::get_value("host") {
+        host_triple
+    } else {
+        rustc_info::get_host_triple()
+    };
+    let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") {
+        if target_triple != "" {
+            target_triple
+        } else {
+            host_triple.clone() // Empty target triple can happen on GHA
+        }
+    } else if let Some(target_triple) = crate::config::get_value("target") {
+        target_triple
+    } else {
+        host_triple.clone()
+    };
+
+    if target_triple.ends_with("-msvc") {
+        eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift.");
+        eprintln!("Switch to the MinGW toolchain for Windows support.");
+        eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to");
+        eprintln!("set the global default target to MinGW");
+        process::exit(1);
+    }
+
+    let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple);
+    build_sysroot::build_sysroot(
+        channel,
+        sysroot_kind,
+        &target_dir,
+        cg_clif_build_dir,
+        &host_triple,
+        &target_triple,
+    );
+}
index ecf62ed213df82aec1daaf5b5b1cf958d0f9054c..7bd9397d64950d19eba45c753c9a9faa61d49294 100644 (file)
@@ -128,6 +128,7 @@ fn codegen_inline_asm(
         let mut clobbers = vec![];
         let mut output_types = vec![];
         let mut op_idx = FxHashMap::default();
+        let mut clobbered_x87 = false;
         for (idx, op) in operands.iter().enumerate() {
             match *op {
                 InlineAsmOperandRef::Out { reg, late, place } => {
@@ -150,7 +151,27 @@ fn codegen_inline_asm(
                     let ty = if let Some(ref place) = place {
                         layout = Some(&place.layout);
                         llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout)
-                    } else if !is_target_supported(reg.reg_class()) {
+                    } else if matches!(
+                        reg.reg_class(),
+                        InlineAsmRegClass::X86(
+                            X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::x87_reg
+                        )
+                    ) {
+                        // Special handling for x87/mmx registers: we always
+                        // clobber the whole set if one register is marked as
+                        // clobbered. This is due to the way LLVM handles the
+                        // FP stack in inline assembly.
+                        if !clobbered_x87 {
+                            clobbered_x87 = true;
+                            clobbers.push("~{st}".to_string());
+                            for i in 1..=7 {
+                                clobbers.push(format!("~{{st({})}}", i));
+                            }
+                        }
+                        continue;
+                    } else if !is_target_supported(reg.reg_class())
+                        || reg.reg_class().is_clobber_only(asm_arch)
+                    {
                         // We turn discarded outputs into clobber constraints
                         // if the target feature needed by the register class is
                         // disabled. This is necessary otherwise LLVM will try
@@ -565,6 +586,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
             InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
+            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+                unreachable!("clobber-only")
+            }
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l",
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
@@ -586,6 +610,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
+            InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+                unreachable!("clobber-only")
+            }
             InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
@@ -593,6 +620,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
+            ) => unreachable!("clobber-only"),
             InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
@@ -617,6 +647,9 @@ fn modifier_to_llvm(
         | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
             if modifier == Some('v') { None } else { modifier }
         }
+        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
         | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None,
         InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
@@ -639,6 +672,9 @@ fn modifier_to_llvm(
         InlineAsmRegClass::PowerPC(_) => None,
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
         | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
+        InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
             None if arch == InlineAsmArch::X86_64 => Some('q'),
@@ -663,6 +699,9 @@ fn modifier_to_llvm(
             _ => unreachable!(),
         },
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
+        InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
         InlineAsmRegClass::Bpf(_) => None,
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
@@ -681,6 +720,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
             cx.type_vector(cx.type_i64(), 2)
         }
+        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
         | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(),
         InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
@@ -704,6 +746,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
+        InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(),
@@ -711,6 +756,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
+        InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
         InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
         InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
index 64416bced31d024dcd8819dbeaa6f35e0f2cf8ad..6ac7093b7dee833870d4568529293b088950f62f 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
 use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
 use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_middle::middle::cstore::DllImport;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
@@ -208,10 +208,12 @@ fn inject_dll_import_lib(
         // have any \0 characters
         let import_name_vector: Vec<CString> = dll_imports
             .iter()
-            .map(if self.config.sess.target.arch == "x86" {
-                |import: &DllImport| CString::new(format!("_{}", import.name.to_string())).unwrap()
-            } else {
-                |import: &DllImport| CString::new(import.name.to_string()).unwrap()
+            .map(|import: &DllImport| {
+                if self.config.sess.target.arch == "x86" {
+                    LlvmArchiveBuilder::i686_decorated_name(import)
+                } else {
+                    CString::new(import.name.to_string()).unwrap()
+                }
             })
             .collect();
 
@@ -391,6 +393,21 @@ fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
             ret
         }
     }
+
+    fn i686_decorated_name(import: &DllImport) -> CString {
+        let name = import.name;
+        // We verified during construction that `name` does not contain any NULL characters, so the
+        // conversion to CString is guaranteed to succeed.
+        CString::new(match import.calling_convention {
+            DllCallingConvention::C => format!("_{}", name),
+            DllCallingConvention::Stdcall(arg_list_size) => format!("_{}@{}", name, arg_list_size),
+            DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size),
+            DllCallingConvention::Vectorcall(arg_list_size) => {
+                format!("{}@@{}", name, arg_list_size)
+            }
+        })
+        .unwrap()
+    }
 }
 
 fn string_to_io_error(s: String) -> io::Error {
index 582c9354041dedad47bd4ccdc9b1c48f40058e6b..2bb0ce68b171e57540b2c1958c71b414ee674903 100644 (file)
@@ -410,17 +410,17 @@ fn array_alloca(&mut self, ty: &'ll Type, len: &'ll Value, align: Align) -> &'ll
         }
     }
 
-    fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
+    fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value {
         unsafe {
-            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
+            let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
             llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
             load
         }
     }
 
-    fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
+    fn volatile_load(&mut self, ty: &'ll Type, ptr: &'ll Value) -> &'ll Value {
         unsafe {
-            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
+            let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
             llvm::LLVMSetVolatile(load, llvm::True);
             load
         }
@@ -428,6 +428,7 @@ fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
 
     fn atomic_load(
         &mut self,
+        ty: &'ll Type,
         ptr: &'ll Value,
         order: rustc_codegen_ssa::common::AtomicOrdering,
         size: Size,
@@ -435,6 +436,7 @@ fn atomic_load(
         unsafe {
             let load = llvm::LLVMRustBuildAtomicLoad(
                 self.llbuilder,
+                ty,
                 ptr,
                 UNNAMED,
                 AtomicOrdering::from_generic(order),
@@ -486,7 +488,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
                 }
             }
             let llval = const_llval.unwrap_or_else(|| {
-                let load = self.load(place.llval, place.align);
+                let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
                 if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
                     scalar_load_metadata(self, load, scalar);
                 }
@@ -498,7 +500,8 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
 
             let mut load = |i, scalar: &abi::Scalar, align| {
                 let llptr = self.struct_gep(place.llval, i as u64);
-                let load = self.load(llptr, align);
+                let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
+                let load = self.load(llty, llptr, align);
                 scalar_load_metadata(self, load, scalar);
                 self.to_immediate_scalar(load, scalar)
             };
@@ -815,13 +818,7 @@ fn memcpy(
         size: &'ll Value,
         flags: MemFlags,
     ) {
-        if flags.contains(MemFlags::NONTEMPORAL) {
-            // HACK(nox): This is inefficient but there is no nontemporal memcpy.
-            let val = self.load(src, src_align);
-            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
-            self.store_with_flags(val, ptr, dst_align, flags);
-            return;
-        }
+        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
         let size = self.intcast(size, self.type_isize(), false);
         let is_volatile = flags.contains(MemFlags::VOLATILE);
         let dst = self.pointercast(dst, self.type_i8p());
@@ -848,13 +845,7 @@ fn memmove(
         size: &'ll Value,
         flags: MemFlags,
     ) {
-        if flags.contains(MemFlags::NONTEMPORAL) {
-            // HACK(nox): This is inefficient but there is no nontemporal memmove.
-            let val = self.load(src, src_align);
-            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
-            self.store_with_flags(val, ptr, dst_align, flags);
-            return;
-        }
+        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
         let size = self.intcast(size, self.type_isize(), false);
         let is_volatile = flags.contains(MemFlags::VOLATILE);
         let dst = self.pointercast(dst, self.type_i8p());
index f662887abf82025aff4ed7ef19f100e5cca4a360..d1aecd32e2f2d00cddfc0d24b6329dd7e2b90f28 100644 (file)
@@ -500,6 +500,7 @@ macro_rules! mk_struct {
         let t_i32 = self.type_i32();
         let t_i64 = self.type_i64();
         let t_i128 = self.type_i128();
+        let t_isize = self.type_isize();
         let t_f32 = self.type_f32();
         let t_f64 = self.type_f64();
 
@@ -712,6 +713,10 @@ macro_rules! mk_struct {
         ifn!("llvm.assume", fn(i1) -> void);
         ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
 
+        // This isn't an "LLVM intrinsic", but LLVM's optimization passes
+        // recognize it like one and we assume it exists in `core::slice::cmp`
+        ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i32);
+
         // variadic intrinsics
         ifn!("llvm.va_start", fn(i8p) -> void);
         ifn!("llvm.va_end", fn(i8p) -> void);
index 38f50a6d621bb0bff399c6e9f7345debcafb870f..de3f719b8163c7ab0486ead4761cd579a06c078d 100644 (file)
@@ -20,7 +20,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_,
         // LLVM to keep around the reference to the global.
         let indices = [bx.const_i32(0), bx.const_i32(0)];
         let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
-        let volative_load_instruction = bx.volatile_load(element);
+        let volative_load_instruction = bx.volatile_load(bx.type_i8(), element);
         unsafe {
             llvm::LLVMSetAlignment(volative_load_instruction, 1);
         }
index 0e42931b29a976c25eee1dd96c6b71489eee826c..7e136c1b24cb26e8a26dcdf53c2339f3f35a70b4 100644 (file)
@@ -1,4 +1,3 @@
-use self::EnumTagInfo::*;
 use self::MemberDescriptionFactory::*;
 use self::RecursiveTypeDescription::*;
 
@@ -28,7 +27,7 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::ich::NodeIdHashingMode;
-use rustc_middle::mir::{self, Field, GeneratorLayout};
+use rustc_middle::mir::{self, GeneratorLayout};
 use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::Instance;
@@ -1188,7 +1187,7 @@ enum MemberDescriptionFactory<'ll, 'tcx> {
     TupleMDF(TupleMemberDescriptionFactory<'tcx>),
     EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
     UnionMDF(UnionMemberDescriptionFactory<'tcx>),
-    VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>),
+    VariantMDF(VariantMemberDescriptionFactory<'tcx>),
 }
 
 impl MemberDescriptionFactory<'ll, 'tcx> {
@@ -1505,14 +1504,8 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                 }
 
                 let variant_info = variant_info_for(index);
-                let (variant_type_metadata, member_description_factory) = describe_enum_variant(
-                    cx,
-                    self.layout,
-                    variant_info,
-                    None,
-                    self_metadata,
-                    self.span,
-                );
+                let (variant_type_metadata, member_description_factory) =
+                    describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span);
 
                 let member_descriptions = member_description_factory.create_member_descriptions(cx);
 
@@ -1524,7 +1517,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                     Some(&self.common_members),
                 );
                 vec![MemberDescription {
-                    name: if fallback { String::new() } else { variant_info.variant_name() },
+                    name: variant_info.variant_name(),
                     type_metadata: variant_type_metadata,
                     offset: Size::ZERO,
                     size: self.layout.size,
@@ -1540,28 +1533,38 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                 ref variants,
                 ..
             } => {
-                let tag_info = if fallback {
-                    // For MSVC, we generate a union of structs for each variant with an explicit
-                    // discriminant field roughly equivalent to the following C:
+                let fallback_discr_variant = if fallback {
+                    // For MSVC, we generate a union of structs for each variant and an
+                    // explicit discriminant field roughly equivalent to the following C:
                     // ```c
                     // union enum$<{name}> {
                     //   struct {variant 0 name} {
-                    //     tag$ variant$;
                     //     <variant 0 fields>
                     //   } variant0;
                     //   <other variant structs>
+                    //   {name} discriminant;
                     // }
                     // ```
-                    // The natvis in `intrinsic.nativs` then matches on `this.variant0.variant$` to
+                    // The natvis in `intrinsic.natvis` then matches on `this.discriminant` to
                     // determine which variant is active and then displays it.
-                    Some(DirectTag {
-                        tag_field: Field::from(tag_field),
-                        tag_type_metadata: self.tag_type_metadata.unwrap(),
+                    let enum_layout = self.layout;
+                    let offset = enum_layout.fields.offset(tag_field);
+                    let discr_ty = enum_layout.field(cx, tag_field).ty;
+                    let (size, align) = cx.size_and_align_of(discr_ty);
+                    Some(MemberDescription {
+                        name: "discriminant".into(),
+                        type_metadata: self.tag_type_metadata.unwrap(),
+                        offset,
+                        size,
+                        align,
+                        flags: DIFlags::FlagZero,
+                        discriminant: None,
+                        source_info: None,
                     })
                 } else {
-                    // This doesn't matter in this case.
                     None
                 };
+
                 variants
                     .iter_enumerated()
                     .map(|(i, _)| {
@@ -1571,7 +1574,6 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                             cx,
                             variant,
                             variant_info,
-                            tag_info,
                             self_metadata,
                             self.span,
                         );
@@ -1605,6 +1607,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                             source_info: variant_info.source_info(cx),
                         }
                     })
+                    .chain(fallback_discr_variant.into_iter())
                     .collect()
             }
             Variants::Multiple {
@@ -1702,7 +1705,6 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                         cx,
                         dataful_variant_layout,
                         variant_info,
-                        Some(NicheTag),
                         self_metadata,
                         self.span,
                     );
@@ -1754,7 +1756,6 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
                                     cx,
                                     variant,
                                     variant_info,
-                                    Some(NicheTag),
                                     self_metadata,
                                     self.span,
                                 );
@@ -1791,39 +1792,27 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
 }
 
 // Creates `MemberDescription`s for the fields of a single enum variant.
-struct VariantMemberDescriptionFactory<'ll, 'tcx> {
+struct VariantMemberDescriptionFactory<'tcx> {
     /// Cloned from the `layout::Struct` describing the variant.
     offsets: Vec<Size>,
     args: Vec<(String, Ty<'tcx>)>,
-    tag_type_metadata: Option<&'ll DIType>,
     span: Span,
 }
 
-impl VariantMemberDescriptionFactory<'ll, 'tcx> {
+impl VariantMemberDescriptionFactory<'tcx> {
     fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
         self.args
             .iter()
             .enumerate()
             .map(|(i, &(ref name, ty))| {
-                // Discriminant is always the first field of our variant
-                // when using the enum fallback.
-                let is_artificial_discr = use_enum_fallback(cx) && i == 0;
                 let (size, align) = cx.size_and_align_of(ty);
                 MemberDescription {
                     name: name.to_string(),
-                    type_metadata: if is_artificial_discr {
-                        self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span))
-                    } else {
-                        type_metadata(cx, ty, self.span)
-                    },
+                    type_metadata: type_metadata(cx, ty, self.span),
                     offset: self.offsets[i],
                     size,
                     align,
-                    flags: if is_artificial_discr {
-                        DIFlags::FlagArtificial
-                    } else {
-                        DIFlags::FlagZero
-                    },
+                    flags: DIFlags::FlagZero,
                     discriminant: None,
                     source_info: None,
                 }
@@ -1832,12 +1821,6 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
     }
 }
 
-#[derive(Copy, Clone)]
-enum EnumTagInfo<'ll> {
-    DirectTag { tag_field: Field, tag_type_metadata: &'ll DIType },
-    NicheTag,
-}
-
 #[derive(Copy, Clone)]
 enum VariantInfo<'a, 'tcx> {
     Adt(&'tcx ty::VariantDef),
@@ -1916,7 +1899,6 @@ fn describe_enum_variant(
     cx: &CodegenCx<'ll, 'tcx>,
     layout: layout::TyAndLayout<'tcx>,
     variant: VariantInfo<'_, 'tcx>,
-    discriminant_info: Option<EnumTagInfo<'ll>>,
     containing_scope: &'ll DIScope,
     span: Span,
 ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
@@ -1935,50 +1917,13 @@ fn describe_enum_variant(
         )
     });
 
-    // Build an array of (field name, field type) pairs to be captured in the factory closure.
-    let (offsets, args) = if use_enum_fallback(cx) {
-        // If this is not a univariant enum, there is also the discriminant field.
-        let (discr_offset, discr_arg) = match discriminant_info {
-            Some(DirectTag { tag_field, .. }) => {
-                // We have the layout of an enum variant, we need the layout of the outer enum
-                let enum_layout = cx.layout_of(layout.ty);
-                let offset = enum_layout.fields.offset(tag_field.as_usize());
-                let args = ("variant$".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
-                (Some(offset), Some(args))
-            }
-            _ => (None, None),
-        };
-        (
-            discr_offset
-                .into_iter()
-                .chain((0..layout.fields.count()).map(|i| layout.fields.offset(i)))
-                .collect(),
-            discr_arg
-                .into_iter()
-                .chain(
-                    (0..layout.fields.count())
-                        .map(|i| (variant.field_name(i), layout.field(cx, i).ty)),
-                )
-                .collect(),
-        )
-    } else {
-        (
-            (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(),
-            (0..layout.fields.count())
-                .map(|i| (variant.field_name(i), layout.field(cx, i).ty))
-                .collect(),
-        )
-    };
+    let offsets = (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect();
+    let args = (0..layout.fields.count())
+        .map(|i| (variant.field_name(i), layout.field(cx, i).ty))
+        .collect();
 
-    let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
-        offsets,
-        args,
-        tag_type_metadata: match discriminant_info {
-            Some(DirectTag { tag_type_metadata, .. }) => Some(tag_type_metadata),
-            _ => None,
-        },
-        span,
-    });
+    let member_description_factory =
+        VariantMDF(VariantMemberDescriptionFactory { offsets, args, span });
 
     (metadata_stub, member_description_factory)
 }
index 1fb201eda6bb0478d83dafe9fe35505be11382ea..a48a694b630f001cd5c17b34d82de0234a3a0d5d 100644 (file)
@@ -162,11 +162,14 @@ fn codegen_intrinsic_call(
 
             sym::volatile_load | sym::unaligned_volatile_load => {
                 let tp_ty = substs.type_at(0);
-                let mut ptr = args[0].immediate();
-                if let PassMode::Cast(ty) = fn_abi.ret.mode {
-                    ptr = self.pointercast(ptr, self.type_ptr_to(ty.llvm_type(self)));
-                }
-                let load = self.volatile_load(ptr);
+                let ptr = args[0].immediate();
+                let load = if let PassMode::Cast(ty) = fn_abi.ret.mode {
+                    let llty = ty.llvm_type(self);
+                    let ptr = self.pointercast(ptr, self.type_ptr_to(llty));
+                    self.volatile_load(llty, ptr)
+                } else {
+                    self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr)
+                };
                 let align = if name == sym::unaligned_volatile_load {
                     1
                 } else {
@@ -296,6 +299,44 @@ fn codegen_intrinsic_call(
                 }
             }
 
+            sym::raw_eq => {
+                use abi::Abi::*;
+                let tp_ty = substs.type_at(0);
+                let layout = self.layout_of(tp_ty).layout;
+                let use_integer_compare = match layout.abi {
+                    Scalar(_) | ScalarPair(_, _) => true,
+                    Uninhabited | Vector { .. } => false,
+                    Aggregate { .. } => {
+                        // For rusty ABIs, small aggregates are actually passed
+                        // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
+                        // so we re-use that same threshold here.
+                        layout.size <= self.data_layout().pointer_size * 2
+                    }
+                };
+
+                let a = args[0].immediate();
+                let b = args[1].immediate();
+                if layout.size.bytes() == 0 {
+                    self.const_bool(true)
+                } else if use_integer_compare {
+                    let integer_ty = self.type_ix(layout.size.bits());
+                    let ptr_ty = self.type_ptr_to(integer_ty);
+                    let a_ptr = self.bitcast(a, ptr_ty);
+                    let a_val = self.load(integer_ty, a_ptr, layout.align.abi);
+                    let b_ptr = self.bitcast(b, ptr_ty);
+                    let b_val = self.load(integer_ty, b_ptr, layout.align.abi);
+                    self.icmp(IntPredicate::IntEQ, a_val, b_val)
+                } else {
+                    let i8p_ty = self.type_i8p();
+                    let a_ptr = self.bitcast(a, i8p_ty);
+                    let b_ptr = self.bitcast(b, i8p_ty);
+                    let n = self.const_usize(layout.size.bytes());
+                    let llfn = self.get_intrinsic("memcmp");
+                    let cmp = self.call(llfn, &[a_ptr, b_ptr, n], None);
+                    self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
+                }
+            }
+
             _ if name_str.starts_with("simd_") => {
                 match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
                     Ok(llval) => llval,
@@ -502,7 +543,7 @@ fn codegen_msvc_try(
         // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
         let flags = bx.const_i32(8);
         let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]);
-        let ptr = catchpad_rust.load(slot, ptr_align);
+        let ptr = catchpad_rust.load(bx.type_i8p(), slot, ptr_align);
         catchpad_rust.call(catch_func, &[data, ptr], Some(&funclet));
         catchpad_rust.catch_ret(&funclet, caught.llbb());
 
index fc890f2385303458e1ee5aa0a8bdd1fa023626c4..26fd1cfbcd08e7dad15a1281f814106b86e50c9d 100644 (file)
@@ -292,12 +292,7 @@ fn link(
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        link_binary::<LlvmArchiveBuilder<'_>>(
-            sess,
-            &codegen_results,
-            outputs,
-            &codegen_results.crate_info.local_crate_name.as_str(),
-        );
+        link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs);
 
         Ok(())
     }
index 91923251018a898671319bc486f5b3e98f651f5e..2ade66ac41eda9cce77b737db651a6fe949bf712 100644 (file)
@@ -1385,7 +1385,12 @@ pub fn LLVMBuildArrayAlloca(
         Val: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildLoad2(
+        B: &Builder<'a>,
+        Ty: &'a Type,
+        PointerVal: &'a Value,
+        Name: *const c_char,
+    ) -> &'a Value;
 
     pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
 
@@ -1631,6 +1636,7 @@ pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>, Src: &'a Value, IsNaN: boo
     // Atomic Operations
     pub fn LLVMRustBuildAtomicLoad(
         B: &Builder<'a>,
+        ElementType: &'a Type,
         PointerVal: &'a Value,
         Name: *const c_char,
         Order: AtomicOrdering,
index 39d08fbee3b7fbc01a72522aef5d18d308f5a871..9df1bd7d1d9bb20897aa3022a92bfd6aab9d629f 100644 (file)
@@ -32,14 +32,15 @@ fn emit_direct_ptr_va_arg(
     slot_size: Align,
     allow_higher_align: bool,
 ) -> (&'ll Value, Align) {
-    let va_list_ptr_ty = bx.cx().type_ptr_to(bx.cx.type_i8p());
+    let va_list_ty = bx.type_i8p();
+    let va_list_ptr_ty = bx.type_ptr_to(va_list_ty);
     let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty {
         bx.bitcast(list.immediate(), va_list_ptr_ty)
     } else {
         list.immediate()
     };
 
-    let ptr = bx.load(va_list_addr, bx.tcx().data_layout.pointer_align.abi);
+    let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
 
     let (addr, addr_align) = if allow_higher_align && align > slot_size {
         (round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align)
@@ -82,10 +83,10 @@ fn emit_ptr_va_arg(
     let (addr, addr_align) =
         emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, slot_size, allow_higher_align);
     if indirect {
-        let tmp_ret = bx.load(addr, addr_align);
-        bx.load(tmp_ret, align.abi)
+        let tmp_ret = bx.load(llty, addr, addr_align);
+        bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi)
     } else {
-        bx.load(addr, addr_align)
+        bx.load(llty, addr, addr_align)
     }
 }
 
@@ -118,7 +119,7 @@ fn emit_aapcs_va_arg(
     };
 
     // if the offset >= 0 then the value will be on the stack
-    let mut reg_off_v = bx.load(reg_off, offset_align);
+    let mut reg_off_v = bx.load(bx.type_i32(), reg_off, offset_align);
     let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero);
     bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb());
 
@@ -139,8 +140,9 @@ fn emit_aapcs_va_arg(
     let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero);
     maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb());
 
+    let top_type = bx.type_i8p();
     let top = in_reg.struct_gep(va_list_addr, reg_top_index);
-    let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);
+    let top = in_reg.load(top_type, top, bx.tcx().data_layout.pointer_align.abi);
 
     // reg_value = *(@top + reg_off_v);
     let mut reg_addr = in_reg.gep(top, &[reg_off_v]);
@@ -149,8 +151,9 @@ fn emit_aapcs_va_arg(
         let offset = bx.const_i32((slot_size - layout.size.bytes()) as i32);
         reg_addr = in_reg.gep(reg_addr, &[offset]);
     }
-    let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(layout.llvm_type(bx)));
-    let reg_value = in_reg.load(reg_addr, layout.align.abi);
+    let reg_type = layout.llvm_type(bx);
+    let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type));
+    let reg_value = in_reg.load(reg_type, reg_addr, layout.align.abi);
     in_reg.br(&end.llbb());
 
     // On Stack block
index d47624da79a73f934e68d4cdf6f55cdbbd26c0fb..f9efa448c93fa32ef6970e414deb5f46443c66d2 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_errors::Handler;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::{DllImport, LibSource};
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -34,8 +34,8 @@
 use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind};
 use tempfile::Builder as TempFileBuilder;
 
-use std::cmp::Ordering;
 use std::ffi::OsString;
+use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
 use std::{ascii, char, env, fmt, fs, io, mem, str};
@@ -54,7 +54,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
     sess: &'a Session,
     codegen_results: &CodegenResults,
     outputs: &OutputFilenames,
-    crate_name: &str,
 ) {
     let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
@@ -87,7 +86,12 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
                 .tempdir()
                 .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
             let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
-            let out_filename = out_filename(sess, crate_type, outputs, crate_name);
+            let out_filename = out_filename(
+                sess,
+                crate_type,
+                outputs,
+                &codegen_results.crate_info.local_crate_name.as_str(),
+            );
             match crate_type {
                 CrateType::Rlib => {
                     let _timer = sess.timer("link_rlib");
@@ -143,102 +147,11 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
     });
 }
 
-// The third parameter is for env vars, used on windows to set up the
-// path for MSVC to find its DLLs, and gcc to find its bundled
-// toolchain
-fn get_linker(
-    sess: &Session,
-    linker: &Path,
-    flavor: LinkerFlavor,
-    self_contained: bool,
-) -> Command {
-    let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
-
-    // If our linker looks like a batch script on Windows then to execute this
-    // we'll need to spawn `cmd` explicitly. This is primarily done to handle
-    // emscripten where the linker is `emcc.bat` and needs to be spawned as
-    // `cmd /c emcc.bat ...`.
-    //
-    // This worked historically but is needed manually since #42436 (regression
-    // was tagged as #42791) and some more info can be found on #44443 for
-    // emscripten itself.
-    let mut cmd = match linker.to_str() {
-        Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
-        _ => match flavor {
-            LinkerFlavor::Lld(f) => Command::lld(linker, f),
-            LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
-                Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
-            }
-            _ => Command::new(linker),
-        },
-    };
-
-    // UWP apps have API restrictions enforced during Store submissions.
-    // To comply with the Windows App Certification Kit,
-    // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
-    let t = &sess.target;
-    if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
-        && t.vendor == "uwp"
-    {
-        if let Some(ref tool) = msvc_tool {
-            let original_path = tool.path();
-            if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
-                let arch = match t.arch.as_str() {
-                    "x86_64" => Some("x64"),
-                    "x86" => Some("x86"),
-                    "aarch64" => Some("arm64"),
-                    "arm" => Some("arm"),
-                    _ => None,
-                };
-                if let Some(ref a) = arch {
-                    // FIXME: Move this to `fn linker_with_args`.
-                    let mut arg = OsString::from("/LIBPATH:");
-                    arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
-                    cmd.arg(&arg);
-                } else {
-                    warn!("arch is not supported");
-                }
-            } else {
-                warn!("MSVC root path lib location not found");
-            }
-        } else {
-            warn!("link.exe not found");
-        }
-    }
-
-    // The compiler's sysroot often has some bundled tools, so add it to the
-    // PATH for the child.
-    let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
-    let mut msvc_changed_path = false;
-    if sess.target.is_like_msvc {
-        if let Some(ref tool) = msvc_tool {
-            cmd.args(tool.args());
-            for &(ref k, ref v) in tool.env() {
-                if k == "PATH" {
-                    new_path.extend(env::split_paths(v));
-                    msvc_changed_path = true;
-                } else {
-                    cmd.env(k, v);
-                }
-            }
-        }
-    }
-
-    if !msvc_changed_path {
-        if let Some(path) = env::var_os("PATH") {
-            new_path.extend(env::split_paths(&path));
-        }
-    }
-    cmd.env("PATH", env::join_paths(new_path).unwrap());
-
-    cmd
-}
-
 pub fn each_linked_rlib(
     info: &CrateInfo,
     f: &mut dyn FnMut(CrateNum, &Path),
 ) -> Result<(), String> {
-    let crates = info.used_crates_static.iter();
+    let crates = info.used_crates.iter();
     let mut fmts = None;
     for (ty, list) in info.dependency_formats.iter() {
         match ty {
@@ -256,22 +169,23 @@ pub fn each_linked_rlib(
         Some(f) => f,
         None => return Err("could not find formats for rlibs".to_string()),
     };
-    for &(cnum, ref path) in crates {
+    for &cnum in crates {
         match fmts.get(cnum.as_usize() - 1) {
             Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue,
             Some(_) => {}
             None => return Err("could not find formats for rlibs".to_string()),
         }
         let name = &info.crate_name[&cnum];
-        let path = match *path {
-            LibSource::Some(ref p) => p,
-            LibSource::MetadataOnly => {
-                return Err(format!(
-                    "could not find rlib for: `{}`, found rmeta (metadata) file",
-                    name
-                ));
-            }
-            LibSource::None => return Err(format!("could not find rlib for: `{}`", name)),
+        let used_crate_source = &info.used_crate_source[&cnum];
+        let path = if let Some((path, _)) = &used_crate_source.rlib {
+            path
+        } else if used_crate_source.rmeta.is_some() {
+            return Err(format!(
+                "could not find rlib for: `{}`, found rmeta (metadata) file",
+                name
+            ));
+        } else {
+            return Err(format!("could not find rlib for: `{}`", name));
         };
         f(cnum, &path);
     }
@@ -345,7 +259,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     }
 
     for (raw_dylib_name, raw_dylib_imports) in
-        collate_raw_dylibs(&codegen_results.crate_info.used_libraries)
+        collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)
     {
         ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
     }
@@ -537,8 +451,11 @@ fn create_metadata_file(sess: &Session, metadata: &[u8]) -> Vec<u8> {
 /// then the CodegenResults value contains one NativeLib instance for each block.  However, the
 /// linker appears to expect only a single import library for each library used, so we need to
 /// collate the symbols together by library name before generating the import libraries.
-fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImport>)> {
-    let mut dylib_table: FxHashMap<String, FxHashSet<Symbol>> = FxHashMap::default();
+fn collate_raw_dylibs(
+    sess: &Session,
+    used_libraries: &[NativeLib],
+) -> Vec<(String, Vec<DllImport>)> {
+    let mut dylib_table: FxHashMap<String, FxHashSet<DllImport>> = FxHashMap::default();
 
     for lib in used_libraries {
         if lib.kind == NativeLibKind::RawDylib {
@@ -550,35 +467,51 @@ fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImpor
             } else {
                 format!("{}.dll", name)
             };
-            dylib_table
-                .entry(name)
-                .or_default()
-                .extend(lib.dll_imports.iter().map(|import| import.name));
+            dylib_table.entry(name).or_default().extend(lib.dll_imports.iter().cloned());
         }
     }
 
-    // FIXME: when we add support for ordinals, fix this to propagate ordinals.  Also figure out
-    // what we should do if we have two DllImport values with the same name but different
-    // ordinals.
-    let mut result = dylib_table
+    // Rustc already signals an error if we have two imports with the same name but different
+    // calling conventions (or function signatures), so we don't have pay attention to those
+    // when ordering.
+    // FIXME: when we add support for ordinals, figure out if we need to do anything if we
+    // have two DllImport values with the same name but different ordinals.
+    let mut result: Vec<(String, Vec<DllImport>)> = dylib_table
         .into_iter()
-        .map(|(lib_name, imported_names)| {
-            let mut names = imported_names
-                .iter()
-                .map(|name| DllImport { name: *name, ordinal: None })
-                .collect::<Vec<_>>();
-            names.sort_unstable_by(|a: &DllImport, b: &DllImport| {
-                match a.name.as_str().cmp(&b.name.as_str()) {
-                    Ordering::Equal => a.ordinal.cmp(&b.ordinal),
-                    x => x,
-                }
-            });
-            (lib_name, names)
+        .map(|(lib_name, import_table)| {
+            let mut imports = Vec::from_iter(import_table.into_iter());
+            imports.sort_unstable_by_key(|x: &DllImport| x.name.as_str());
+            (lib_name, imports)
         })
         .collect::<Vec<_>>();
     result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
         a.0.cmp(&b.0)
     });
+    let result = result;
+
+    // Check for multiple imports with the same name but different calling conventions or
+    // (when relevant) argument list sizes.  Rustc only signals an error for this if the
+    // declarations are at the same scope level; if one shadows the other, we only get a lint
+    // warning.
+    for (library, imports) in &result {
+        let mut import_table: FxHashMap<Symbol, DllCallingConvention> = FxHashMap::default();
+        for import in imports {
+            if let Some(old_convention) =
+                import_table.insert(import.name, import.calling_convention)
+            {
+                if import.calling_convention != old_convention {
+                    sess.span_fatal(
+                        import.span,
+                        &format!(
+                            "multiple definitions of external function `{}` from library `{}` have different calling conventions",
+                            import.name,
+                            library,
+                    ));
+                }
+            }
+        }
+    }
+
     result
 }
 
@@ -1759,8 +1692,19 @@ fn add_rpath_args(
     // where extern libraries might live, based on the
     // add_lib_search_paths
     if sess.opts.cg.rpath {
+        let libs = codegen_results
+            .crate_info
+            .used_crates
+            .iter()
+            .filter_map(|cnum| {
+                codegen_results.crate_info.used_crate_source[cnum]
+                    .dylib
+                    .as_ref()
+                    .map(|(path, _)| &**path)
+            })
+            .collect::<Vec<_>>();
         let mut rpath_config = RPathConfig {
-            used_crates: &codegen_results.crate_info.used_crates_dynamic,
+            libs: &*libs,
             out_filename: out_filename.to_path_buf(),
             has_rpath: sess.target.has_rpath,
             is_like_osx: sess.target.is_like_osx,
@@ -1788,11 +1732,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     codegen_results: &CodegenResults,
 ) -> Command {
     let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
-    let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
-    // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
-    // to the linker args construction.
-    assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");
-    let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor);
+    let cmd = &mut *super::linker::get_linker(
+        sess,
+        path,
+        flavor,
+        crt_objects_fallback,
+        &codegen_results.crate_info.target_cpu,
+    );
     let link_output_kind = link_output_kind(sess, crate_type);
 
     // ------------ Early order-dependent options ------------
@@ -1802,7 +1748,11 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     // dynamic library.
     // Must be passed before any libraries to prevent the symbols to export from being thrown away,
     // at least on some platforms (e.g. windows-gnu).
-    cmd.export_symbols(tmpdir, crate_type);
+    cmd.export_symbols(
+        tmpdir,
+        crate_type,
+        &codegen_results.crate_info.exported_symbols[&crate_type],
+    );
 
     // Can be used for adding custom CRT objects or overriding order-dependent options above.
     // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
@@ -1974,10 +1924,10 @@ fn add_order_independent_options(
     if flavor == LinkerFlavor::PtxLinker {
         // Provide the linker with fallback to internal `target-cpu`.
         cmd.arg("--fallback-arch");
-        cmd.arg(&codegen_results.linker_info.target_cpu);
+        cmd.arg(&codegen_results.crate_info.target_cpu);
     } else if flavor == LinkerFlavor::BpfLinker {
         cmd.arg("--cpu");
-        cmd.arg(&codegen_results.linker_info.target_cpu);
+        cmd.arg(&codegen_results.crate_info.target_cpu);
         cmd.arg("--cpu-features");
         cmd.arg(match &sess.opts.cg.target_feature {
             feat if !feat.is_empty() => feat,
@@ -2121,7 +2071,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
 
     // Invoke get_used_crates to ensure that we get a topological sorting of
     // crates.
-    let deps = &codegen_results.crate_info.used_crates_dynamic;
+    let deps = &codegen_results.crate_info.used_crates;
 
     // There's a few internal crates in the standard library (aka libcore and
     // libstd) which actually have a circular dependence upon one another. This
@@ -2149,7 +2099,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     let mut required = FxHashSet::default();
 
     let info = &codegen_results.crate_info;
-    for &(cnum, _) in deps.iter().rev() {
+    for &cnum in deps.iter().rev() {
         if let Some(missing) = info.missing_lang_items.get(&cnum) {
             let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied());
             required.extend(missing_crates);
@@ -2176,7 +2126,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
 
     let mut compiler_builtins = None;
 
-    for &(cnum, _) in deps.iter() {
+    for &cnum in deps.iter() {
         if group_start == Some(cnum) {
             cmd.group_start();
         }
@@ -2388,9 +2338,9 @@ fn add_upstream_native_libraries(
         .find(|(ty, _)| *ty == crate_type)
         .expect("failed to find crate type in dependency format list");
 
-    let crates = &codegen_results.crate_info.used_crates_static;
+    let crates = &codegen_results.crate_info.used_crates;
     let mut last = (NativeLibKind::Unspecified, None);
-    for &(cnum, _) in crates {
+    for &cnum in crates {
         for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
             let name = match lib.name {
                 Some(l) => l,
index 43ff664c3e641059488a75f90f672990418144bb..9e1c6a169f1525235ac04d526f6a54dd944cd6b4 100644 (file)
@@ -7,19 +7,21 @@
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufWriter};
-use std::mem;
 use std::path::{Path, PathBuf};
+use std::{env, mem, str};
 
-use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::ty::TyCtxt;
 use rustc_serialize::{json, Encoder};
 use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
+use rustc_session::search_paths::PathKind;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
 
+use cc::windows_registry;
+
 /// Disables non-English messages from localized linkers.
 /// Such messages may cause issues with text encoding on Windows (#35785)
 /// and prevent inspection of linker output in case of errors, which we occasionally do.
@@ -33,60 +35,121 @@ pub fn disable_localization(linker: &mut Command) {
     linker.env("VSLANG", "1033");
 }
 
-/// For all the linkers we support, and information they might
-/// need out of the shared crate context before we get rid of it.
-#[derive(Encodable, Decodable)]
-pub struct LinkerInfo {
-    pub(super) target_cpu: String,
-    exports: FxHashMap<CrateType, Vec<String>>,
-}
-
-impl LinkerInfo {
-    pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> LinkerInfo {
-        LinkerInfo {
-            target_cpu,
-            exports: tcx
-                .sess
-                .crate_types()
-                .iter()
-                .map(|&c| (c, exported_symbols(tcx, c)))
-                .collect(),
+// The third parameter is for env vars, used on windows to set up the
+// path for MSVC to find its DLLs, and gcc to find its bundled
+// toolchain
+pub fn get_linker<'a>(
+    sess: &'a Session,
+    linker: &Path,
+    flavor: LinkerFlavor,
+    self_contained: bool,
+    target_cpu: &'a str,
+) -> Box<dyn Linker + 'a> {
+    let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
+
+    // If our linker looks like a batch script on Windows then to execute this
+    // we'll need to spawn `cmd` explicitly. This is primarily done to handle
+    // emscripten where the linker is `emcc.bat` and needs to be spawned as
+    // `cmd /c emcc.bat ...`.
+    //
+    // This worked historically but is needed manually since #42436 (regression
+    // was tagged as #42791) and some more info can be found on #44443 for
+    // emscripten itself.
+    let mut cmd = match linker.to_str() {
+        Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
+        _ => match flavor {
+            LinkerFlavor::Lld(f) => Command::lld(linker, f),
+            LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
+                Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
+            }
+            _ => Command::new(linker),
+        },
+    };
+
+    // UWP apps have API restrictions enforced during Store submissions.
+    // To comply with the Windows App Certification Kit,
+    // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
+    let t = &sess.target;
+    if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
+        && t.vendor == "uwp"
+    {
+        if let Some(ref tool) = msvc_tool {
+            let original_path = tool.path();
+            if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
+                let arch = match t.arch.as_str() {
+                    "x86_64" => Some("x64"),
+                    "x86" => Some("x86"),
+                    "aarch64" => Some("arm64"),
+                    "arm" => Some("arm"),
+                    _ => None,
+                };
+                if let Some(ref a) = arch {
+                    // FIXME: Move this to `fn linker_with_args`.
+                    let mut arg = OsString::from("/LIBPATH:");
+                    arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
+                    cmd.arg(&arg);
+                } else {
+                    warn!("arch is not supported");
+                }
+            } else {
+                warn!("MSVC root path lib location not found");
+            }
+        } else {
+            warn!("link.exe not found");
         }
     }
 
-    pub fn to_linker<'a>(
-        &'a self,
-        cmd: Command,
-        sess: &'a Session,
-        flavor: LinkerFlavor,
-    ) -> Box<dyn Linker + 'a> {
-        match flavor {
-            LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
-                Box::new(MsvcLinker { cmd, sess, info: self }) as Box<dyn Linker>
-            }
-            LinkerFlavor::Em => Box::new(EmLinker { cmd, sess, info: self }) as Box<dyn Linker>,
-            LinkerFlavor::Gcc => {
-                Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: false })
-                    as Box<dyn Linker>
+    // The compiler's sysroot often has some bundled tools, so add it to the
+    // PATH for the child.
+    let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
+    let mut msvc_changed_path = false;
+    if sess.target.is_like_msvc {
+        if let Some(ref tool) = msvc_tool {
+            cmd.args(tool.args());
+            for &(ref k, ref v) in tool.env() {
+                if k == "PATH" {
+                    new_path.extend(env::split_paths(v));
+                    msvc_changed_path = true;
+                } else {
+                    cmd.env(k, v);
+                }
             }
+        }
+    }
 
-            LinkerFlavor::Lld(LldFlavor::Ld)
-            | LinkerFlavor::Lld(LldFlavor::Ld64)
-            | LinkerFlavor::Ld => {
-                Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: true })
-                    as Box<dyn Linker>
-            }
+    if !msvc_changed_path {
+        if let Some(path) = env::var_os("PATH") {
+            new_path.extend(env::split_paths(&path));
+        }
+    }
+    cmd.env("PATH", env::join_paths(new_path).unwrap());
 
-            LinkerFlavor::Lld(LldFlavor::Wasm) => {
-                Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
-            }
+    // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
+    // to the linker args construction.
+    assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
 
-            LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
+    match flavor {
+        LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
+            Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
+        }
+        LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
+        LinkerFlavor::Gcc => {
+            Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
+                as Box<dyn Linker>
+        }
 
-            LinkerFlavor::BpfLinker => {
-                Box::new(BpfLinker { cmd, sess, info: self }) as Box<dyn Linker>
-            }
+        LinkerFlavor::Lld(LldFlavor::Ld)
+        | LinkerFlavor::Lld(LldFlavor::Ld64)
+        | LinkerFlavor::Ld => {
+            Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
+                as Box<dyn Linker>
         }
+
+        LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
+
+        LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
+
+        LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
     }
 }
 
@@ -122,7 +185,7 @@ pub trait Linker {
     fn debuginfo(&mut self, strip: Strip);
     fn no_crt_objects(&mut self);
     fn no_default_libraries(&mut self);
-    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
     fn subsystem(&mut self, subsystem: &str);
     fn group_start(&mut self);
     fn group_end(&mut self);
@@ -150,7 +213,7 @@ pub fn take_cmd(&mut self) -> Command {
 pub struct GccLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
+    target_cpu: &'a str,
     hinted_static: bool, // Keeps track of the current hinting mode.
     // Link as ld
     is_ld: bool,
@@ -225,7 +288,7 @@ fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
         };
 
         self.linker_arg(&format!("-plugin-opt={}", opt_level));
-        self.linker_arg(&format!("-plugin-opt=mcpu={}", self.info.target_cpu));
+        self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu));
     }
 
     fn build_dylib(&mut self, out_filename: &Path) {
@@ -554,7 +617,7 @@ fn no_default_libraries(&mut self) {
         }
     }
 
-    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
         // Symbol visibility in object files typically takes care of this.
         if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none()
         {
@@ -583,7 +646,7 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
             // Write a plain, newline-separated list of symbols
             let res: io::Result<()> = try {
                 let mut f = BufWriter::new(File::create(&path)?);
-                for sym in self.info.exports[&crate_type].iter() {
+                for sym in symbols {
                     debug!("  _{}", sym);
                     writeln!(f, "_{}", sym)?;
                 }
@@ -598,7 +661,7 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
                 // .def file similar to MSVC one but without LIBRARY section
                 // because LD doesn't like when it's empty
                 writeln!(f, "EXPORTS")?;
-                for symbol in self.info.exports[&crate_type].iter() {
+                for symbol in symbols {
                     debug!("  _{}", symbol);
                     writeln!(f, "  {}", symbol)?;
                 }
@@ -611,9 +674,9 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
             let res: io::Result<()> = try {
                 let mut f = BufWriter::new(File::create(&path)?);
                 writeln!(f, "{{")?;
-                if !self.info.exports[&crate_type].is_empty() {
+                if !symbols.is_empty() {
                     writeln!(f, "  global:")?;
-                    for sym in self.info.exports[&crate_type].iter() {
+                    for sym in symbols {
                         debug!("    {};", sym);
                         writeln!(f, "    {};", sym)?;
                     }
@@ -713,7 +776,6 @@ fn add_as_needed(&mut self) {
 pub struct MsvcLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for MsvcLinker<'a> {
@@ -887,7 +949,7 @@ fn debuginfo(&mut self, strip: Strip) {
     // crates. Upstream rlibs may be linked statically to this dynamic library,
     // in which case they may continue to transitively be used and hence need
     // their symbols exported.
-    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
         // Symbol visibility takes care of this typically
         if crate_type == CrateType::Executable {
             return;
@@ -901,7 +963,7 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
             // straight to exports.
             writeln!(f, "LIBRARY")?;
             writeln!(f, "EXPORTS")?;
-            for symbol in self.info.exports[&crate_type].iter() {
+            for symbol in symbols {
                 debug!("  _{}", symbol);
                 writeln!(f, "  {}", symbol)?;
             }
@@ -954,7 +1016,6 @@ fn add_no_exec(&mut self) {
 pub struct EmLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for EmLinker<'a> {
@@ -1066,9 +1127,7 @@ fn no_default_libraries(&mut self) {
         self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
     }
 
-    fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
-        let symbols = &self.info.exports[&crate_type];
-
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
         debug!("EXPORTED SYMBOLS:");
 
         self.cmd.arg("-s");
@@ -1110,11 +1169,10 @@ fn linker_plugin_lto(&mut self) {
 pub struct WasmLd<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> WasmLd<'a> {
-    fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
+    fn new(mut cmd: Command, sess: &'a Session) -> WasmLd<'a> {
         // If the atomics feature is enabled for wasm then we need a whole bunch
         // of flags:
         //
@@ -1147,7 +1205,7 @@ fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a>
             cmd.arg("--export=__tls_align");
             cmd.arg("--export=__tls_base");
         }
-        WasmLd { cmd, sess, info }
+        WasmLd { cmd, sess }
     }
 }
 
@@ -1263,8 +1321,8 @@ fn no_crt_objects(&mut self) {}
 
     fn no_default_libraries(&mut self) {}
 
-    fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
-        for sym in self.info.exports[&crate_type].iter() {
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
+        for sym in symbols {
             self.cmd.arg("--export").arg(&sym);
         }
 
@@ -1287,7 +1345,7 @@ fn linker_plugin_lto(&mut self) {
     }
 }
 
-fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
+pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
     if let Some(ref exports) = tcx.sess.target.override_export_symbols {
         return exports.clone();
     }
@@ -1416,7 +1474,7 @@ fn no_default_libraries(&mut self) {}
 
     fn control_flow_guard(&mut self) {}
 
-    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
@@ -1430,7 +1488,6 @@ fn linker_plugin_lto(&mut self) {}
 pub struct BpfLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for BpfLinker<'a> {
@@ -1517,11 +1574,11 @@ fn no_default_libraries(&mut self) {}
 
     fn control_flow_guard(&mut self) {}
 
-    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+    fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
         let path = tmpdir.join("symbols");
         let res: io::Result<()> = try {
             let mut f = BufWriter::new(File::create(&path)?);
-            for sym in self.info.exports[&crate_type].iter() {
+            for sym in symbols {
                 writeln!(f, "{}", sym)?;
             }
         };
index 39b0ccd120de519c747af97a88091c035d1cf4a2..61c3ef62fb1930c977f78753b2f974f225570bdb 100644 (file)
@@ -4,11 +4,8 @@
 use std::fs;
 use std::path::{Path, PathBuf};
 
-use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::LibSource;
-
 pub struct RPathConfig<'a> {
-    pub used_crates: &'a [(CrateNum, LibSource)],
+    pub libs: &'a [&'a Path],
     pub out_filename: PathBuf,
     pub is_like_osx: bool,
     pub has_rpath: bool,
@@ -23,9 +20,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
 
     debug!("preparing the RPATH!");
 
-    let libs = config.used_crates;
-    let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::<Vec<_>>();
-    let rpaths = get_rpaths(config, &libs);
+    let rpaths = get_rpaths(config);
     let mut flags = rpaths_to_flags(&rpaths);
 
     // Use DT_RUNPATH instead of DT_RPATH if available
@@ -52,17 +47,17 @@ fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
     ret
 }
 
-fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
+fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<String> {
     debug!("output: {:?}", config.out_filename.display());
     debug!("libs:");
-    for libpath in libs {
+    for libpath in config.libs {
         debug!("    {:?}", libpath.display());
     }
 
     // Use relative paths to the libraries. Binaries can be moved
     // as long as they maintain the relative relationship to the
     // crates they depend on.
-    let rpaths = get_rpaths_relative_to_output(config, libs);
+    let rpaths = get_rpaths_relative_to_output(config);
 
     debug!("rpaths:");
     for rpath in &rpaths {
@@ -73,8 +68,8 @@ fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
     minimize_rpaths(&rpaths)
 }
 
-fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
-    libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
+fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<String> {
+    config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
 }
 
 fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> String {
index 24c362db12275b103947ad2cbfcdaaecf4f9faae..604f19144a6a446a0310655e94384158e88acbda 100644 (file)
@@ -35,7 +35,7 @@ fn test_minimize2() {
 fn test_rpath_relative() {
     if cfg!(target_os = "macos") {
         let config = &mut RPathConfig {
-            used_crates: &[],
+            libs: &[],
             has_rpath: true,
             is_like_osx: true,
             linker_is_gnu: false,
@@ -45,7 +45,7 @@ fn test_rpath_relative() {
         assert_eq!(res, "@loader_path/../lib");
     } else {
         let config = &mut RPathConfig {
-            used_crates: &[],
+            libs: &[],
             out_filename: PathBuf::from("bin/rustc"),
             has_rpath: true,
             is_like_osx: false,
index d27eb7da810bef4f27f93f1e4c6840f110cf0f48..41823f7d80d69acd3d28c95060a91c4b517c33b4 100644 (file)
@@ -1,5 +1,4 @@
 use super::link::{self, ensure_removed};
-use super::linker::LinkerInfo;
 use super::lto::{self, SerializedModule};
 use super::symbol_export::symbol_name_for_instance_in_crate;
 
@@ -430,8 +429,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
     let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
 
-    let linker_info = LinkerInfo::new(tcx, target_cpu);
-    let crate_info = CrateInfo::new(tcx);
+    let crate_info = CrateInfo::new(tcx, target_cpu);
 
     let regular_config =
         ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins);
@@ -461,7 +459,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     OngoingCodegen {
         backend,
         metadata,
-        linker_info,
         crate_info,
 
         coordinator_send,
@@ -1799,7 +1796,6 @@ pub fn check(&self, sess: &Session, blocking: bool) {
 pub struct OngoingCodegen<B: ExtraBackendMethods> {
     pub backend: B,
     pub metadata: EncodedMetadata,
-    pub linker_info: LinkerInfo,
     pub crate_info: CrateInfo,
     pub coordinator_send: Sender<Box<dyn Any + Send>>,
     pub codegen_worker_receive: Receiver<Message<B>>,
@@ -1842,7 +1838,6 @@ pub fn join(self, sess: &Session) -> (CodegenResults, FxHashMap<WorkProductId, W
         (
             CodegenResults {
                 metadata: self.metadata,
-                linker_info: self.linker_info,
                 crate_info: self.crate_info,
 
                 modules: compiled_modules.modules,
index ec1aa4fd58eb38465a35b99df9222ded0ade4878..be2bf8b199724ab59a00a6c054d38034b783e914 100644 (file)
@@ -20,7 +20,6 @@
 use rustc_index::vec::Idx;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::cstore::EncodedMetadata;
-use rustc_middle::middle::cstore::{self, LinkagePreference};
 use rustc_middle::middle::lang_items;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
 use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
@@ -755,7 +754,13 @@ fn drop(&mut self) {
 }
 
 impl CrateInfo {
-    pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
+    pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
+        let exported_symbols = tcx
+            .sess
+            .crate_types()
+            .iter()
+            .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
+            .collect();
         let local_crate_name = tcx.crate_name(LOCAL_CRATE);
         let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
         let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
@@ -770,17 +775,33 @@ pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
             subsystem.to_string()
         });
 
+        // This list is used when generating the command line to pass through to
+        // system linker. The linker expects undefined symbols on the left of the
+        // command line to be defined in libraries on the right, not the other way
+        // around. For more info, see some comments in the add_used_library function
+        // below.
+        //
+        // In order to get this left-to-right dependency ordering, we use the reverse
+        // postorder of all crates putting the leaves at the right-most positions.
+        let used_crates = tcx
+            .postorder_cnums(())
+            .iter()
+            .rev()
+            .copied()
+            .filter(|&cnum| !tcx.dep_kind(cnum).macros_only())
+            .collect();
+
         let mut info = CrateInfo {
+            target_cpu,
+            exported_symbols,
             local_crate_name,
-            panic_runtime: None,
             compiler_builtins: None,
             profiler_runtime: None,
             is_no_builtins: Default::default(),
             native_libraries: Default::default(),
             used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
             crate_name: Default::default(),
-            used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
-            used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
+            used_crates,
             used_crate_source: Default::default(),
             lang_item_to_crate: Default::default(),
             missing_lang_items: Default::default(),
@@ -802,9 +823,6 @@ pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
                 .insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect());
             info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
             info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
-            if tcx.is_panic_runtime(cnum) {
-                info.panic_runtime = Some(cnum);
-            }
             if tcx.is_compiler_builtins(cnum) {
                 info.compiler_builtins = Some(cnum);
             }
index a97c6a6b4429f7c77ac1d626fa686a2f1af95fb3..b3c14d9072ccec77a517d02b581039bfe187bf71 100644 (file)
@@ -367,6 +367,10 @@ fn msvc_enum_fallback(
     ) {
         let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error");
 
+        output.push_str("enum$<");
+        push_item_name(tcx, def.did, true, output);
+        push_generic_params_internal(tcx, substs, output, visited);
+
         if let Variants::Multiple {
             tag_encoding: TagEncoding::Niche { dataful_variant, .. },
             tag,
@@ -386,19 +390,19 @@ fn msvc_enum_fallback(
             let max = dataful_discriminant_range.end();
             let max = tag.value.size(&tcx).truncate(*max);
 
-            output.push_str("enum$<");
-            push_item_name(tcx, def.did, true, output);
-            push_generic_params_internal(tcx, substs, output, visited);
-
             let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
 
-            output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name));
-        } else {
-            output.push_str("enum$<");
-            push_item_name(tcx, def.did, true, output);
-            push_generic_params_internal(tcx, substs, output, visited);
-            push_close_angle_bracket(tcx, output);
+            output.push_str(&format!(", {}, {}, {}", min, max, dataful_variant_name));
+        } else if let Variants::Single { index: variant_idx } = &layout.variants {
+            // Uninhabited enums can't be constructed and should never need to be visualized so
+            // skip this step for them.
+            if def.variants.len() != 0 {
+                let variant = def.variants[*variant_idx].ident.as_str();
+
+                output.push_str(&format!(", {}", variant));
+            }
         }
+        push_close_angle_bracket(tcx, output);
     }
 }
 
index b6de12fa35e37ee183dcc89412d5ad2af0a08d8a..b6ee70c419b160e224a8dcb60067c8ff9e240e06 100644 (file)
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::LangItem;
 use rustc_middle::dep_graph::WorkProduct;
-use rustc_middle::middle::cstore::{self, CrateSource, LibSource};
+use rustc_middle::middle::cstore::{self, CrateSource};
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::ty::query::Providers;
-use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
+use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::utils::NativeLibKind;
 use rustc_span::symbol::Symbol;
 use std::path::{Path, PathBuf};
@@ -135,8 +135,9 @@ fn from(lib: &cstore::NativeLib) -> Self {
 /// and the corresponding properties without referencing information outside of a `CrateInfo`.
 #[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
+    pub target_cpu: String,
+    pub exported_symbols: FxHashMap<CrateType, Vec<String>>,
     pub local_crate_name: Symbol,
-    pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
     pub is_no_builtins: FxHashSet<CrateNum>,
@@ -144,8 +145,7 @@ pub struct CrateInfo {
     pub crate_name: FxHashMap<CrateNum, String>,
     pub used_libraries: Vec<NativeLib>,
     pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
-    pub used_crates_static: Vec<(CrateNum, LibSource)>,
-    pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
+    pub used_crates: Vec<CrateNum>,
     pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
     pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
     pub dependency_formats: Lrc<Dependencies>,
@@ -158,7 +158,6 @@ pub struct CodegenResults {
     pub allocator_module: Option<CompiledModule>,
     pub metadata_module: Option<CompiledModule>,
     pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
-    pub linker_info: back::linker::LinkerInfo,
     pub crate_info: CrateInfo,
 }
 
index 63245a94c8e3d8fb9388d85e948e8347c53865a5..b392b2c4ab8acfc70aa129b04767cb9efb8d9338 100644 (file)
@@ -20,10 +20,11 @@ pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
         // Load the data pointer from the object.
         debug!("get_fn({:?}, {:?})", llvtable, self);
 
-        let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.fn_ptr_backend_type(fn_abi)));
+        let llty = bx.fn_ptr_backend_type(fn_abi);
+        let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
-        let ptr = bx.load(gep, ptr_align);
+        let ptr = bx.load(llty, gep, ptr_align);
         bx.nonnull_metadata(ptr);
         // Vtable loads are invariant.
         bx.set_invariant_load(ptr);
@@ -38,10 +39,11 @@ pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
         // Load the data pointer from the object.
         debug!("get_int({:?}, {:?})", llvtable, self);
 
-        let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.type_isize()));
+        let llty = bx.type_isize();
+        let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
         let usize_align = bx.tcx().data_layout.pointer_align.abi;
         let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
-        let ptr = bx.load(gep, usize_align);
+        let ptr = bx.load(llty, gep, usize_align);
         // Vtable loads are invariant.
         bx.set_invariant_load(ptr);
         ptr
index 2cb28d7361c33b6a56a0280629f0f359954df8c4..b584801a62de2cb91cefe79303dae8bb58d6fb3b 100644 (file)
@@ -260,7 +260,7 @@ fn codegen_return_terminator(&mut self, mut bx: Bx) {
             PassMode::Direct(_) | PassMode::Pair(..) => {
                 let op = self.codegen_consume(&mut bx, mir::Place::return_place().as_ref());
                 if let Ref(llval, _, align) = op.val {
-                    bx.load(llval, align)
+                    bx.load(bx.backend_type(op.layout), llval, align)
                 } else {
                     op.immediate_or_packed_pair(&mut bx)
                 }
@@ -287,8 +287,9 @@ fn codegen_return_terminator(&mut self, mut bx: Bx) {
                         llval
                     }
                 };
-                let addr = bx.pointercast(llslot, bx.type_ptr_to(bx.cast_backend_type(&cast_ty)));
-                bx.load(addr, self.fn_abi.ret.layout.align.abi)
+                let ty = bx.cast_backend_type(&cast_ty);
+                let addr = bx.pointercast(llslot, bx.type_ptr_to(ty));
+                bx.load(ty, addr, self.fn_abi.ret.layout.align.abi)
             }
         };
         bx.ret(llval);
@@ -1086,15 +1087,16 @@ fn codegen_argument(
         if by_ref && !arg.is_indirect() {
             // Have to load the argument, maybe while casting it.
             if let PassMode::Cast(ty) = arg.mode {
-                let addr = bx.pointercast(llval, bx.type_ptr_to(bx.cast_backend_type(&ty)));
-                llval = bx.load(addr, align.min(arg.layout.align.abi));
+                let llty = bx.cast_backend_type(&ty);
+                let addr = bx.pointercast(llval, bx.type_ptr_to(llty));
+                llval = bx.load(llty, addr, align.min(arg.layout.align.abi));
             } else {
                 // We can't use `PlaceRef::load` here because the argument
                 // may have a type we don't treat as immediate, but the ABI
                 // used for this call is passing it by-value. In that case,
                 // the load would just produce `OperandValue::Ref` instead
                 // of the `OperandValue::Immediate` we need for the call.
-                llval = bx.load(llval, align);
+                llval = bx.load(bx.backend_type(arg.layout), llval, align);
                 if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
                     if scalar.is_bool() {
                         bx.range_metadata(llval, 0..2);
index 6bb20545f07bea36fed1ea8a0092aa0ef2c4d327..c139f915e6cbb21932924f897e7a2822da161658 100644 (file)
@@ -274,7 +274,7 @@ pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
                 match *elem {
                     mir::ProjectionElem::Deref => {
                         indirect_offsets.push(Size::ZERO);
-                        place = place.project_deref(bx);
+                        place = bx.load_operand(place).deref(bx.cx());
                     }
                     mir::ProjectionElem::Field(field, _) => {
                         let i = field.index();
index 8502309b90e5a1e7bfab7d1bd54cdc16b7d229e4..56ff1b3934c13e1b070bf56d2becc9e3af7b18d7 100644 (file)
@@ -448,15 +448,14 @@ pub fn codegen_intrinsic_call(
                             if ty.is_unsafe_ptr() {
                                 // Some platforms do not support atomic operations on pointers,
                                 // so we cast to integer first...
-                                let ptr_llty = bx.type_ptr_to(bx.type_isize());
+                                let llty = bx.type_isize();
+                                let ptr_llty = bx.type_ptr_to(llty);
                                 source = bx.pointercast(source, ptr_llty);
-                            }
-                            let result = bx.atomic_load(source, order, size);
-                            if ty.is_unsafe_ptr() {
+                                let result = bx.atomic_load(llty, source, order, size);
                                 // ... and then cast the result back to a pointer
                                 bx.inttoptr(result, bx.backend_type(layout))
                             } else {
-                                result
+                                bx.atomic_load(bx.backend_type(layout), source, order, size)
                             }
                         } else {
                             return invalid_monomorphization(ty);
index 25e84c38ed31518574360442649507db56e3ab6b..3c42b2cc2ea7a57206bf5a0b31587063f9690c82 100644 (file)
@@ -289,6 +289,14 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         }
         match self {
             OperandValue::Ref(r, None, source_align) => {
+                if flags.contains(MemFlags::NONTEMPORAL) {
+                    // HACK(nox): This is inefficient but there is no nontemporal memcpy.
+                    let ty = bx.backend_type(dest.layout);
+                    let ptr = bx.pointercast(r, bx.type_ptr_to(ty));
+                    let val = bx.load(ty, ptr, source_align);
+                    bx.store_with_flags(val, dest.llval, dest.align, flags);
+                    return;
+                }
                 base::memcpy_ty(bx, dest.llval, dest.align, r, source_align, dest.layout, flags)
             }
             OperandValue::Ref(_, Some(_), _) => {
index a9e7ebf6d43f72f178551e95592679bd8f683a0a..66d9d1a1e0c490ef2237a25e1602c92f8ceda921 100644 (file)
@@ -402,18 +402,6 @@ pub fn project_downcast<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         downcast
     }
 
-    pub fn project_deref<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) -> Self {
-        let target_ty = self.layout.ty.builtin_deref(true).expect("failed to deref");
-        let layout = bx.layout_of(target_ty.ty);
-
-        PlaceRef {
-            llval: bx.load(self.llval, self.align),
-            llextra: None,
-            layout,
-            align: layout.align.abi,
-        }
-    }
-
     pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
         bx.lifetime_start(self.llval, self.layout.size);
     }
index 29b2db5d4d7af2696726f7865dd62c3885b8443c..f0c232a97bc946bd395957a3ecea12640b054b6d 100644 (file)
@@ -137,9 +137,15 @@ fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::V
     fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
     fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value;
 
-    fn load(&mut self, ptr: Self::Value, align: Align) -> Self::Value;
-    fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value;
-    fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value;
+    fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
+    fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
+    fn atomic_load(
+        &mut self,
+        ty: Self::Type,
+        ptr: Self::Value,
+        order: AtomicOrdering,
+        size: Size,
+    ) -> Self::Value;
     fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>)
     -> OperandRef<'tcx, Self::Value>;
 
index 7cb58f9d0cb74c0906db6b007596530dd1d6a01c..7fecfeaa57c283000e81c42e4f6dacb7200d824a 100644 (file)
@@ -10,7 +10,7 @@ Erroneous code example:
 fn _stable_fn() {}
 
 #[rustc_const_stable(feature = "_stable_const_fn")] // invalid
-fn _stable_const_fn() {}
+const fn _stable_const_fn() {}
 
 #[stable(feature = "_deprecated_fn", since = "0.1.0")]
 #[rustc_deprecated(
@@ -29,7 +29,7 @@ To fix this issue, you need to provide the `since` field. Example:
 fn _stable_fn() {}
 
 #[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] // ok!
-fn _stable_const_fn() {}
+const fn _stable_const_fn() {}
 
 #[stable(feature = "_deprecated_fn", since = "0.1.0")]
 #[rustc_deprecated(
index 9fb935a3ab1abbb254c7b05631ec7c75cec17a52..7aba084f4d3aa82b50e8c3958ec891c5b7d4ef84 100644 (file)
@@ -10,7 +10,7 @@ Erroneous code example:
 fn _unstable_fn() {}
 
 #[rustc_const_unstable(feature = "_unstable_const_fn", issue = "0")] // invalid
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
 ```
 
 To fix this issue, you need to provide a correct value in the `issue` field.
@@ -24,7 +24,7 @@ Example:
 fn _unstable_fn() {}
 
 #[rustc_const_unstable(feature = "_unstable_const_fn", issue = "1")] // ok!
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
 ```
 
 See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
index 1aa4b354248842e5dbf408fb6cefb563d97f27c2..4950325df640007c23ef4e6b2490f74a49623b9a 100644 (file)
@@ -10,7 +10,7 @@ Erroneous code example:
 fn _unstable_fn() {}
 
 #[rustc_const_unstable(feature = "_unstable_const_fn")] // invalid
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
 ```
 
 To fix this issue, you need to provide the `issue` field. Example:
@@ -26,7 +26,7 @@ fn _unstable_fn() {}
     feature = "_unstable_const_fn",
     issue = "none"
 )] // ok!
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
 ```
 
 See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
index 577baec21f064f232d96a83914619cdac7ce4004..2253007ce30276928bd9a74db9ee4a6621436dd6 100644 (file)
@@ -145,8 +145,9 @@ fn emit_messages_default(
                 title: Some(Annotation {
                     label: Some(&message),
                     id: code.as_ref().map(|c| match c {
-                        DiagnosticId::Error(val)
-                        | DiagnosticId::Lint { name: val, has_future_breakage: _ } => val.as_str(),
+                        DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => {
+                            val.as_str()
+                        }
                     }),
                     annotation_type: annotation_type_for_level(*level),
                 }),
index 14ccced2c6a56678fd4e6f4ac2d5d34555a57c52..45661ac15623f8bc61f6e632887a73c098c123d7 100644 (file)
@@ -29,7 +29,7 @@ pub struct Diagnostic {
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DiagnosticId {
     Error(String),
-    Lint { name: String, has_future_breakage: bool },
+    Lint { name: String, has_future_breakage: bool, is_force_warn: bool },
 }
 
 /// A "sub"-diagnostic attached to a parent diagnostic.
@@ -109,6 +109,13 @@ pub fn has_future_breakage(&self) -> bool {
         }
     }
 
+    pub fn is_force_warn(&self) -> bool {
+        match self.code {
+            Some(DiagnosticId::Lint { is_force_warn, .. }) => is_force_warn,
+            _ => false,
+        }
+    }
+
     /// Cancel the diagnostic (a structured diagnostic must either be emitted or
     /// canceled or it will panic when dropped).
     pub fn cancel(&mut self) {
index d3f92bf3047b06a5db22f290b400c1753103e59b..fd024a8ecfa4a8ee09cbc85e3a14021df86045f5 100644 (file)
@@ -309,9 +309,7 @@ fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
                     // are some which do actually involve macros.
                     ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
 
-                    ExpnKind::Macro { kind: macro_kind, name, proc_macro: _ } => {
-                        Some((macro_kind, name))
-                    }
+                    ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)),
                 }
             });
 
@@ -372,19 +370,10 @@ fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrac
                     new_labels
                         .push((trace.call_site, "in the inlined copy of this code".to_string()));
                 } else if always_backtrace {
-                    let proc_macro = if let ExpnKind::Macro { kind: _, name: _, proc_macro: true } =
-                        trace.kind
-                    {
-                        "procedural macro "
-                    } else {
-                        ""
-                    };
-
                     new_labels.push((
                         trace.def_site,
                         format!(
-                            "in this expansion of {}`{}`{}",
-                            proc_macro,
+                            "in this expansion of `{}`{}",
                             trace.kind.descr(),
                             if macro_backtrace.len() > 1 {
                                 // if macro_backtrace.len() == 1 it'll be
@@ -410,11 +399,7 @@ fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrac
                 // and it needs an "in this macro invocation" label to match that.
                 let redundant_span = trace.call_site.contains(sp);
 
-                if !redundant_span
-                    && matches!(
-                        trace.kind,
-                        ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ }
-                    )
+                if !redundant_span && matches!(trace.kind, ExpnKind::Macro(MacroKind::Bang, _))
                     || always_backtrace
                 {
                     new_labels.push((
index 72395bd31eca556aed999d8f7057489b6a546dca..485e7564587ea62925f834e6626cf5a8c476ecab 100644 (file)
@@ -559,7 +559,7 @@ fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<Diagnosti
         s.map(|s| {
             let s = match s {
                 DiagnosticId::Error(s) => s,
-                DiagnosticId::Lint { name, has_future_breakage: _ } => name,
+                DiagnosticId::Lint { name, .. } => name,
             };
             let je_result =
                 je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
index e69e868c8ede5fa413a3588540e81f13ee47a94e..d055937ac36e37f9b21aa3194f9073dab7d71237 100644 (file)
@@ -39,16 +39,11 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-fn with_default_session_globals(f: impl FnOnce()) {
-    let session_globals = rustc_span::SessionGlobals::new(rustc_span::edition::DEFAULT_EDITION);
-    rustc_span::SESSION_GLOBALS.set(&session_globals, f);
-}
-
 /// Test the span yields correct positions in JSON.
 fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
     let expected_output = TestData { spans: vec![expected_output] };
 
-    with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
 
index ca2386dfae202e911f2cbeef6cbbff4e4e8d9f77..f8339d6e3f4935d07d0b74ab23a0e1821e4d933f 100644 (file)
@@ -520,12 +520,28 @@ pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> {
     }
 
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
+    ///
+    /// The builder will be canceled if warnings cannot be emitted.
     pub fn struct_span_warn(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> {
         let mut result = self.struct_warn(msg);
         result.set_span(span);
         result
     }
 
+    /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
+    ///
+    /// This will "force" the warning meaning it will not be canceled even
+    /// if warnings cannot be emitted.
+    pub fn struct_span_force_warn(
+        &self,
+        span: impl Into<MultiSpan>,
+        msg: &str,
+    ) -> DiagnosticBuilder<'_> {
+        let mut result = self.struct_force_warn(msg);
+        result.set_span(span);
+        result
+    }
+
     /// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
     pub fn struct_span_allow(
         &self,
@@ -551,6 +567,8 @@ pub fn struct_span_warn_with_code(
     }
 
     /// Construct a builder at the `Warning` level with the `msg`.
+    ///
+    /// The builder will be canceled if warnings cannot be emitted.
     pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
         if !self.flags.can_emit_warnings {
@@ -559,6 +577,14 @@ pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
         result
     }
 
+    /// Construct a builder at the `Warning` level with the `msg`.
+    ///
+    /// This will "force" a warning meaning it will not be canceled even
+    /// if warnings cannot be emitted.
+    pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        DiagnosticBuilder::new(self, Level::Warning, msg)
+    }
+
     /// Construct a builder at the `Allow` level with the `msg`.
     pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> {
         DiagnosticBuilder::new(self, Level::Allow, msg)
@@ -801,7 +827,10 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             self.future_breakage_diagnostics.push(diagnostic.clone());
         }
 
-        if diagnostic.level == Warning && !self.flags.can_emit_warnings {
+        if diagnostic.level == Warning
+            && !self.flags.can_emit_warnings
+            && !diagnostic.is_force_warn()
+        {
             if diagnostic.has_future_breakage() {
                 (*TRACK_DIAGNOSTICS)(diagnostic);
             }
@@ -873,7 +902,7 @@ fn print_error_count(&mut self, registry: &Registry) {
 
         match (errors.len(), warnings.len()) {
             (0, 0) => return,
-            (0, _) => self.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)),
+            (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)),
             (_, 0) => {
                 let _ = self.fatal(&errors);
             }
index 96fd6cb68e8b93419cc6d9a40b9d02327fc9cba3..b3e52502b0739245b962c190a53de2db75ddc199 100644 (file)
@@ -809,17 +809,10 @@ pub fn expn_data(
         call_site: Span,
         descr: Symbol,
         macro_def_id: Option<DefId>,
+        parent_module: Option<DefId>,
     ) -> ExpnData {
-        use SyntaxExtensionKind::*;
-        let proc_macro = match self.kind {
-            // User-defined proc macro
-            Bang(..) | Attr(..) | Derive(..) => true,
-            // Consider everthing else to be not a proc
-            // macro for diagnostic purposes
-            LegacyBang(..) | LegacyAttr(..) | NonMacroAttr { .. } | LegacyDerive(..) => false,
-        };
         ExpnData::new(
-            ExpnKind::Macro { kind: self.macro_kind(), name: descr, proc_macro },
+            ExpnKind::Macro(self.macro_kind(), descr),
             parent,
             call_site,
             self.span,
@@ -828,6 +821,7 @@ pub fn expn_data(
             self.local_inner_macros,
             self.edition,
             macro_def_id,
+            parent_module,
         )
     }
 }
index a255b4f83acbe10aa3b770f3a4c15d78e12587a8..8b68c94e61a384c19603352176b09e396236e31e 100644 (file)
@@ -18,7 +18,9 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::Features;
-use rustc_lint_defs::builtin::{OR_PATTERNS_BACK_COMPAT, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS};
+use rustc_lint_defs::builtin::{
+    RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
+};
 use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::parser::Parser;
 use rustc_session::parse::ParseSess;
@@ -975,7 +977,7 @@ fn check_matcher_core(
                             Some(NonterminalKind::PatParam { inferred: false }),
                         ));
                         sess.buffer_lint_with_diagnostic(
-                            &OR_PATTERNS_BACK_COMPAT,
+                            &RUST_2021_INCOMPATIBLE_OR_PATTERNS,
                             span,
                             ast::CRATE_NODE_ID,
                             "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",
index 7e7155ad27876bff0571d97c42305eb518be8ade..0068539fb3bd4b075c2176305abe776351b871a2 100644 (file)
@@ -3,8 +3,8 @@
 use rustc_ast as ast;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast_pretty::pprust;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::symbol::Ident;
-use rustc_span::with_default_session_globals;
 
 // This version doesn't care about getting comments or doc-strings in.
 fn print_crate_items(krate: &ast::Crate) -> String {
@@ -38,7 +38,7 @@ macro_rules! assert_pred {
 // Make sure idents get transformed everywhere.
 #[test]
 fn ident_transformation() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mut zz_visitor = ToZzIdentMutVisitor;
         let mut krate =
             string_to_crate("#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
@@ -55,7 +55,7 @@ fn ident_transformation() {
 // Make sure idents get transformed even inside macro defs.
 #[test]
 fn ident_transformation_in_defs() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mut zz_visitor = ToZzIdentMutVisitor;
         let mut krate = string_to_crate(
             "macro_rules! a {(b $c:expr $(d $e:token)f+ => \
index 288efe22982fa13cbfba4e7569549357a249f9c7..6402a81e7c1a5dba758fff4da279b140b9015ab8 100644 (file)
@@ -10,9 +10,9 @@
 use rustc_parse::new_parser_from_source_str;
 use rustc_parse::parser::ForceCollect;
 use rustc_session::parse::ParseSess;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::with_default_session_globals;
 use rustc_span::{BytePos, FileName, Pos, Span};
 
 use std::path::PathBuf;
@@ -51,7 +51,7 @@ fn string_to_item(source_str: String) -> Option<P<ast::Item>> {
 #[should_panic]
 #[test]
 fn bad_path_expr_1() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         string_to_expr("::abc::def::return".to_string());
     })
 }
@@ -59,7 +59,7 @@ fn bad_path_expr_1() {
 // Checks the token-tree-ization of macros.
 #[test]
 fn string_to_tts_macro() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let tts: Vec<_> =
             string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect();
         let tts: &[TokenTree] = &tts[..];
@@ -96,7 +96,7 @@ fn string_to_tts_macro() {
 
 #[test]
 fn string_to_tts_1() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let tts = string_to_stream("fn a (b : i32) { b; }".to_string());
 
         let expected = TokenStream::new(vec![
@@ -131,7 +131,7 @@ fn string_to_tts_1() {
 
 #[test]
 fn parse_use() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let use_s = "use foo::bar::baz;";
         let vitem = string_to_item(use_s.to_string()).unwrap();
         let vitem_s = item_to_string(&vitem);
@@ -146,7 +146,7 @@ fn parse_use() {
 
 #[test]
 fn parse_extern_crate() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let ex_s = "extern crate foo;";
         let vitem = string_to_item(ex_s.to_string()).unwrap();
         let vitem_s = item_to_string(&vitem);
@@ -184,7 +184,7 @@ fn visit_pat(&mut self, p: &'a ast::Pat) {
 
 #[test]
 fn span_of_self_arg_pat_idents_are_correct() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let srcs = [
             "impl z { fn a (&self, &myarg: i32) {} }",
             "impl z { fn a (&mut self, &myarg: i32) {} }",
@@ -208,7 +208,7 @@ fn span_of_self_arg_pat_idents_are_correct() {
 
 #[test]
 fn parse_exprs() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         // just make sure that they parse....
         string_to_expr("3 + 4".to_string());
         string_to_expr("a::z.froob(b,&(987+3))".to_string());
@@ -217,7 +217,7 @@ fn parse_exprs() {
 
 #[test]
 fn attrs_fix_bug() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         string_to_item(
             "pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
                 -> Result<Box<Writer>, String> {
@@ -238,7 +238,7 @@ fn wb() -> c_int { O_WRONLY as c_int }
 
 #[test]
 fn crlf_doc_comments() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let sess = sess();
 
         let name_1 = FileName::Custom("crlf_source_1".to_string());
@@ -272,7 +272,7 @@ fn parse_expr_from_source_str(
         new_parser_from_source_str(sess, name, source).parse_expr()
     }
 
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let sess = sess();
         let expr = parse_expr_from_source_str(
             PathBuf::from("foo").into(),
@@ -300,7 +300,7 @@ fn parse_expr_from_source_str(
 // See `recurse_into_file_modules` in the parser.
 #[test]
 fn out_of_line_mod() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let item = parse_item_from_source_str(
             PathBuf::from("foo").into(),
             "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
index 494b3fb61ee970d38f1535c83dcd185f202beea1..3f84979ac05e762bbc26b4bd404c52b2352356a2 100644 (file)
@@ -9,14 +9,12 @@
 use rustc_errors::ErrorReported;
 use rustc_parse::nt_to_tokenstream;
 use rustc_parse::parser::ForceCollect;
-use rustc_span::def_id::CrateNum;
 use rustc_span::{Span, DUMMY_SP};
 
 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
 
 pub struct BangProcMacro {
     pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
-    pub krate: CrateNum,
 }
 
 impl base::ProcMacro for BangProcMacro {
@@ -26,7 +24,7 @@ fn expand<'cx>(
         span: Span,
         input: TokenStream,
     ) -> Result<TokenStream, ErrorReported> {
-        let server = proc_macro_server::Rustc::new(ecx, self.krate);
+        let server = proc_macro_server::Rustc::new(ecx);
         self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| {
             let mut err = ecx.struct_span_err(span, "proc macro panicked");
             if let Some(s) = e.as_str() {
@@ -40,7 +38,6 @@ fn expand<'cx>(
 
 pub struct AttrProcMacro {
     pub client: pm::bridge::client::Client<fn(pm::TokenStream, pm::TokenStream) -> pm::TokenStream>,
-    pub krate: CrateNum,
 }
 
 impl base::AttrProcMacro for AttrProcMacro {
@@ -51,7 +48,7 @@ fn expand<'cx>(
         annotation: TokenStream,
         annotated: TokenStream,
     ) -> Result<TokenStream, ErrorReported> {
-        let server = proc_macro_server::Rustc::new(ecx, self.krate);
+        let server = proc_macro_server::Rustc::new(ecx);
         self.client
             .run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace)
             .map_err(|e| {
@@ -67,7 +64,6 @@ fn expand<'cx>(
 
 pub struct ProcMacroDerive {
     pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
-    pub krate: CrateNum,
 }
 
 impl MultiItemModifier for ProcMacroDerive {
@@ -101,7 +97,7 @@ fn expand(
             nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
         };
 
-        let server = proc_macro_server::Rustc::new(ecx, self.krate);
+        let server = proc_macro_server::Rustc::new(ecx);
         let stream =
             match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) {
                 Ok(stream) => stream,
index 1d73002710d381b3b74a3c477cffabf3e1619610..ff135f60a822a70ab52cf5f924650793e922fc4f 100644 (file)
@@ -14,7 +14,6 @@
 use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
 use rustc_session::parse::ParseSess;
 use rustc_span::def_id::CrateNum;
-use rustc_span::hygiene::ExpnId;
 use rustc_span::hygiene::ExpnKind;
 use rustc_span::symbol::{self, kw, sym, Symbol};
 use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span};
@@ -363,26 +362,20 @@ pub(crate) struct Rustc<'a> {
     mixed_site: Span,
     span_debug: bool,
     krate: CrateNum,
-    expn_id: ExpnId,
     rebased_spans: FxHashMap<usize, Span>,
 }
 
 impl<'a> Rustc<'a> {
-    pub fn new(cx: &'a ExtCtxt<'_>, krate: CrateNum) -> Self {
+    pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
         let expn_data = cx.current_expansion.id.expn_data();
-        let def_site = cx.with_def_site_ctxt(expn_data.def_site);
-        let call_site = cx.with_call_site_ctxt(expn_data.call_site);
-        let mixed_site = cx.with_mixed_site_ctxt(expn_data.call_site);
-        let sess = cx.parse_sess();
         Rustc {
             resolver: cx.resolver,
-            sess,
-            def_site,
-            call_site,
-            mixed_site,
+            sess: cx.parse_sess(),
+            def_site: cx.with_def_site_ctxt(expn_data.def_site),
+            call_site: cx.with_call_site_ctxt(expn_data.call_site),
+            mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site),
             span_debug: cx.ecfg.span_debug,
-            krate,
-            expn_id: cx.current_expansion.id,
+            krate: expn_data.macro_def_id.unwrap().krate,
             rebased_spans: FxHashMap::default(),
         }
     }
@@ -782,25 +775,15 @@ fn source_text(&mut self, span: Self::Span) -> Option<String> {
     /// span from the metadata of `my_proc_macro` (which we have access to,
     /// since we've loaded `my_proc_macro` from disk in order to execute it).
     /// In this way, we have obtained a span pointing into `my_proc_macro`
-    fn save_span(&mut self, mut span: Self::Span) -> usize {
-        // Throw away the `SyntaxContext`, since we currently
-        // skip serializing `SyntaxContext`s for proc-macro crates
-        span = span.with_ctxt(rustc_span::SyntaxContext::root());
+    fn save_span(&mut self, span: Self::Span) -> usize {
         self.sess.save_proc_macro_span(span)
     }
     fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
-        let resolver = self.resolver;
-        let krate = self.krate;
-        let expn_id = self.expn_id;
+        let (resolver, krate, def_site) = (self.resolver, self.krate, self.def_site);
         *self.rebased_spans.entry(id).or_insert_with(|| {
-            let raw_span = resolver.get_proc_macro_quoted_span(krate, id);
-            // Ignore the deserialized `SyntaxContext` entirely.
-            // FIXME: Preserve the macro backtrace from the serialized span
-            // For example, if a proc-macro crate has code like
-            // `macro_one!() -> macro_two!() -> quote!()`, we might
-            // want to 'concatenate' this backtrace with the backtrace from
-            // our current call site.
-            raw_span.with_def_site_ctxt(expn_id)
+            // FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding,
+            // replace it with a def-site context until we are encoding it properly.
+            resolver.get_proc_macro_quoted_span(krate, id).with_ctxt(def_site.ctxt())
         })
     }
 }
@@ -812,7 +795,7 @@ fn ident_name_compatibility_hack(
     rustc: &mut Rustc<'_>,
 ) -> Option<(rustc_span::symbol::Ident, bool)> {
     if let NtIdent(ident, is_raw) = nt {
-        if let ExpnKind::Macro { name: macro_name, .. } = orig_span.ctxt().outer_expn_data().kind {
+        if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
             let source_map = rustc.sess.source_map();
             let filename = source_map.span_to_filename(orig_span);
             if let FileName::Real(RealFileName::LocalPath(path)) = filename {
index f2345ff2707e953d081b4aaee3064ddea877071a..ed3aa1eaca84e18fe955553975ee8cef9896d465 100644 (file)
@@ -2,8 +2,8 @@
 use rustc_ast::tokenstream::TokenStream;
 use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
 use rustc_session::parse::ParseSess;
+use rustc_span::create_default_session_if_not_set_then;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::with_default_session_globals;
 use rustc_span::{BytePos, MultiSpan, Span};
 
 use rustc_data_structures::sync::Lrc;
@@ -124,7 +124,7 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
-    with_default_session_globals(|| {
+    create_default_session_if_not_set_then(|_| {
         let output = Arc::new(Mutex::new(Vec::new()));
 
         let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
index 8b546e7e4a343a1bb39fe177457bd85459ca8fd6..31052bfb54ce8584e445689ddd90d64268a138b4 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_ast::token;
 use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree};
-use rustc_span::with_default_session_globals;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::{BytePos, Span, Symbol};
 use smallvec::smallvec;
 
@@ -20,7 +20,7 @@ fn joint(tree: TokenTree) -> TokenStream {
 
 #[test]
 fn test_concat() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_res = string_to_ts("foo::bar::baz");
         let test_fst = string_to_ts("foo::bar");
         let test_snd = string_to_ts("::baz");
@@ -33,7 +33,7 @@ fn test_concat() {
 
 #[test]
 fn test_to_from_bijection() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_start = string_to_ts("foo::bar(baz)");
         let test_end = test_start.trees().collect();
         assert_eq!(test_start, test_end)
@@ -42,7 +42,7 @@ fn test_to_from_bijection() {
 
 #[test]
 fn test_eq_0() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_res = string_to_ts("foo");
         let test_eqs = string_to_ts("foo");
         assert_eq!(test_res, test_eqs)
@@ -51,7 +51,7 @@ fn test_eq_0() {
 
 #[test]
 fn test_eq_1() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_res = string_to_ts("::bar::baz");
         let test_eqs = string_to_ts("::bar::baz");
         assert_eq!(test_res, test_eqs)
@@ -60,7 +60,7 @@ fn test_eq_1() {
 
 #[test]
 fn test_eq_3() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_res = string_to_ts("");
         let test_eqs = string_to_ts("");
         assert_eq!(test_res, test_eqs)
@@ -69,7 +69,7 @@ fn test_eq_3() {
 
 #[test]
 fn test_diseq_0() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_res = string_to_ts("::bar::baz");
         let test_eqs = string_to_ts("bar::baz");
         assert_eq!(test_res == test_eqs, false)
@@ -78,7 +78,7 @@ fn test_diseq_0() {
 
 #[test]
 fn test_diseq_1() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test_res = string_to_ts("(bar,baz)");
         let test_eqs = string_to_ts("bar,baz");
         assert_eq!(test_res == test_eqs, false)
@@ -87,7 +87,7 @@ fn test_diseq_1() {
 
 #[test]
 fn test_is_empty() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let test0: TokenStream = Vec::<TokenTree>::new().into_iter().collect();
         let test1: TokenStream =
             TokenTree::token(token::Ident(Symbol::intern("a"), false), sp(0, 1)).into();
@@ -101,7 +101,7 @@ fn test_is_empty() {
 
 #[test]
 fn test_dotdotdot() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mut builder = TokenStreamBuilder::new();
         builder.push(joint(TokenTree::token(token::Dot, sp(0, 1))));
         builder.push(joint(TokenTree::token(token::Dot, sp(1, 2))));
index f045a75cdc890a8c98184819597e878742f00e37..9eaf4693811ca100844fe5fd4fc51d614463a468 100644 (file)
@@ -416,9 +416,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows accessing fields of unions inside `const` functions.
     (active, const_fn_union, "1.27.0", Some(51909), None),
 
-    /// Allows casting raw pointers to `usize` during const eval.
-    (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
-
     /// Allows dereferencing raw pointers during const eval.
     (active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
 
@@ -685,7 +682,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (incomplete, unnamed_fields, "1.53.0", Some(49804), None),
 
     /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
-    (active, more_qualified_paths, "1.54.0", Some(80080), None),
+    (active, more_qualified_paths, "1.54.0", Some(86935), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
index 71c10eb650754699eb8d98456c7fe0a4dd2e46ca..6d3e2b9c5171366219cb1d904d1288e86349285e 100644 (file)
@@ -144,6 +144,10 @@ macro_rules! declare_features {
     (removed, external_doc, "1.54.0", Some(44732), None,
      Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
 
+     /// Allows casting raw pointers to `usize` during const eval.
+    (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None,
+     Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),
+
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
index 753b8c85670ba5dd1e01f9f7ba6c5a57752149e9..30a367052cba58411702cd20b1e0f50cbd478b9f 100644 (file)
@@ -5,16 +5,13 @@
 //! expressions) that are mostly just leftovers.
 
 pub use crate::def_id::DefPathHash;
-use crate::def_id::{
-    CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE,
-};
+use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use crate::hir;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::vec::IndexVec;
-use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -26,7 +23,7 @@
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
 /// stores the `DefIndex` of its parent.
 /// There is one `DefPathTable` for each crate.
-#[derive(Clone, Default)]
+#[derive(Clone, Default, Debug)]
 pub struct DefPathTable {
     index_to_key: IndexVec<DefIndex, DefKey>,
     def_path_hashes: IndexVec<DefIndex, DefPathHash>,
@@ -99,7 +96,7 @@ pub fn enumerated_keys_and_path_hashes(
 /// The definition table containing node definitions.
 /// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
 /// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct Definitions {
     table: DefPathTable,
 
@@ -108,9 +105,6 @@ pub struct Definitions {
     /// The reverse mapping of `def_id_to_hir_id`.
     pub(super) hir_id_to_def_id: FxHashMap<hir::HirId, LocalDefId>,
 
-    /// If `ExpnId` is an ID of some macro expansion,
-    /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
-    parent_modules_of_macro_defs: FxHashMap<ExpnId, DefId>,
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
 }
@@ -330,7 +324,7 @@ pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefI
     }
 
     /// Adds a root definition (no parent) and a few other reserved definitions.
-    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions {
+    pub fn new(stable_crate_id: StableCrateId) -> Definitions {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -339,7 +333,6 @@ pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definit
             },
         };
 
-        let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
         let parent_hash = DefPathHash::new(stable_crate_id, 0);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
@@ -353,7 +346,6 @@ pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definit
             def_id_to_hir_id: Default::default(),
             hir_id_to_def_id: Default::default(),
             expansions_that_defined: Default::default(),
-            parent_modules_of_macro_defs: Default::default(),
         }
     }
 
@@ -420,14 +412,6 @@ pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId {
         self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root)
     }
 
-    pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId {
-        self.parent_modules_of_macro_defs[&expn_id]
-    }
-
-    pub fn add_parent_module_of_macro_def(&mut self, expn_id: ExpnId, module: DefId) {
-        self.parent_modules_of_macro_defs.insert(expn_id, module);
-    }
-
     pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
         self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
     }
index bab685006eafc2e2e3ef5c75610ec247dd912f5f..28ae08030e63029f34adcc4eccd8153564c7145c 100644 (file)
@@ -348,7 +348,4 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     Range,                   sym::Range,               range_struct,               Target::Struct;
     RangeToInclusive,        sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct;
     RangeTo,                 sym::RangeTo,             range_to_struct,            Target::Struct;
-    Send,                    sym::send,                send_trait,                 Target::Trait;
-    UnwindSafe,              sym::unwind_safe,         unwind_safe_trait,          Target::Trait;
-    RefUnwindSafe,           sym::ref_unwind_safe,     ref_unwind_safe_trait,      Target::Trait;
 }
index 2aafc6afa236d8fd5d2b6c7e0361768d1aace5e5..4636d515249d9809ed55b2fe182ef3a2c63e7ab8 100644 (file)
@@ -1,6 +1,4 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 
 #[test]
@@ -13,17 +11,16 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    let d0 = CrateDisambiguator::from(Fingerprint::new(12, 34));
-    let d1 = CrateDisambiguator::from(Fingerprint::new(56, 78));
+    let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
+    let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
 
-    let h0 = mk_test_hash("foo", d0);
-    let h1 = mk_test_hash("foo", d1);
+    let h0 = mk_test_hash(id0);
+    let h1 = mk_test_hash(id1);
 
     assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
     assert_ne!(h0.local_hash(), h1.local_hash());
 
-    fn mk_test_hash(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> DefPathHash {
-        let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
+    fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
         let parent_hash = DefPathHash::new(stable_crate_id, 0);
 
         let key = DefKey {
index 83e80b55daec1b3e2d9eac3bcdc9f7067550ac62..2ed0539841aa30b42f896132fbf02779b70354c6 100644 (file)
 use rustc_data_structures::{base_n, flock};
 use rustc_errors::ErrorReported;
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::{Session, StableCrateId};
 
 use std::fs as std_fs;
 use std::io;
@@ -189,7 +189,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 pub fn prepare_session_directory(
     sess: &Session,
     crate_name: &str,
-    crate_disambiguator: CrateDisambiguator,
+    stable_crate_id: StableCrateId,
 ) -> Result<(), ErrorReported> {
     if sess.opts.incremental.is_none() {
         return Ok(());
@@ -200,7 +200,7 @@ pub fn prepare_session_directory(
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
-    let crate_dir = crate_path(sess, crate_name, crate_disambiguator);
+    let crate_dir = crate_path(sess, crate_name, stable_crate_id);
     debug!("crate-dir: {}", crate_dir.display());
     create_dir(sess, &crate_dir, "crate")?;
 
@@ -648,19 +648,12 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path(
-    sess: &Session,
-    crate_name: &str,
-    crate_disambiguator: CrateDisambiguator,
-) -> PathBuf {
+fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
     let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
 
-    // The full crate disambiguator is really long. 64 bits of it should be
-    // sufficient.
-    let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
-    let crate_disambiguator = base_n::encode(crate_disambiguator as u128, INT_ENCODE_BASE);
+    let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
 
-    let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
+    let crate_name = format!("{}-{}", crate_name, stable_crate_id);
     incr_dir.join(crate_name)
 }
 
index a1090ee316db48881a508485b2d1f31dd052f7ba..086c49c73972f6efff13f0c1cbe31950493297b0 100644 (file)
@@ -76,7 +76,7 @@ pub fn build_output_filenames(
 
 /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
 pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
-    rustc_span::with_default_session_globals(move || {
+    rustc_span::create_default_session_if_not_set_then(move |_| {
         let cfg = cfgspecs
             .into_iter()
             .map(|s| {
index c0f7ea8df49e465813b18446417fac926ef3b475..e568b5ca50110aca5cdac528cf658c466b117806 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_errors::{ErrorReported, PResult};
 use rustc_expand::base::ExtCtxt;
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
 use rustc_hir::Crate;
 use rustc_lint::LintStore;
 use rustc_metadata::creader::CStore;
@@ -195,9 +195,13 @@ pub fn register_plugins<'a>(
     let crate_types = util::collect_crate_types(sess, &krate.attrs);
     sess.init_crate_types(crate_types);
 
-    let disambiguator = util::compute_crate_disambiguator(sess);
-    sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
-    rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?;
+    let stable_crate_id = StableCrateId::new(
+        crate_name,
+        sess.crate_types().contains(&CrateType::Executable),
+        sess.opts.cg.metadata.clone(),
+    );
+    sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
+    rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?;
 
     if sess.opts.incremental.is_some() {
         sess.time("incr_comp_garbage_collect_session_directories", || {
@@ -211,10 +215,6 @@ pub fn register_plugins<'a>(
         });
     }
 
-    sess.time("recursion_limit", || {
-        middle::limits::update_limits(sess, &krate);
-    });
-
     let mut lint_store = rustc_lint::new_lint_store(
         sess.opts.debugging_opts.no_interleave_lints,
         sess.unstable_options(),
@@ -311,9 +311,11 @@ pub fn configure_and_expand(
 
         // Create the config for macro expansion
         let features = sess.features_untracked();
+        let recursion_limit =
+            rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess);
         let cfg = rustc_expand::expand::ExpansionConfig {
             features: Some(&features),
-            recursion_limit: sess.recursion_limit(),
+            recursion_limit,
             trace_mac: sess.opts.debugging_opts.trace_macros,
             should_test: sess.opts.test,
             span_debug: sess.opts.debugging_opts.span_debug,
@@ -872,6 +874,13 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                     tcx.ensure().check_mod_unstable_api_usage(module);
                     tcx.ensure().check_mod_const_bodies(module);
                 });
+            },
+            {
+                // We force these querie to run,
+                // since they might not otherwise get called.
+                // This marks the corresponding crate-level attributes
+                // as used, and ensures that their values are valid.
+                tcx.ensure().limits(());
             }
         );
     });
index b252409a92ada8373339f387d34579063de6a218..a053253ec16e00625cd8c3d04c28a8f9772355d6 100644 (file)
@@ -107,7 +107,7 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) {
 // When the user supplies --test we should implicitly supply --cfg test
 #[test]
 fn test_switch_implies_cfg_test() {
-    rustc_span::with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let matches = optgroups().parse(&["--test".to_string()]).unwrap();
         let (sess, cfg) = mk_session(matches);
         let cfg = build_configuration(&sess, to_crate_config(cfg));
@@ -118,7 +118,7 @@ fn test_switch_implies_cfg_test() {
 // When the user supplies --test and --cfg test, don't implicitly add another --cfg test
 #[test]
 fn test_switch_implies_cfg_test_unless_cfg_test() {
-    rustc_span::with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
         let (sess, cfg) = mk_session(matches);
         let cfg = build_configuration(&sess, to_crate_config(cfg));
@@ -130,20 +130,20 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
 
 #[test]
 fn test_can_print_warnings() {
-    rustc_span::with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
         let (sess, _) = mk_session(matches);
         assert!(!sess.diagnostic().can_emit_warnings());
     });
 
-    rustc_span::with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let matches =
             optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap();
         let (sess, _) = mk_session(matches);
         assert!(sess.diagnostic().can_emit_warnings());
     });
 
-    rustc_span::with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
         let (sess, _) = mk_session(matches);
         assert!(sess.diagnostic().can_emit_warnings());
index 6485fbebd665fd028ccc35274b6fd65ef89d9648..4f51ce620427b4ecad71acdf53da52719b5e8787 100644 (file)
@@ -2,11 +2,9 @@
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode};
 use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[cfg(parallel_compiler)]
 use rustc_data_structures::jobserver;
-use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
@@ -18,7 +16,6 @@
 use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
 use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::CrateConfig;
-use rustc_session::CrateDisambiguator;
 use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -153,7 +150,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
     crate::callbacks::setup_callbacks();
 
     let main_handler = move || {
-        rustc_span::with_session_globals(edition, || {
+        rustc_span::create_session_globals_then(edition, || {
             io::set_output_capture(stderr.clone());
             f()
         })
@@ -174,12 +171,13 @@ unsafe fn handle_deadlock() {
     rustc_data_structures::sync::assert_sync::<tls::ImplicitCtxt<'_, '_>>();
     let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>);
 
-    let session_globals = rustc_span::SESSION_GLOBALS.with(|sg| sg as *const _);
+    let session_globals = rustc_span::with_session_globals(|sg| sg as *const _);
     let session_globals = &*session_globals;
     thread::spawn(move || {
         tls::enter_context(icx, |_| {
-            rustc_span::SESSION_GLOBALS
-                .set(session_globals, || tls::with(|tcx| tcx.queries.deadlock(tcx, &registry)))
+            rustc_span::set_session_globals_then(session_globals, || {
+                tls::with(|tcx| tcx.queries.deadlock(tcx, &registry))
+            })
         });
     });
 }
@@ -206,13 +204,13 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
 
     let with_pool = move |pool: &rayon::ThreadPool| pool.install(f);
 
-    rustc_span::with_session_globals(edition, || {
-        rustc_span::SESSION_GLOBALS.with(|session_globals| {
+    rustc_span::create_session_globals_then(edition, || {
+        rustc_span::with_session_globals(|session_globals| {
             // The main handler runs for each Rayon worker thread and sets up
             // the thread local rustc uses. `session_globals` is captured and set
             // on the new threads.
             let main_handler = move |thread: rayon::ThreadBuilder| {
-                rustc_span::SESSION_GLOBALS.set(session_globals, || {
+                rustc_span::set_session_globals_then(session_globals, || {
                     io::set_output_capture(stderr.clone());
                     thread.run()
                 })
@@ -487,39 +485,6 @@ pub fn get_codegen_sysroot(
     }
 }
 
-pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
-    use std::hash::Hasher;
-
-    // The crate_disambiguator is a 128 bit hash. The disambiguator is fed
-    // into various other hashes quite a bit (symbol hashes, incr. comp. hashes,
-    // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits
-    // should still be safe enough to avoid collisions in practice.
-    let mut hasher = StableHasher::new();
-
-    let mut metadata = session.opts.cg.metadata.clone();
-    // We don't want the crate_disambiguator to dependent on the order
-    // -C metadata arguments, so sort them:
-    metadata.sort();
-    // Every distinct -C metadata value is only incorporated once:
-    metadata.dedup();
-
-    hasher.write(b"metadata");
-    for s in &metadata {
-        // Also incorporate the length of a metadata string, so that we generate
-        // different values for `-Cmetadata=ab -Cmetadata=c` and
-        // `-Cmetadata=a -Cmetadata=bc`
-        hasher.write_usize(s.len());
-        hasher.write(s.as_bytes());
-    }
-
-    // Also incorporate crate type, so that we don't get symbol conflicts when
-    // linking against a library of the same name, if this is an executable.
-    let is_exe = session.crate_types().contains(&CrateType::Executable);
-    hasher.write(if is_exe { b"exe" } else { b"lib" });
-
-    CrateDisambiguator::from(hasher.finish::<Fingerprint>())
-}
-
 pub(crate) fn check_attr_crate_type(
     sess: &Session,
     attrs: &[ast::Attribute],
index b303f55cf772b8af4a73efb55e3f5e6f0aad4190..92e627bce02934de317fe5cf8ae55416f5aa68d8 100644 (file)
@@ -571,6 +571,12 @@ fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) {
         self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate");
 
         for macro_def in krate.exported_macros {
+            // Non exported macros should be skipped, since `missing_docs` only
+            // applies to externally visible items.
+            if !cx.access_levels.is_exported(macro_def.hir_id()) {
+                continue;
+            }
+
             let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
             let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
             if !has_doc {
index e7322251f5e445562fc86e58dc62f990273ebb87..c44df407f6b3ae5ef3c88bc1bada2f2b6f3921af 100644 (file)
@@ -16,7 +16,7 @@
 
 use self::TargetLint::*;
 
-use crate::levels::LintLevelsBuilder;
+use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
 use crate::passes::{EarlyLintPassObject, LateLintPassObject};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
@@ -129,6 +129,8 @@ pub enum CheckLintNameResult<'a> {
     Ok(&'a [LintId]),
     /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
     NoLint(Option<Symbol>),
+    /// The lint refers to a tool that has not been registered.
+    NoTool,
     /// The lint is either renamed or removed. This is the warning
     /// message, and an optional new name (`None` if removed).
     Warning(String, Option<String>),
@@ -321,9 +323,17 @@ pub fn find_lints(&self, mut lint_name: &str) -> Result<Vec<LintId>, FindLintErr
         }
     }
 
-    /// Checks the validity of lint names derived from the command line
-    pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Level) {
-        let db = match self.check_lint_name(lint_name, None) {
+    /// Checks the validity of lint names derived from the command line.
+    pub fn check_lint_name_cmdline(
+        &self,
+        sess: &Session,
+        lint_name: &str,
+        level: Level,
+        crate_attrs: &[ast::Attribute],
+    ) {
+        let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
+
+        let db = match self.check_lint_name(sess, lint_name_only, tool_name, crate_attrs) {
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
             CheckLintNameResult::NoLint(suggestion) => {
@@ -345,6 +355,13 @@ pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Le
                 ))),
                 _ => None,
             },
+            CheckLintNameResult::NoTool => Some(struct_span_err!(
+                sess,
+                DUMMY_SP,
+                E0602,
+                "unknown lint tool: `{}`",
+                tool_name.unwrap()
+            )),
         };
 
         if let Some(mut db) = db {
@@ -387,9 +404,17 @@ pub fn is_lint_group(&self, lint_name: Symbol) -> bool {
     /// printing duplicate warnings.
     pub fn check_lint_name(
         &self,
+        sess: &Session,
         lint_name: &str,
         tool_name: Option<Symbol>,
+        crate_attrs: &[ast::Attribute],
     ) -> CheckLintNameResult<'_> {
+        if let Some(tool_name) = tool_name {
+            if !is_known_lint_tool(tool_name, sess, crate_attrs) {
+                return CheckLintNameResult::NoTool;
+            }
+        }
+
         let complete_name = if let Some(tool_name) = tool_name {
             format!("{}::{}", tool_name, lint_name)
         } else {
@@ -1005,3 +1030,14 @@ fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
         self.tcx.layout_of(self.param_env.and(ty))
     }
 }
+
+pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
+    match lint_name.split_once("::") {
+        Some((tool_name, lint_name)) => {
+            let tool_name = Symbol::intern(tool_name);
+
+            (Some(tool_name), lint_name)
+        }
+        None => (None, lint_name),
+    }
+}
index 0398d4a99618a9fe1498bea256be428c69956945..9b1a339572ec3cfe5b9fde1709d72415c3aba51a 100644 (file)
@@ -248,21 +248,10 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
                 if last.ident.name == sym::LintPass {
                     let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
                     let call_site = expn_data.call_site;
-                    if !matches!(
-                        expn_data.kind,
-                        ExpnKind::Macro {
-                            kind: MacroKind::Bang,
-                            name: sym::impl_lint_pass,
-                            proc_macro: _
-                        }
-                    ) && !matches!(
-                        call_site.ctxt().outer_expn_data().kind,
-                        ExpnKind::Macro {
-                            kind: MacroKind::Bang,
-                            name: sym::declare_lint_pass,
-                            proc_macro: _
-                        }
-                    ) {
+                    if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass)
+                        && call_site.ctxt().outer_expn_data().kind
+                            != ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
+                    {
                         cx.struct_span_lint(
                             LINT_PASS_IMPL_WITHOUT_MACRO,
                             lint_pass.path.span,
index c0a059b92aa9ff27536a06c0528ab25799c29bca..bc6956f57978311e02de9344d56f3a9bc404533e 100644 (file)
@@ -11,7 +11,8 @@
 use rustc_middle::lint::LevelAndSource;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::lint::{
-    struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet,
+    struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, LintStackIndex,
+    COMMAND_LINE,
 };
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -50,15 +51,15 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
 pub struct LintLevelsBuilder<'s> {
     sess: &'s Session,
     sets: LintLevelSets,
-    id_to_set: FxHashMap<HirId, u32>,
-    cur: u32,
+    id_to_set: FxHashMap<HirId, LintStackIndex>,
+    cur: LintStackIndex,
     warn_about_weird_lints: bool,
     store: &'s LintStore,
     crate_attrs: &'s [ast::Attribute],
 }
 
 pub struct BuilderPush {
-    prev: u32,
+    prev: LintStackIndex,
     pub changed: bool,
 }
 
@@ -72,7 +73,7 @@ pub fn new(
         let mut builder = LintLevelsBuilder {
             sess,
             sets: LintLevelSets::new(),
-            cur: 0,
+            cur: COMMAND_LINE,
             id_to_set: Default::default(),
             warn_about_weird_lints,
             store,
@@ -88,7 +89,7 @@ fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
         self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
 
         for &(ref lint_name, level) in &sess.opts.lint_opts {
-            store.check_lint_name_cmdline(sess, &lint_name, level);
+            store.check_lint_name_cmdline(sess, &lint_name, level, self.crate_attrs);
             let orig_level = level;
 
             // If the cap is less than this specified level, e.g., if we've got
@@ -110,7 +111,7 @@ fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
         }
 
         for lint_name in &sess.opts.force_warns {
-            store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn);
+            store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn, self.crate_attrs);
             let lints = store
                 .find_lints(lint_name)
                 .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
@@ -120,7 +121,7 @@ fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
             }
         }
 
-        self.sets.list.push(LintSet::CommandLine { specs });
+        self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE });
     }
 
     /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
@@ -321,33 +322,14 @@ pub(crate) fn push(
                         continue;
                     }
                 };
-                let tool_name = if meta_item.path.segments.len() > 1 {
-                    let tool_ident = meta_item.path.segments[0].ident;
-                    if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
-                        let mut err = struct_span_err!(
-                            sess,
-                            tool_ident.span,
-                            E0710,
-                            "unknown tool name `{}` found in scoped lint: `{}`",
-                            tool_ident.name,
-                            pprust::path_to_string(&meta_item.path),
-                        );
-                        if sess.is_nightly_build() {
-                            err.help(&format!(
-                                "add `#![register_tool({})]` to the crate root",
-                                tool_ident.name
-                            ));
-                        }
-                        err.emit();
-                        continue;
-                    }
-
-                    Some(meta_item.path.segments.remove(0).ident.name)
+                let tool_ident = if meta_item.path.segments.len() > 1 {
+                    Some(meta_item.path.segments.remove(0).ident)
                 } else {
                     None
                 };
+                let tool_name = tool_ident.map(|ident| ident.name);
                 let name = pprust::path_to_string(&meta_item.path);
-                let lint_result = store.check_lint_name(&name, tool_name);
+                let lint_result = store.check_lint_name(sess, &name, tool_name, self.crate_attrs);
                 match &lint_result {
                     CheckLintNameResult::Ok(ids) => {
                         let src = LintLevelSource::Node(
@@ -364,7 +346,8 @@ pub(crate) fn push(
                     CheckLintNameResult::Tool(result) => {
                         match *result {
                             Ok(ids) => {
-                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+                                let complete_name =
+                                    &format!("{}::{}", tool_ident.unwrap().name, name);
                                 let src = LintLevelSource::Node(
                                     Symbol::intern(complete_name),
                                     sp,
@@ -419,6 +402,26 @@ pub(crate) fn push(
                         }
                     }
 
+                    &CheckLintNameResult::NoTool => {
+                        let mut err = struct_span_err!(
+                            sess,
+                            tool_ident.map_or(DUMMY_SP, |ident| ident.span),
+                            E0710,
+                            "unknown tool name `{}` found in scoped lint: `{}::{}`",
+                            tool_name.unwrap(),
+                            tool_name.unwrap(),
+                            pprust::path_to_string(&meta_item.path),
+                        );
+                        if sess.is_nightly_build() {
+                            err.help(&format!(
+                                "add `#![register_tool({})]` to the crate root",
+                                tool_name.unwrap()
+                            ));
+                        }
+                        err.emit();
+                        continue;
+                    }
+
                     _ if !self.warn_about_weird_lints => {}
 
                     CheckLintNameResult::Warning(msg, renamed) => {
@@ -450,8 +453,8 @@ pub(crate) fn push(
                         let (level, src) =
                             self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
                         struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
-                            let name = if let Some(tool_name) = tool_name {
-                                format!("{}::{}", tool_name, name)
+                            let name = if let Some(tool_ident) = tool_ident {
+                                format!("{}::{}", tool_ident.name, name)
                             } else {
                                 name.to_string()
                             };
@@ -474,7 +477,9 @@ pub(crate) fn push(
                 if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result {
                     // Ignore any errors or warnings that happen because the new name is inaccurate
                     // NOTE: `new_name` already includes the tool name, so we don't have to add it again.
-                    if let CheckLintNameResult::Ok(ids) = store.check_lint_name(&new_name, None) {
+                    if let CheckLintNameResult::Ok(ids) =
+                        store.check_lint_name(sess, &new_name, None, self.crate_attrs)
+                    {
                         let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason);
                         for &id in ids {
                             self.check_gated_lint(id, attr.span);
@@ -523,8 +528,7 @@ pub(crate) fn push(
 
         let prev = self.cur;
         if !specs.is_empty() {
-            self.cur = self.sets.list.len() as u32;
-            self.sets.list.push(LintSet::Node { specs, parent: prev });
+            self.cur = self.sets.list.push(LintSet { specs, parent: prev });
         }
 
         BuilderPush { prev, changed: prev != self.cur }
@@ -578,7 +582,7 @@ pub fn build_map(self) -> LintLevelMap {
     }
 }
 
-fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
+pub fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
     if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) {
         return true;
     }
index 89f9809d643e08487ebbdbaf47c8d0e4376470e9..28b60603a2dbb36a2a25d7d3c728cd08aca15783 100644 (file)
@@ -325,6 +325,9 @@ macro_rules! register_passes {
     store.register_renamed("redundant_semicolon", "redundant_semicolons");
     store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
     store.register_renamed("safe_packed_borrows", "unaligned_references");
+    store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures");
+    store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns");
+    store.register_renamed("non_fmt_panic", "non_fmt_panics");
 
     // These were moved to tool lints, but rustc still sees them when compiling normally, before
     // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use
@@ -494,3 +497,6 @@ fn register_internals(store: &mut LintStore) {
         ],
     );
 }
+
+#[cfg(test)]
+mod tests;
index 3ea5a3bcc3b98a3b721472e2aa4040b9c8b9d68c..a32caf1bc433df1cbf94ffa4f3d7322f2ff43ed5 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol};
 
 declare_lint! {
-    /// The `non_fmt_panic` lint detects `panic!(..)` invocations where the first
+    /// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first
     /// argument is not a formatting string.
     ///
     /// ### Example
@@ -29,7 +29,7 @@
     /// an `i32` as message.
     ///
     /// Rust 2021 always interprets the first argument as format string.
-    NON_FMT_PANIC,
+    NON_FMT_PANICS,
     Warn,
     "detect single-argument panic!() invocations in which the argument is not a format string",
     @future_incompatible = FutureIncompatibleInfo {
@@ -39,7 +39,7 @@
     report_in_external_macro
 }
 
-declare_lint_pass!(NonPanicFmt => [NON_FMT_PANIC]);
+declare_lint_pass!(NonPanicFmt => [NON_FMT_PANICS]);
 
 impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
@@ -91,7 +91,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
         arg_span = expn.call_site;
     }
 
-    cx.struct_span_lint(NON_FMT_PANIC, arg_span, |lint| {
+    cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| {
         let mut l = lint.build("panic message is not a string literal");
         l.note("this usage of panic!() is deprecated; it will be a hard error in Rust 2021");
         l.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>");
@@ -174,7 +174,7 @@ fn check_panic_str<'tcx>(
             [] => vec![fmt_span],
             v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
         };
-        cx.struct_span_lint(NON_FMT_PANIC, arg_spans, |lint| {
+        cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
             let mut l = lint.build(match n_arguments {
                 1 => "panic message contains an unused formatting placeholder",
                 _ => "panic message contains unused formatting placeholders",
@@ -208,7 +208,7 @@ fn check_panic_str<'tcx>(
             Some(v) if v.len() == 1 => "panic message contains a brace",
             _ => "panic message contains braces",
         };
-        cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
+        cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
             let mut l = lint.build(msg);
             l.note("this message is not used as a format string, but will be in Rust 2021");
             if span.contains(arg.span) {
@@ -256,10 +256,6 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span,
     }
 
     let macro_symbol =
-        if let hygiene::ExpnKind::Macro { kind: _, name: symbol, proc_macro: _ } = expn.kind {
-            symbol
-        } else {
-            Symbol::intern("panic")
-        };
+        if let hygiene::ExpnKind::Macro(_, symbol) = expn.kind { symbol } else { sym::panic };
     (expn.call_site, panic_macro, macro_symbol.as_str())
 }
diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs
new file mode 100644 (file)
index 0000000..fc9d6f6
--- /dev/null
@@ -0,0 +1,26 @@
+use crate::context::parse_lint_and_tool_name;
+use rustc_span::{create_default_session_globals_then, Symbol};
+
+#[test]
+fn parse_lint_no_tool() {
+    create_default_session_globals_then(|| {
+        assert_eq!(parse_lint_and_tool_name("foo"), (None, "foo"))
+    });
+}
+
+#[test]
+fn parse_lint_with_tool() {
+    create_default_session_globals_then(|| {
+        assert_eq!(parse_lint_and_tool_name("clippy::foo"), (Some(Symbol::intern("clippy")), "foo"))
+    });
+}
+
+#[test]
+fn parse_lint_multiple_path() {
+    create_default_session_globals_then(|| {
+        assert_eq!(
+            parse_lint_and_tool_name("clippy::foo::bar"),
+            (Some(Symbol::intern("clippy")), "foo::bar")
+        )
+    });
+}
index 9bb1109fc646bfbbfefec39db5b6520d6d96f318..01291de51bdab4024b71099f448b094ccbf0c80e 100644 (file)
         MISSING_ABI,
         INVALID_DOC_ATTRIBUTES,
         SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
-        DISJOINT_CAPTURE_MIGRATION,
+        RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
         LEGACY_DERIVE_HELPERS,
         PROC_MACRO_BACK_COMPAT,
-        OR_PATTERNS_BACK_COMPAT,
+        RUST_2021_INCOMPATIBLE_OR_PATTERNS,
         LARGE_ASSIGNMENTS,
-        FUTURE_PRELUDE_COLLISION,
-        RESERVED_PREFIX,
+        RUST_2021_PRELUDE_COLLISIONS,
+        RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+        UNSUPPORTED_CALLING_CONVENTIONS,
     ]
 }
 
 }
 
 declare_lint! {
-    /// The `disjoint_capture_migration` lint detects variables that aren't completely
+    /// The `rust_2021_incompatible_closure_captures` lint detects variables that aren't completely
     /// captured in Rust 2021 and affect the Drop order of at least one path starting at this variable.
     /// It can also detect when a variable implements a trait, but one of its field does not and
     /// the field is captured by a closure and used with the assumption that said field implements
     /// ### Example of drop reorder
     ///
     /// ```rust,compile_fail
-    /// # #![deny(disjoint_capture_migration)]
+    /// # #![deny(rust_2021_incompatible_closure_captures)]
     /// # #![allow(unused)]
     /// struct FancyInteger(i32);
     ///
     /// ### Example of auto-trait
     ///
     /// ```rust,compile_fail
-    /// #![deny(disjoint_capture_migration)]
+    /// #![deny(rust_2021_incompatible_closure_captures)]
     /// use std::thread;
     ///
     /// struct Pointer(*mut i32);
     /// In the above example, only `fptr.0` is captured in Rust 2021.
     /// The field is of type *mut i32 which doesn't implement Send, making the code invalid as the
     /// field cannot be sent between thread safely.
-    pub DISJOINT_CAPTURE_MIGRATION,
+    pub RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
     Allow,
     "detects closures affected by Rust 2021 changes",
     @future_incompatible = FutureIncompatibleInfo {
 }
 
 declare_lint! {
-    /// The `or_patterns_back_compat` lint detects usage of old versions of or-patterns.
+    /// The `rust_2021_incompatible_or_patterns` lint detects usage of old versions of or-patterns.
     ///
     /// ### Example
     ///
     /// ```rust,compile_fail
-    /// #![deny(or_patterns_back_compat)]
+    /// #![deny(rust_2021_incompatible_or_patterns)]
     /// macro_rules! match_any {
     ///     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
     ///         match $expr {
     /// ### Explanation
     ///
     /// In Rust 2021, the pat matcher will match new patterns, which include the | character.
-    pub OR_PATTERNS_BACK_COMPAT,
+    pub RUST_2021_INCOMPATIBLE_OR_PATTERNS,
     Allow,
     "detects usage of old versions of or-patterns",
     @future_incompatible = FutureIncompatibleInfo {
 }
 
 declare_lint! {
-    /// The `future_prelude_collision` lint detects the usage of trait methods which are ambiguous
+    /// The `rust_2021_prelude_collisions` lint detects the usage of trait methods which are ambiguous
     /// with traits added to the prelude in future editions.
     ///
     /// ### Example
     ///
     /// ```rust,compile_fail
-    /// #![deny(future_prelude_collision)]
+    /// #![deny(rust_2021_prelude_collisions)]
     ///
     /// trait Foo {
     ///     fn try_into(self) -> Result<String, !>;
     ///  is called directly on a type.
     ///
     /// [prelude changes]: https://blog.rust-lang.org/inside-rust/2021/03/04/planning-rust-2021.html#prelude-changes
-    pub FUTURE_PRELUDE_COLLISION,
+    pub RUST_2021_PRELUDE_COLLISIONS,
     Allow,
     "detects the usage of trait methods which are ambiguous with traits added to the \
         prelude in future editions",
 }
 
 declare_lint! {
-    /// The `reserved_prefix` lint detects identifiers that will be parsed as a
+    /// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a
     /// prefix instead in Rust 2021.
     ///
     /// ### Example
     ///
     /// ```rust,compile_fail
-    /// #![deny(reserved_prefix)]
+    /// #![deny(rust_2021_prefixes_incompatible_syntax)]
     ///
     /// macro_rules! m {
     ///     (z $x:expr) => ();
     ///
     /// This lint suggests to add whitespace between the `z` and `"hey"` tokens
     /// to keep them separated in Rust 2021.
-    pub RESERVED_PREFIX,
+    pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
     Allow,
     "identifiers that will be parsed as a prefix in Rust 2021",
     @future_incompatible = FutureIncompatibleInfo {
     };
     crate_level_only
 }
+
+declare_lint! {
+    /// The `unsupported_calling_conventions` lint is output whenever there is an use of the
+    /// `stdcall`, `fastcall`, `thiscall`, `vectorcall` calling conventions (or their unwind
+    /// variants) on targets that cannot meaningfully be supported for the requested target.
+    ///
+    /// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc
+    /// code, because this calling convention was never specified for those targets.
+    ///
+    /// Historically MSVC toolchains have fallen back to the regular C calling convention for
+    /// targets other than x86, but Rust doesn't really see a similar need to introduce a similar
+    /// hack across many more targets.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs specific targets)
+    /// extern "stdcall" fn stdcall() {}
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// warning: use of calling convention not supported on this target
+    ///   --> $DIR/unsupported.rs:39:1
+    ///    |
+    /// LL | extern "stdcall" fn stdcall() {}
+    ///    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///    |
+    ///    = note: `#[warn(unsupported_calling_conventions)]` on by default
+    ///    = warning: this was previously accepted by the compiler but is being phased out;
+    ///               it will become a hard error in a future release!
+    ///    = note: for more information, see issue ...
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// On most of the targets the behaviour of `stdcall` and similar calling conventions is not
+    /// defined at all, but was previously accepted due to a bug in the implementation of the
+    /// compiler.
+    pub UNSUPPORTED_CALLING_CONVENTIONS,
+    Warn,
+    "use of unsupported calling convention",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #00000 <https://github.com/rust-lang/rust/issues/00000>",
+    };
+}
index 9b757eb40c1840b64834fac51a76a36f58f1ed4e..4cdc8a4155bcc58ba6489aab09e433a750afdace 100644 (file)
@@ -349,11 +349,10 @@ extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
 }
 
 extern "C" LLVMValueRef
-LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name,
-                        LLVMAtomicOrdering Order) {
+LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
+                        const char *Name, LLVMAtomicOrdering Order) {
   Value *Ptr = unwrap(Source);
-  Type *Ty = Ptr->getType()->getPointerElementType();
-  LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name);
+  LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
   LI->setAtomic(fromRust(Order));
   return wrap(LI);
 }
index 03a46efec3c7c174bd8b56568fdddf495e8eb920..250af3c6e89cb723d3ec12c07eb90890dac4dce8 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -51,6 +51,12 @@ pub struct CStore {
     unused_externs: Vec<Symbol>,
 }
 
+impl std::fmt::Debug for CStore {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("CStore").finish_non_exhaustive()
+    }
+}
+
 pub struct CrateLoader<'a> {
     // Immutable configuration.
     sess: &'a Session,
@@ -222,10 +228,8 @@ pub fn new(
         metadata_loader: Box<MetadataLoaderDyn>,
         local_crate_name: &str,
     ) -> Self {
-        let local_crate_stable_id =
-            StableCrateId::new(local_crate_name, sess.local_crate_disambiguator());
         let mut stable_crate_ids = FxHashMap::default();
-        stable_crate_ids.insert(local_crate_stable_id, LOCAL_CRATE);
+        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
 
         CrateLoader {
             sess,
@@ -327,17 +331,14 @@ fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Opt
 
     fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
         // Check for (potential) conflicts with the local crate
-        if self.local_crate_name == root.name()
-            && self.sess.local_crate_disambiguator() == root.disambiguator()
-        {
+        if self.sess.local_stable_crate_id() == root.stable_crate_id() {
             return Err(CrateError::SymbolConflictsCurrent(root.name()));
         }
 
         // Check for conflicts with any crate loaded so far
         let mut res = Ok(());
         self.cstore.iter_crate_data(|_, other| {
-            if other.name() == root.name() && // same crate-name
-               other.disambiguator() == root.disambiguator() && // same crate-disambiguator
+            if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id
                other.hash() != root.hash()
             {
                 // but different SVH
@@ -411,7 +412,7 @@ fn register_crate(
                 None => (&source, &crate_root),
             };
             let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
-            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?)
+            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
         } else {
             None
         };
@@ -664,7 +665,7 @@ fn resolve_crate_deps(
     fn dlsym_proc_macros(
         &self,
         path: &Path,
-        disambiguator: CrateDisambiguator,
+        stable_crate_id: StableCrateId,
     ) -> Result<&'static [ProcMacro], CrateError> {
         // Make sure the path contains a / or the linker will search for it.
         let path = env::current_dir().unwrap().join(path);
@@ -673,7 +674,7 @@ fn dlsym_proc_macros(
             Err(s) => return Err(CrateError::DlOpen(s)),
         };
 
-        let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator);
+        let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
         let decls = unsafe {
             let sym = match lib.symbol(&sym) {
                 Ok(f) => f,
index f7778d67d20d6295d25158c6658a8e1884010529..2d4deb1d8d5da43d9a2e19bdf5d8b32aad0c2383 100644 (file)
@@ -55,8 +55,8 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::CrateNum;
+use rustc_middle::middle::cstore::CrateDepKind;
 use rustc_middle::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
-use rustc_middle::middle::cstore::{self, CrateDepKind};
 use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
@@ -274,8 +274,18 @@ fn add_library(
 }
 
 fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
-    let crates = cstore::used_crates(tcx, RequireStatic);
-    if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
+    let all_crates_available_as_rlib = tcx
+        .crates(())
+        .iter()
+        .cloned()
+        .filter_map(|cnum| {
+            if tcx.dep_kind(cnum).macros_only() {
+                return None;
+            }
+            Some(tcx.used_crate_source(cnum).rlib.is_some())
+        })
+        .all(|is_rlib| is_rlib);
+    if !all_crates_available_as_rlib {
         return None;
     }
 
index 8570bf30f80787a7c2ac8bb0a3c13207438c8d40..028104fd6b5057a1bef7d6f13fae94eb9dcc586b 100644 (file)
 use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::CanonicalizedPath;
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::{Session, StableCrateId};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
@@ -787,7 +787,7 @@ pub fn find_plugin_registrar(
     metadata_loader: &dyn MetadataLoader,
     span: Span,
     name: Symbol,
-) -> (PathBuf, CrateDisambiguator) {
+) -> (PathBuf, StableCrateId) {
     match find_plugin_registrar_impl(sess, metadata_loader, name) {
         Ok(res) => res,
         // `core` is always available if we got as far as loading plugins.
@@ -799,7 +799,7 @@ fn find_plugin_registrar_impl<'a>(
     sess: &'a Session,
     metadata_loader: &dyn MetadataLoader,
     name: Symbol,
-) -> Result<(PathBuf, CrateDisambiguator), CrateError> {
+) -> Result<(PathBuf, StableCrateId), CrateError> {
     info!("find plugin registrar `{}`", name);
     let mut locator = CrateLocator::new(
         sess,
@@ -816,7 +816,7 @@ fn find_plugin_registrar_impl<'a>(
 
     match locator.maybe_load_library_crate()? {
         Some(library) => match library.source.dylib {
-            Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())),
+            Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())),
             None => Err(CrateError::NonDylibPlugin(name)),
         },
         None => Err(locator.into_error()),
index cd4c394ae14ecf752d1deba6ff36927be57ca8ab..16b4d26b37b4b79879bea9822765f137946a9a39 100644 (file)
@@ -3,8 +3,8 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::{DllImport, NativeLib};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport, NativeLib};
+use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_session::utils::NativeLibKind;
 use rustc_session::Session;
@@ -199,22 +199,10 @@ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
             }
 
             if lib.kind == NativeLibKind::RawDylib {
-                match abi {
-                    Abi::C { .. } => (),
-                    Abi::Cdecl => (),
-                    _ => {
-                        if sess.target.arch == "x86" {
-                            sess.span_fatal(
-                                it.span,
-                                r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#,
-                            );
-                        }
-                    }
-                };
                 lib.dll_imports.extend(
                     foreign_mod_items
                         .iter()
-                        .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }),
+                        .map(|child_item| self.build_dll_import(abi, child_item)),
                 );
             }
 
@@ -396,4 +384,58 @@ fn process_command_line(&mut self) {
             }
         }
     }
+
+    fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
+        let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
+            self.tcx
+                .type_of(item.id.def_id)
+                .fn_sig(self.tcx)
+                .inputs()
+                .map_bound(|slice| self.tcx.mk_type_list(slice.iter())),
+        );
+
+        argument_types
+            .iter()
+            .map(|ty| {
+                let layout = self
+                    .tcx
+                    .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty })
+                    .expect("layout")
+                    .layout;
+                // In both stdcall and fastcall, we always round up the argument size to the
+                // nearest multiple of 4 bytes.
+                (layout.size.bytes_usize() + 3) & !3
+            })
+            .sum()
+    }
+
+    fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport {
+        let calling_convention = if self.tcx.sess.target.arch == "x86" {
+            match abi {
+                Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
+                Abi::Stdcall { .. } | Abi::System { .. } => {
+                    DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
+                }
+                Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)),
+                // Vectorcall is intentionally not supported at this time.
+                _ => {
+                    self.tcx.sess.span_fatal(
+                        item.span,
+                        r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#,
+                    );
+                }
+            }
+        } else {
+            match abi {
+                Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C,
+                _ => {
+                    self.tcx.sess.span_fatal(
+                        item.span,
+                        r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#,
+                    );
+                }
+            }
+        };
+        DllImport { name: item.ident.name, ordinal: None, calling_convention, span: item.span }
+    }
 }
index 45972c0a0cd024bc8473769c194c9a40636d7eeb..6ecd4a512e9b40e5b66b56d6409688d36decb029 100644 (file)
@@ -633,10 +633,6 @@ impl CrateRoot<'_> {
         self.name
     }
 
-    crate fn disambiguator(&self) -> CrateDisambiguator {
-        self.disambiguator
-    }
-
     crate fn hash(&self) -> Svh {
         self.hash
     }
@@ -729,37 +725,30 @@ fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
             .decode((self, sess))
     }
 
-    fn load_proc_macro(&self, def_id: DefId, sess: &Session) -> SyntaxExtension {
-        let (name, kind, helper_attrs) = match *self.raw_proc_macro(def_id.index) {
+    fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
+        let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
             ProcMacro::CustomDerive { trait_name, attributes, client } => {
                 let helper_attrs =
                     attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
                 (
                     trait_name,
-                    SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
-                        client,
-                        krate: def_id.krate,
-                    })),
+                    SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })),
                     helper_attrs,
                 )
             }
-            ProcMacro::Attr { name, client } => (
-                name,
-                SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client, krate: def_id.krate })),
-                Vec::new(),
-            ),
-            ProcMacro::Bang { name, client } => (
-                name,
-                SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client, krate: def_id.krate })),
-                Vec::new(),
-            ),
+            ProcMacro::Attr { name, client } => {
+                (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new())
+            }
+            ProcMacro::Bang { name, client } => {
+                (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new())
+            }
         };
 
-        let attrs: Vec<_> = self.get_item_attrs(def_id.index, sess).collect();
+        let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
         SyntaxExtension::new(
             sess,
             kind,
-            self.get_span(def_id.index, sess),
+            self.get_span(id, sess),
             helper_attrs,
             self.root.edition,
             Symbol::intern(name),
@@ -1940,8 +1929,8 @@ impl CrateMetadata {
         self.root.name
     }
 
-    crate fn disambiguator(&self) -> CrateDisambiguator {
-        self.root.disambiguator
+    crate fn stable_crate_id(&self) -> StableCrateId {
+        self.root.stable_crate_id
     }
 
     crate fn hash(&self) -> Svh {
index 27723a4b9d8673d2d4c8150bb417e24a02d13676..473ae4eb386413725b0dce32629128a4b5d3c89d 100644 (file)
@@ -18,7 +18,7 @@
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, Visibility};
 use rustc_session::utils::NativeLibKind;
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::{Session, StableCrateId};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Symbol;
 
@@ -185,7 +185,6 @@ fn into_args(self) -> (DefId, DefId) {
     }
     native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
     foreign_modules => { cdata.get_foreign_modules(tcx) }
-    crate_disambiguator => { cdata.root.disambiguator }
     crate_hash => { cdata.root.hash }
     crate_host_hash => { cdata.host_hash }
     crate_name => { cdata.root.name }
@@ -412,7 +411,7 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
 
         let data = self.get_crate_data(id.krate);
         if data.root.is_proc_macro_crate() {
-            return LoadedMacro::ProcMacro(data.load_proc_macro(id, sess));
+            return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess));
         }
 
         let span = data.get_span(id.index, sess);
@@ -489,8 +488,8 @@ fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol {
         self.get_crate_data(cnum).root.name
     }
 
-    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
-        self.get_crate_data(cnum).root.disambiguator
+    fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId {
+        self.get_crate_data(cnum).root.stable_crate_id
     }
 
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh {
index 86f056b2b2d779fc55bf127e5da6e0c5e934a148..0e924d644353ce22b9a9c930a9956a2599e86d3f 100644 (file)
@@ -445,7 +445,7 @@ fn encode_info_for_items(&mut self) {
     }
 
     fn encode_def_path_table(&mut self) {
-        let table = self.tcx.hir().definitions().def_path_table();
+        let table = self.tcx.resolutions(()).definitions.def_path_table();
         if self.is_proc_macro {
             for def_index in std::iter::once(CRATE_DEF_INDEX)
                 .chain(self.tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))
@@ -671,7 +671,6 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
             triple: tcx.sess.opts.target_triple.clone(),
             hash: tcx.crate_hash(LOCAL_CRATE),
-            disambiguator: tcx.sess.local_crate_disambiguator(),
             stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
             panic_strategy: tcx.sess.panic_strategy(),
             edition: tcx.sess.edition(),
@@ -1063,7 +1062,7 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
 
         let data = ModData {
             reexports,
-            expansion: tcx.hir().definitions().expansion_that_defined(local_def_id),
+            expansion: tcx.resolutions(()).definitions.expansion_that_defined(local_def_id),
         };
 
         record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
@@ -1760,7 +1759,7 @@ fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
             .map(|(trait_def_id, mut impls)| {
                 // Bring everything into deterministic order for hashing
                 impls.sort_by_cached_key(|&(index, _)| {
-                    tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
+                    tcx.hir().def_path_hash(LocalDefId { local_def_index: index })
                 });
 
                 TraitImpls {
index 99ea0cc8f2f1634374efff7691f739ce8bf4b994..3793058062347325950c82741e396c6e027099d4 100644 (file)
@@ -18,7 +18,6 @@
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
-use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{Ident, Symbol};
@@ -202,7 +201,6 @@ macro_rules! Lazy {
     triple: TargetTriple,
     extra_filename: String,
     hash: Svh,
-    disambiguator: CrateDisambiguator,
     stable_crate_id: StableCrateId,
     panic_strategy: PanicStrategy,
     edition: Edition,
index 20bbf9097f4255c80287557d66197b27ff3d085e..6f799ea940b05c04bbc9c76a5a90c7b0550610ba 100644 (file)
@@ -9,12 +9,13 @@
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, Definitions};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::*;
 use rustc_index::vec::Idx;
+use rustc_span::def_id::StableCrateId;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -153,13 +154,9 @@ pub fn krate(&self) -> &'hir Crate<'hir> {
         self.tcx.hir_crate(())
     }
 
-    #[inline]
-    pub fn definitions(&self) -> &'hir Definitions {
-        &self.tcx.definitions
-    }
-
     pub fn def_key(&self, def_id: LocalDefId) -> DefKey {
-        self.tcx.definitions.def_key(def_id)
+        // Accessing the DefKey is ok, since it is part of DefPathHash.
+        self.tcx.untracked_resolutions.definitions.def_key(def_id)
     }
 
     pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
@@ -167,7 +164,14 @@ pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
     }
 
     pub fn def_path(&self, def_id: LocalDefId) -> DefPath {
-        self.tcx.definitions.def_path(def_id)
+        // Accessing the DefPath is ok, since it is part of DefPathHash.
+        self.tcx.untracked_resolutions.definitions.def_path(def_id)
+    }
+
+    #[inline]
+    pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
+        // Accessing the DefPathHash is ok, it is incr. comp. stable.
+        self.tcx.untracked_resolutions.definitions.def_path_hash(def_id)
     }
 
     #[inline]
@@ -183,16 +187,21 @@ pub fn local_def_id(&self, hir_id: HirId) -> LocalDefId {
 
     #[inline]
     pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<LocalDefId> {
-        self.tcx.definitions.opt_hir_id_to_local_def_id(hir_id)
+        // FIXME(#85914) is this access safe for incr. comp.?
+        self.tcx.untracked_resolutions.definitions.opt_hir_id_to_local_def_id(hir_id)
     }
 
     #[inline]
     pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
-        self.tcx.definitions.local_def_id_to_hir_id(def_id)
+        // FIXME(#85914) is this access safe for incr. comp.?
+        self.tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id)
     }
 
     pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
-        self.tcx.definitions.iter_local_def_id()
+        // Create a dependency to the crate to be sure we reexcute this when the amount of
+        // definitions change.
+        self.tcx.ensure().hir_crate(());
+        self.tcx.untracked_resolutions.definitions.iter_local_def_id()
     }
 
     pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
@@ -931,9 +940,15 @@ fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
 pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> {
     let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
 
+    // We can access untracked state since we are an eval_always query.
     let hcx = tcx.create_stable_hashing_context();
-    let mut collector =
-        NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx);
+    let mut collector = NodeCollector::root(
+        tcx.sess,
+        &**tcx.arena,
+        tcx.untracked_crate,
+        &tcx.untracked_resolutions.definitions,
+        hcx,
+    );
     intravisit::walk_crate(&mut collector, tcx.untracked_crate);
 
     let map = collector.finalize_and_compute_crate_hash();
@@ -943,6 +958,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tc
 pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     assert_eq!(crate_num, LOCAL_CRATE);
 
+    // We can access untracked state since we are an eval_always query.
     let mut hcx = tcx.create_stable_hashing_context();
 
     let mut hir_body_nodes: Vec<_> = tcx
@@ -950,7 +966,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
         .map
         .iter_enumerated()
         .filter_map(|(def_id, hod)| {
-            let def_path_hash = tcx.definitions.def_path_hash(def_id);
+            let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
             let mut hasher = StableHasher::new();
             hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
             AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
@@ -967,7 +983,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
         },
     );
 
-    let upstream_crates = upstream_crates(&*tcx.cstore);
+    let upstream_crates = upstream_crates(&*tcx.untracked_resolutions.cstore);
 
     // We hash the final, remapped names of all local source files so we
     // don't have to include the path prefix remapping commandline args.
@@ -990,25 +1006,24 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
     source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
-    tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher);
+    tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
     tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher);
 
     let crate_hash: Fingerprint = stable_hasher.finish();
     Svh::new(crate_hash.to_smaller_hash())
 }
 
-fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
+fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> {
     let mut upstream_crates: Vec<_> = cstore
         .crates_untracked()
         .iter()
         .map(|&cnum| {
-            let name = cstore.crate_name_untracked(cnum);
-            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
+            let stable_crate_id = cstore.stable_crate_id_untracked(cnum);
             let hash = cstore.crate_hash_untracked(cnum);
-            (name, disambiguator, hash)
+            (stable_crate_id, hash)
         })
         .collect();
-    upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
+    upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
     upstream_crates
 }
 
index 087f772c812bdb2cf5a2aade1900cd4d8c59f398..3026bf8274d2e2eb60717de5f7b146b4fdd2e4da 100644 (file)
@@ -169,6 +169,6 @@ pub fn provide(providers: &mut Providers) {
     providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
     providers.expn_that_defined = |tcx, id| {
         let id = id.expect_local();
-        tcx.definitions.expansion_that_defined(id)
+        tcx.resolutions(()).definitions.expansion_that_defined(id)
     };
 }
index 91c81c367a16febb0e59bc64429f0d291c8425be..f1c4529b8552b0da73a86b2c49d3a31cb6e69c24 100644 (file)
@@ -245,6 +245,8 @@ fn span_data_to_lines_and_cols(
     }
 }
 
+impl rustc_session::HashStableContext for StableHashingContext<'a> {}
+
 pub fn hash_stable_trait_impls<'a>(
     hcx: &mut StableHashingContext<'a>,
     hasher: &mut StableHasher,
index 7ac7720a7c56367afbf09be4eeb1975d2ccf9ff6..63872ca9017668c0015993b0347d816bce958b6d 100644 (file)
@@ -5,6 +5,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_hir::HirId;
+use rustc_index::vec::IndexVec;
 use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
     FutureIncompatibilityReason, Level, Lint, LintId,
@@ -51,35 +52,37 @@ pub fn span(&self) -> Span {
 /// A tuple of a lint level and its source.
 pub type LevelAndSource = (Level, LintLevelSource);
 
-#[derive(Debug)]
+#[derive(Debug, HashStable)]
 pub struct LintLevelSets {
-    pub list: Vec<LintSet>,
+    pub list: IndexVec<LintStackIndex, LintSet>,
     pub lint_cap: Level,
 }
 
-#[derive(Debug)]
-pub enum LintSet {
-    CommandLine {
-        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
-        // flag.
-        specs: FxHashMap<LintId, LevelAndSource>,
-    },
-
-    Node {
-        specs: FxHashMap<LintId, LevelAndSource>,
-        parent: u32,
-    },
+rustc_index::newtype_index! {
+    #[derive(HashStable)]
+    pub struct LintStackIndex {
+        const COMMAND_LINE = 0,
+    }
+}
+
+#[derive(Debug, HashStable)]
+pub struct LintSet {
+    // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+    // flag.
+    pub specs: FxHashMap<LintId, LevelAndSource>,
+
+    pub parent: LintStackIndex,
 }
 
 impl LintLevelSets {
     pub fn new() -> Self {
-        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+        LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid }
     }
 
     pub fn get_lint_level(
         &self,
         lint: &'static Lint,
-        idx: u32,
+        idx: LintStackIndex,
         aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
     ) -> LevelAndSource {
@@ -108,8 +111,13 @@ pub fn get_lint_level(
             }
         }
 
-        // Ensure that we never exceed the `--cap-lints` argument.
-        level = cmp::min(level, self.lint_cap);
+        // Ensure that we never exceed the `--cap-lints` argument
+        // unless the source is a --force-warn
+        level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = src {
+            level
+        } else {
+            cmp::min(level, self.lint_cap)
+        };
 
         if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
             // Ensure that we never exceed driver level.
@@ -122,7 +130,7 @@ pub fn get_lint_level(
     pub fn get_lint_id_level(
         &self,
         id: LintId,
-        mut idx: u32,
+        mut idx: LintStackIndex,
         aux: Option<&FxHashMap<LintId, LevelAndSource>>,
     ) -> (Option<Level>, LintLevelSource) {
         if let Some(specs) = aux {
@@ -131,20 +139,14 @@ pub fn get_lint_id_level(
             }
         }
         loop {
-            match self.list[idx as usize] {
-                LintSet::CommandLine { ref specs } => {
-                    if let Some(&(level, src)) = specs.get(&id) {
-                        return (Some(level), src);
-                    }
-                    return (None, LintLevelSource::Default);
-                }
-                LintSet::Node { ref specs, parent } => {
-                    if let Some(&(level, src)) = specs.get(&id) {
-                        return (Some(level), src);
-                    }
-                    idx = parent;
-                }
+            let LintSet { ref specs, parent } = self.list[idx];
+            if let Some(&(level, src)) = specs.get(&id) {
+                return (Some(level), src);
+            }
+            if idx == COMMAND_LINE {
+                return (None, LintLevelSource::Default);
             }
+            idx = parent;
         }
     }
 }
@@ -152,7 +154,7 @@ pub fn get_lint_id_level(
 #[derive(Debug)]
 pub struct LintLevelMap {
     pub sets: LintLevelSets,
-    pub id_to_set: FxHashMap<HirId, u32>,
+    pub id_to_set: FxHashMap<HirId, LintStackIndex>,
 }
 
 impl LintLevelMap {
@@ -180,29 +182,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 
         id_to_set.hash_stable(hcx, hasher);
 
-        let LintLevelSets { ref list, lint_cap } = *sets;
-
-        lint_cap.hash_stable(hcx, hasher);
-
-        hcx.while_hashing_spans(true, |hcx| {
-            list.len().hash_stable(hcx, hasher);
-
-            // We are working under the assumption here that the list of
-            // lint-sets is built in a deterministic order.
-            for lint_set in list {
-                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
-
-                match *lint_set {
-                    LintSet::CommandLine { ref specs } => {
-                        specs.hash_stable(hcx, hasher);
-                    }
-                    LintSet::Node { ref specs, parent } => {
-                        specs.hash_stable(hcx, hasher);
-                        parent.hash_stable(hcx, hasher);
-                    }
-                }
-            }
-        })
+        hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher))
     }
 }
 
@@ -258,8 +238,10 @@ fn struct_lint_level_impl(
                     return;
                 }
             }
-            (Level::Warn | Level::ForceWarn, Some(span)) => sess.struct_span_warn(span, ""),
-            (Level::Warn | Level::ForceWarn, None) => sess.struct_warn(""),
+            (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""),
+            (Level::Warn, None) => sess.struct_warn(""),
+            (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""),
+            (Level::ForceWarn, None) => sess.struct_force_warn(""),
             (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
             (Level::Deny | Level::Forbid, None) => sess.struct_err(""),
         };
@@ -349,7 +331,8 @@ fn struct_lint_level_impl(
             }
         }
 
-        err.code(DiagnosticId::Lint { name, has_future_breakage });
+        let is_force_warn = matches!(level, Level::ForceWarn);
+        err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
 
         if let Some(future_incompatible) = future_incompatible {
             let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
@@ -404,7 +387,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
             false
         }
         ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
-        ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ } => {
+        ExpnKind::Macro(MacroKind::Bang, _) => {
             // Dummy span for the `def_site` means it's an external macro.
             expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site)
         }
index e9bcbe016c7c903f0f9ff59a45e136cc501b09a7..fcd4988635b079a3beb6dc139586ec0a4ed42fa7 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_macros::HashStable;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
-use rustc_session::CrateDisambiguator;
+use rustc_session::StableCrateId;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::Target;
@@ -60,26 +60,6 @@ pub fn macros_only(self) -> bool {
     }
 }
 
-#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
-pub enum LibSource {
-    Some(PathBuf),
-    MetadataOnly,
-    None,
-}
-
-impl LibSource {
-    pub fn is_some(&self) -> bool {
-        matches!(self, LibSource::Some(_))
-    }
-
-    pub fn option(&self) -> Option<PathBuf> {
-        match *self {
-            LibSource::Some(ref p) => Some(p.clone()),
-            LibSource::MetadataOnly | LibSource::None => None,
-        }
-    }
-}
-
 #[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)]
 pub enum LinkagePreference {
     RequireDynamic,
@@ -97,10 +77,29 @@ pub struct NativeLib {
     pub dll_imports: Vec<DllImport>,
 }
 
-#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
 pub struct DllImport {
     pub name: Symbol,
     pub ordinal: Option<u16>,
+    /// Calling convention for the function.
+    ///
+    /// On x86_64, this is always `DllCallingConvention::C`; on i686, it can be any
+    /// of the values, and we use `DllCallingConvention::C` to represent `"cdecl"`.
+    pub calling_convention: DllCallingConvention,
+    /// Span of import's "extern" declaration; used for diagnostics.
+    pub span: Span,
+}
+
+/// Calling convention for a function defined in an external library.
+///
+/// The usize value, where present, indicates the size of the function's argument list
+/// in bytes.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
+pub enum DllCallingConvention {
+    C,
+    Stdcall(usize),
+    Fastcall(usize),
+    Vectorcall(usize),
 }
 
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
@@ -188,7 +187,7 @@ pub trait MetadataLoader {
 /// that it's *not* tracked for dependency information throughout compilation
 /// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
 /// during resolve)
-pub trait CrateStore {
+pub trait CrateStore: std::fmt::Debug {
     fn as_any(&self) -> &dyn Any;
 
     // resolve
@@ -205,7 +204,7 @@ fn def_path_hash_to_def_id(
 
     // "queries" used in resolve that aren't tracked for incremental compilation
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
-    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
+    fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
 
     // This is basically a 1-based range of ints, which is a little
@@ -217,45 +216,3 @@ fn def_path_hash_to_def_id(
 }
 
 pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
-
-// This method is used when generating the command line to pass through to
-// system linker. The linker expects undefined symbols on the left of the
-// command line to be defined in libraries on the right, not the other way
-// around. For more info, see some comments in the add_used_library function
-// below.
-//
-// In order to get this left-to-right dependency ordering, we perform a
-// topological sort of all crates putting the leaves at the right-most
-// positions.
-pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> {
-    let mut libs = tcx
-        .crates(())
-        .iter()
-        .cloned()
-        .filter_map(|cnum| {
-            if tcx.dep_kind(cnum).macros_only() {
-                return None;
-            }
-            let source = tcx.used_crate_source(cnum);
-            let path = match prefer {
-                LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
-                LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
-            };
-            let path = match path {
-                Some(p) => LibSource::Some(p),
-                None => {
-                    if source.rmeta.is_some() {
-                        LibSource::MetadataOnly
-                    } else {
-                        LibSource::None
-                    }
-                }
-            };
-            Some((cnum, path))
-        })
-        .collect::<Vec<_>>();
-    let mut ordering = tcx.postorder_cnums(()).to_owned();
-    ordering.reverse();
-    libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a));
-    libs
-}
index 288dd0394464581691c16201964eaa7b2f085d8e..5ea78e087f8451c34d6503dc45060f4f93bdfc46 100644 (file)
@@ -48,8 +48,8 @@ pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolNam
 
 pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
     format!(
-        "rust_metadata_{}_{}",
+        "rust_metadata_{}_{:08x}",
         tcx.crate_name(LOCAL_CRATE),
-        tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
+        tcx.sess.local_stable_crate_id().to_u64(),
     )
 }
index 601198fd0de0443090df30821db510102dee1d82..c4bfd0ebb2fde61996d0e3f365ed89e0f027cf16 100644 (file)
 //! just peeks and looks for that attribute.
 
 use crate::bug;
-use rustc_ast as ast;
-use rustc_data_structures::sync::OnceCell;
+use crate::ty;
+use rustc_ast::Attribute;
 use rustc_session::Session;
+use rustc_session::{Limit, Limits};
 use rustc_span::symbol::{sym, Symbol};
 
 use std::num::IntErrorKind;
 
-pub fn update_limits(sess: &Session, krate: &ast::Crate) {
-    update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
-    update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0);
-    update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
-    update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
+pub fn provide(providers: &mut ty::query::Providers) {
+    providers.limits = |tcx, ()| Limits {
+        recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
+        move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0),
+        type_length_limit: get_limit(
+            tcx.hir().krate_attrs(),
+            tcx.sess,
+            sym::type_length_limit,
+            1048576,
+        ),
+        const_eval_limit: get_limit(
+            tcx.hir().krate_attrs(),
+            tcx.sess,
+            sym::const_eval_limit,
+            1_000_000,
+        ),
+    }
+}
+
+pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
+    get_limit(krate_attrs, sess, sym::recursion_limit, 128)
 }
 
-fn update_limit(
-    sess: &Session,
-    krate: &ast::Crate,
-    limit: &OnceCell<impl From<usize> + std::fmt::Debug>,
-    name: Symbol,
-    default: usize,
-) {
-    for attr in &krate.attrs {
+fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
+    for attr in krate_attrs {
         if !sess.check_name(attr, name) {
             continue;
         }
 
         if let Some(s) = attr.value_str() {
             match s.as_str().parse() {
-                Ok(n) => {
-                    limit.set(From::from(n)).unwrap();
-                    return;
-                }
+                Ok(n) => return Limit::new(n),
                 Err(e) => {
                     let mut err =
                         sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
@@ -68,5 +76,5 @@ fn update_limit(
             }
         }
     }
-    limit.set(From::from(default)).unwrap();
+    return Limit::new(default);
 }
index a369e85306b36514815730773d7b4be4c7f93edb..b370ec152e8ecf685c7f874efb6f94975c4b68a5 100644 (file)
@@ -32,3 +32,7 @@ pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
 pub mod region;
 pub mod resolve_lifetime;
 pub mod stability;
+
+pub fn provide(providers: &mut crate::ty::query::Providers) {
+    limits::provide(providers);
+}
index aa0f18846d1540c981015f2de000021c19b37d34..2804fe580615c2dfafea4c99c1016762a318939c 100644 (file)
@@ -226,18 +226,19 @@ fn late_report_deprecation(
     suggestion: Option<Symbol>,
     lint: &'static Lint,
     span: Span,
+    method_span: Option<Span>,
     hir_id: HirId,
     def_id: DefId,
 ) {
     if span.in_derive_expansion() {
         return;
     }
-
-    tcx.struct_span_lint_hir(lint, hir_id, span, |lint| {
+    let method_span = method_span.unwrap_or(span);
+    tcx.struct_span_lint_hir(lint, hir_id, method_span, |lint| {
         let mut diag = lint.build(message);
         if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
             let kind = tcx.def_kind(def_id).descr(def_id);
-            deprecation_suggestion(&mut diag, kind, suggestion, span);
+            deprecation_suggestion(&mut diag, kind, suggestion, method_span);
         }
         diag.emit()
     });
@@ -306,13 +307,13 @@ pub fn eval_stability(
                     let path = &with_no_trimmed_paths(|| self.def_path_str(def_id));
                     let kind = self.def_kind(def_id).descr(def_id);
                     let (message, lint) = deprecation_message(&depr_entry.attr, kind, path);
-                    let span = method_span.unwrap_or(span);
                     late_report_deprecation(
                         self,
                         &message,
                         depr_entry.attr.suggestion,
                         lint,
                         span,
+                        method_span,
                         id,
                         def_id,
                     );
index f1b1bb9ab88ab4b9dbd42a0e9a6549e76341decd..c2645a0914007f012fa2d55f886558dfa2b9a720 100644 (file)
@@ -361,6 +361,8 @@ pub fn write_scalar(
         range: AllocRange,
         val: ScalarMaybeUninit<Tag>,
     ) -> AllocResult {
+        assert!(self.mutability == Mutability::Mut);
+
         let val = match val {
             ScalarMaybeUninit::Scalar(scalar) => scalar,
             ScalarMaybeUninit::Uninit => {
@@ -484,6 +486,7 @@ pub fn mark_init(&mut self, range: AllocRange, is_init: bool) {
         if range.size.bytes() == 0 {
             return;
         }
+        assert!(self.mutability == Mutability::Mut);
         self.init_mask.set_range(range.start, range.end(), is_init);
     }
 }
index 672686410f9bfcb3e4dc8382a2b44dff7ec957f0..ed813c054c2636d29121799b78211fc854223dd4 100644 (file)
@@ -651,7 +651,7 @@ pub enum BorrowKind {
     /// in an aliasable location. To solve, you'd have to translate with
     /// an `&mut` borrow:
     ///
-    ///     struct Env { x: & &mut isize }
+    ///     struct Env { x: &mut &mut isize }
     ///     let x: &mut isize = ...;
     ///     let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
     ///     fn fn_ptr(env: &mut Env) { **env.x += 5; }
index 74650f50a1c8aa6385cc7d82fa6cba005be6ff23..776cf002c170311a3be270f90f7f53d2a3e78208 100644 (file)
@@ -490,15 +490,23 @@ pub fn build_cgu_name_no_mangle<I, C, S>(
             // local crate's ID. Otherwise there can be collisions between CGUs
             // instantiating stuff for upstream crates.
             let local_crate_id = if cnum != LOCAL_CRATE {
-                let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE));
-                format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8])
+                let local_stable_crate_id = tcx.sess.local_stable_crate_id();
+                format!(
+                    "-in-{}.{:08x}",
+                    tcx.crate_name(LOCAL_CRATE),
+                    local_stable_crate_id.to_u64() as u32,
+                )
             } else {
                 String::new()
             };
 
-            let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
-            // Using a shortened disambiguator of about 40 bits
-            format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id)
+            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            format!(
+                "{}.{:08x}{}",
+                tcx.crate_name(cnum),
+                stable_crate_id.to_u64() as u32,
+                local_crate_id,
+            )
         });
 
         write!(cgu_name, "{}", crate_prefix).unwrap();
index 0986a46572969b4293dd6902c5d7b6f6fc6ed086..79a4e94948e5e9a9107d91c55a42caf0445b7be2 100644 (file)
         desc { "trigger a delay span bug" }
     }
 
+    query resolutions(_: ()) -> &'tcx ty::ResolverOutputs {
+        eval_always
+        no_hash
+        desc { "get the resolver outputs" }
+    }
+
     /// Represents crate as a whole (as distinct from the top-level crate module).
     /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
     /// we will have to assume that any change means that you need to be recompiled.
     }
 
     query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
-        eval_always
         desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
     }
 
         desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
     }
 
+    query should_inherit_track_caller(def_id: DefId) -> bool {
+        desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
+    }
+
     query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
         desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
     }
 
     query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export<LocalDefId>]> {
         desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
-        eval_always
     }
 
     query impl_defaultness(def_id: DefId) -> hir::Defaultness {
     query proc_macro_decls_static(_: ()) -> Option<LocalDefId> {
         desc { "looking up the derive registrar for a crate" }
     }
-    query crate_disambiguator(_: CrateNum) -> CrateDisambiguator {
-        eval_always
-        desc { "looking up the disambiguator a crate" }
-    }
     // The macro which defines `rustc_metadata::provide_extern` depends on this query's name.
     // Changing the name should cause a compiler error, but in case that changes, be aware.
     query crate_hash(_: CrateNum) -> Svh {
     }
 
     query visibility(def_id: DefId) -> ty::Visibility {
-        eval_always
         desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
     }
 
         desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
     }
     query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
-        // This depends on untracked global state (`tcx.extern_crate_map`)
-        eval_always
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
         eval_always
     }
     query maybe_unused_trait_import(def_id: LocalDefId) -> bool {
-        eval_always
         desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
     query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
-        eval_always
         desc { "looking up all possibly unused extern crates" }
     }
-    query names_imported_by_glob_use(def_id: LocalDefId)
-        -> &'tcx FxHashSet<Symbol> {
-        eval_always
+    query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
         desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
         desc { "calculating the stability index for the local crate" }
     }
     query crates(_: ()) -> &'tcx [CrateNum] {
-        eval_always
         desc { "fetching all foreign CrateNum instances" }
     }
 
         desc { "evaluating trait selection obligation `{}`", goal.value }
     }
 
-    /// Evaluates whether the given type implements the given trait
-    /// in the given environment.
-    ///
-    /// The inputs are:
-    ///
-    /// - the def-id of the trait
-    /// - the self type
-    /// - the *other* type parameters of the trait, excluding the self-type
-    /// - the parameter environment
-    ///
-    /// FIXME. If the type, trait, or environment has inference variables,
-    /// this yields `EvaluatedToUnknown`. It should be refactored
-    /// to use canonicalization, really.
-    query type_implements_trait(
-        key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
-    ) -> traits::EvaluationResult {
-        desc { "evaluating `type_implements_trait` `{:?}`", key }
-    }
-
     /// Do not call this query directly: part of the `Eq` type-op
     query type_op_ascribe_user_type(
         goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
     query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
         desc { "conservatively checking if {:?} is privately uninhabited", key }
     }
+
+    query limits(key: ()) -> Limits {
+        desc { "looking up limits" }
+    }
 }
index c9b73c682098b6fd728e8c388294de4774658beb..892a29e4e22c7e4e090d95b0cb01431c88321aec 100644 (file)
@@ -426,10 +426,10 @@ pub enum SelectionError<'tcx> {
 /// impl Clone for i32 { ... }                   // Impl_3
 ///
 /// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
-///     // Case A: Vtable points at a specific impl. Only possible when
+///     // Case A: ImplSource points at a specific impl. Only possible when
 ///     // type is concretely known. If the impl itself has bounded
-///     // type parameters, Vtable will carry resolutions for those as well:
-///     concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
+///     // type parameters, ImplSource will carry resolutions for those as well:
+///     concrete.clone(); // ImpleSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
 ///
 ///     // Case A: ImplSource points at a specific impl. Only possible when
 ///     // type is concretely known. If the impl itself has bounded
index 0706a057dd0c6d6d335989d6ce9663e1ab85b18d..b0156daf17effd53b59b8b5aca1861a6cfe8c82f 100644 (file)
@@ -347,7 +347,7 @@ pub enum BorrowKind {
     /// an `&mut` borrow:
     ///
     /// ```
-    /// struct Env { x: & &mut isize }
+    /// struct Env { x: &mut &mut isize }
     /// let x: &mut isize = ...;
     /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
     /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
index 257912ad57e4f8054234a9b93e32a008aa07818d..1afeb4a138f9da1334d428a90bf007684ad4186f 100644 (file)
@@ -2,13 +2,12 @@
 
 use crate::arena::Arena;
 use crate::dep_graph::DepGraph;
-use crate::hir::exports::ExportMap;
 use crate::hir::place::Place as HirPlace;
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
 use crate::middle;
-use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata};
+use crate::middle::cstore::EncodedMetadata;
 use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
 use crate::middle::stability;
 use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
 use crate::ty::{
     self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
     ClosureSizeProfileData, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar,
-    FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List,
-    MainDefinition, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
-    ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
-    TyVid, TypeAndMut, UintTy, Visibility,
+    FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+    ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind,
+    ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
 };
 use rustc_ast as ast;
 use rustc_attr as attr;
@@ -39,7 +37,6 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::definitions::Definitions;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
@@ -53,6 +50,7 @@
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
 use rustc_session::lint::{Level, Lint};
+use rustc_session::Limit;
 use rustc_session::Session;
 use rustc_span::def_id::StableCrateId;
 use rustc_span::source_map::MultiSpan;
@@ -965,8 +963,6 @@ pub struct GlobalCtxt<'tcx> {
 
     interners: CtxtInterners<'tcx>,
 
-    pub(crate) cstore: Box<CrateStoreDyn>,
-
     pub sess: &'tcx Session,
 
     /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
@@ -988,17 +984,10 @@ pub struct GlobalCtxt<'tcx> {
     /// Common consts, pre-interned for your convenience.
     pub consts: CommonConsts<'tcx>,
 
-    /// Visibilities produced by resolver.
-    pub visibilities: FxHashMap<LocalDefId, Visibility>,
-
-    /// Resolutions of `extern crate` items produced by resolver.
-    extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
-
-    /// Export map produced by name resolution.
-    export_map: ExportMap<LocalDefId>,
+    /// Output of the resolver.
+    pub(crate) untracked_resolutions: ty::ResolverOutputs,
 
     pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>,
-    pub(crate) definitions: Definitions,
 
     /// This provides access to the incremental compilation on-disk cache for query results.
     /// Do not access this directly. It is only meant to be used by
@@ -1009,15 +998,6 @@ pub struct GlobalCtxt<'tcx> {
     pub queries: &'tcx dyn query::QueryEngine<'tcx>,
     pub query_caches: query::QueryCaches<'tcx>,
 
-    maybe_unused_trait_imports: FxHashSet<LocalDefId>,
-    maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
-    /// A map of glob use to a set of names it actually imports. Currently only
-    /// used in save-analysis.
-    pub(crate) glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
-    /// Extern prelude entries. The value is `true` if the entry was introduced
-    /// via `extern crate` item and not `--extern` option or compiler built-in.
-    pub extern_prelude: FxHashMap<Symbol, bool>,
-
     // Internal caches for metadata decoding. No need to track deps on this.
     pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
     pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
@@ -1051,8 +1031,6 @@ pub struct GlobalCtxt<'tcx> {
 
     output_filenames: Arc<OutputFilenames>,
 
-    pub main_def: Option<MainDefinition>,
-
     pub(super) vtables_cache:
         Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
 }
@@ -1175,28 +1153,19 @@ pub fn create_global_ctxt(
         let common_types = CommonTypes::new(&interners);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
-        let cstore = resolutions.cstore;
 
         GlobalCtxt {
             sess: s,
             lint_store,
-            cstore,
             arena,
             interners,
             dep_graph,
+            untracked_resolutions: resolutions,
             prof: s.prof.clone(),
             types: common_types,
             lifetimes: common_lifetimes,
             consts: common_consts,
-            visibilities: resolutions.visibilities,
-            extern_crate_map: resolutions.extern_crate_map,
-            export_map: resolutions.export_map,
-            maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
-            maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
-            glob_map: resolutions.glob_map,
-            extern_prelude: resolutions.extern_prelude,
             untracked_crate: krate,
-            definitions: resolutions.definitions,
             on_disk_cache,
             queries,
             query_caches: query::QueryCaches::default(),
@@ -1211,7 +1180,6 @@ pub fn create_global_ctxt(
             const_stability_interner: Default::default(),
             alloc_map: Lock::new(interpret::AllocMap::new()),
             output_filenames: Arc::new(output_filenames),
-            main_def: resolutions.main_def,
             vtables_cache: Default::default(),
         }
     }
@@ -1272,7 +1240,12 @@ pub fn features(self) -> &'tcx rustc_feature::Features {
     }
 
     pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
-        if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) }
+        // Accessing the DefKey is ok, since it is part of DefPathHash.
+        if let Some(id) = id.as_local() {
+            self.untracked_resolutions.definitions.def_key(id)
+        } else {
+            self.untracked_resolutions.cstore.def_key(id)
+        }
     }
 
     /// Converts a `DefId` into its fully expanded `DefPath` (every
@@ -1281,74 +1254,88 @@ pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
     /// Note that if `id` is not local to this crate, the result will
     ///  be a non-local `DefPath`.
     pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
+        // Accessing the DefPath is ok, since it is part of DefPathHash.
         if let Some(id) = id.as_local() {
-            self.hir().def_path(id)
+            self.untracked_resolutions.definitions.def_path(id)
         } else {
-            self.cstore.def_path(id)
+            self.untracked_resolutions.cstore.def_path(id)
         }
     }
 
     #[inline]
     pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
+        // Accessing the DefPathHash is ok, it is incr. comp. stable.
         if let Some(def_id) = def_id.as_local() {
-            self.definitions.def_path_hash(def_id)
+            self.untracked_resolutions.definitions.def_path_hash(def_id)
         } else {
-            self.cstore.def_path_hash(def_id)
+            self.untracked_resolutions.cstore.def_path_hash(def_id)
         }
     }
 
     #[inline]
-    pub fn stable_crate_id(self, cnum: CrateNum) -> StableCrateId {
-        self.def_path_hash(cnum.as_def_id()).stable_crate_id()
+    pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
+        if crate_num == LOCAL_CRATE {
+            self.sess.local_stable_crate_id()
+        } else {
+            self.untracked_resolutions.cstore.stable_crate_id_untracked(crate_num)
+        }
     }
 
     pub fn def_path_debug_str(self, def_id: DefId) -> String {
         // We are explicitly not going through queries here in order to get
-        // crate name and disambiguator since this code is called from debug!()
+        // crate name and stable crate id since this code is called from debug!()
         // statements within the query system and we'd run into endless
         // recursion otherwise.
-        let (crate_name, crate_disambiguator) = if def_id.is_local() {
-            (self.crate_name, self.sess.local_crate_disambiguator())
+        let (crate_name, stable_crate_id) = if def_id.is_local() {
+            (self.crate_name, self.sess.local_stable_crate_id())
         } else {
+            let cstore = &self.untracked_resolutions.cstore;
             (
-                self.cstore.crate_name_untracked(def_id.krate),
-                self.cstore.crate_disambiguator_untracked(def_id.krate),
+                cstore.crate_name_untracked(def_id.krate),
+                cstore.stable_crate_id_untracked(def_id.krate),
             )
         };
 
         format!(
             "{}[{}]{}",
             crate_name,
-            // Don't print the whole crate disambiguator. That's just
+            // Don't print the whole stable crate id. That's just
             // annoying in debug output.
-            &(crate_disambiguator.to_fingerprint().to_hex())[..4],
+            &(format!("{:08x}", stable_crate_id.to_u64()))[..4],
             self.def_path(def_id).to_string_no_crate_verbose()
         )
     }
 
     pub fn encode_metadata(self) -> EncodedMetadata {
         let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata");
-        self.cstore.encode_metadata(self)
+        self.untracked_resolutions.cstore.encode_metadata(self)
     }
 
     // Note that this is *untracked* and should only be used within the query
     // system if the result is otherwise tracked through queries
     pub fn cstore_as_any(self) -> &'tcx dyn Any {
-        self.cstore.as_any()
+        self.untracked_resolutions.cstore.as_any()
     }
 
     #[inline(always)]
     pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
         let krate = self.gcx.untracked_crate;
+        let resolutions = &self.gcx.untracked_resolutions;
 
-        StableHashingContext::new(self.sess, krate, &self.definitions, &*self.cstore)
+        StableHashingContext::new(self.sess, krate, &resolutions.definitions, &*resolutions.cstore)
     }
 
     #[inline(always)]
     pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> {
         let krate = self.gcx.untracked_crate;
+        let resolutions = &self.gcx.untracked_resolutions;
 
-        StableHashingContext::ignore_spans(self.sess, krate, &self.definitions, &*self.cstore)
+        StableHashingContext::ignore_spans(
+            self.sess,
+            krate,
+            &resolutions.definitions,
+            &*resolutions.cstore,
+        )
     }
 
     pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult {
@@ -1569,6 +1556,22 @@ pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static s
             def_kind => (def_kind.article(), def_kind.descr(def_id)),
         }
     }
+
+    pub fn type_length_limit(self) -> Limit {
+        self.limits(()).type_length_limit
+    }
+
+    pub fn recursion_limit(self) -> Limit {
+        self.limits(()).recursion_limit
+    }
+
+    pub fn move_size_limit(self) -> Limit {
+        self.limits(()).move_size_limit
+    }
+
+    pub fn const_eval_limit(self) -> Limit {
+        self.limits(()).const_eval_limit
+    }
 }
 
 /// A trait implemented for all `X<'a>` types that can be safely and
@@ -2800,15 +2803,19 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
 
 pub fn provide(providers: &mut ty::query::Providers) {
     providers.in_scope_traits_map = |tcx, id| tcx.hir_crate(()).trait_map.get(&id);
-    providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).map(|v| &v[..]);
+    providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
+    providers.module_exports = |tcx, id| tcx.resolutions(()).export_map.get(&id).map(|v| &v[..]);
     providers.crate_name = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
         tcx.crate_name
     };
-    providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id);
-    providers.maybe_unused_extern_crates = |tcx, ()| &tcx.maybe_unused_extern_crates[..];
-    providers.names_imported_by_glob_use =
-        |tcx, id| tcx.arena.alloc(tcx.glob_map.get(&id).cloned().unwrap_or_default());
+    providers.maybe_unused_trait_import =
+        |tcx, id| tcx.resolutions(()).maybe_unused_trait_imports.contains(&id);
+    providers.maybe_unused_extern_crates =
+        |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
+    providers.names_imported_by_glob_use = |tcx, id| {
+        tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
+    };
 
     providers.lookup_stability = |tcx, id| {
         let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
@@ -2822,8 +2829,10 @@ pub fn provide(providers: &mut ty::query::Providers) {
         let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_deprecation_entry(id)
     };
-    providers.extern_mod_stmt_cnum = |tcx, id| tcx.extern_crate_map.get(&id).cloned();
-    providers.crates = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked());
+    providers.extern_mod_stmt_cnum =
+        |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
+    providers.crates =
+        |tcx, ()| tcx.arena.alloc_slice(&tcx.resolutions(()).cstore.crates_untracked());
     providers.output_filenames = |tcx, ()| tcx.output_filenames.clone();
     providers.features_query = |tcx, ()| tcx.sess.features_untracked();
     providers.is_panic_runtime = |tcx, cnum| {
index 41d953216e0dd1425d2b59d465c4720c2e57ebdf..261a19f862e02958b226f4e386f04c6ce17793b6 100644 (file)
@@ -227,8 +227,9 @@ pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool {
 
     pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
         match *self {
-            InstanceDef::Item(def) => {
-                tcx.codegen_fn_attrs(def.did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+            InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
+            | InstanceDef::Virtual(def_id, _) => {
+                tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
             }
             _ => false,
         }
@@ -403,7 +404,7 @@ pub fn resolve_for_vtable(
         def_id: DefId,
         substs: SubstsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
-        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
+        debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
         let fn_sig = tcx.fn_sig(def_id);
         let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
             && fn_sig.input(0).skip_binder().is_param(0)
@@ -412,7 +413,50 @@ pub fn resolve_for_vtable(
             debug!(" => associated item with unsizeable self: Self");
             Some(Instance { def: InstanceDef::VtableShim(def_id), substs })
         } else {
-            Instance::resolve_for_fn_ptr(tcx, param_env, def_id, substs)
+            Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
+                match resolved.def {
+                    InstanceDef::Item(def) => {
+                        // We need to generate a shim when we cannot guarantee that
+                        // the caller of a trait object method will be aware of
+                        // `#[track_caller]` - this ensures that the caller
+                        // and callee ABI will always match.
+                        //
+                        // The shim is generated when all of these conditions are met:
+                        //
+                        // 1) The underlying method expects a caller location parameter
+                        // in the ABI
+                        if resolved.def.requires_caller_location(tcx)
+                            // 2) The caller location parameter comes from having `#[track_caller]`
+                            // on the implementation, and *not* on the trait method.
+                            && !tcx.should_inherit_track_caller(def.did)
+                            // If the method implementation comes from the trait definition itself
+                            // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
+                            // then we don't need to generate a shim. This check is needed because
+                            // `should_inherit_track_caller` returns `false` if our method
+                            // implementation comes from the trait block, and not an impl block
+                            && !matches!(
+                                tcx.opt_associated_item(def.did),
+                                Some(ty::AssocItem {
+                                    container: ty::AssocItemContainer::TraitContainer(_),
+                                    ..
+                                })
+                            )
+                        {
+                            debug!(
+                                " => vtable fn pointer created for function with #[track_caller]"
+                            );
+                            resolved.def = InstanceDef::ReifyShim(def.did);
+                        }
+                    }
+                    InstanceDef::Virtual(def_id, _) => {
+                        debug!(" => vtable fn pointer created for virtual call");
+                        resolved.def = InstanceDef::ReifyShim(def_id);
+                    }
+                    _ => {}
+                }
+
+                resolved
+            })
         }
     }
 
index 6b1ec1b0646aec1354d6ade066bd2539fae58b32..dbb5064c4f546f9a0a0dea613934bca8f873fd1c 100644 (file)
@@ -221,7 +221,7 @@ fn layout_raw<'tcx>(
     ty::tls::with_related_context(tcx, move |icx| {
         let (param_env, ty) = query.into_parts();
 
-        if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) {
+        if !tcx.recursion_limit().value_within_limit(icx.layout_depth) {
             tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
         }
 
index 7036c05a593e84e377782f7a32f0165b32156b73..42a8f1763f117b8f110278a8764a4e9f492a92e0 100644 (file)
 
 // Data types
 
+#[derive(Debug)]
 pub struct ResolverOutputs {
     pub definitions: rustc_hir::definitions::Definitions,
     pub cstore: Box<CrateStoreDyn>,
@@ -1902,13 +1903,11 @@ pub fn adjust_ident_and_get_scope(
         scope: DefId,
         block: hir::HirId,
     ) -> (Ident, DefId) {
-        let scope =
-            match ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) {
-                Some(actual_expansion) => {
-                    self.hir().definitions().parent_module_of_macro_def(actual_expansion)
-                }
-                None => self.parent_module(block).to_def_id(),
-            };
+        let scope = ident
+            .span
+            .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope))
+            .and_then(|actual_expansion| actual_expansion.expn_data().parent_module)
+            .unwrap_or_else(|| self.parent_module(block).to_def_id());
         (ident, scope)
     }
 
@@ -1987,6 +1986,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
     util::provide(providers);
     print::provide(providers);
     super::util::bug::provide(providers);
+    super::middle::provide(providers);
     *providers = ty::query::Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         type_uninhabited_from: inhabitedness::type_uninhabited_from,
index c59394a23d044efdcd39c5ce8b89bc08403fef0d..21d5baced7687de4df41f9abf89d8c93655909a6 100644 (file)
@@ -1437,7 +1437,7 @@ fn print_region(self, region: ty::Region<'_>) -> Result<Self::Region, Self::Erro
     }
 
     fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
-        let type_length_limit = self.tcx.sess.type_length_limit();
+        let type_length_limit = self.tcx.type_length_limit();
         if type_length_limit.value_within_limit(self.printed_type_count) {
             self.printed_type_count += 1;
             self.pretty_print_type(ty)
@@ -2313,7 +2313,7 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
         &mut FxHashMap::default();
 
-    for symbol_set in tcx.glob_map.values() {
+    for symbol_set in tcx.resolutions(()).glob_map.values() {
         for symbol in symbol_set {
             unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
             unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
index 2ac121fec7ee0db4df90c7de2766bf16695d300d..2ed9ede8951c9ff639936a828279a4a414619e09 100644 (file)
@@ -48,7 +48,7 @@
 use rustc_serialize::opaque;
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::utils::NativeLibKind;
-use rustc_session::CrateDisambiguator;
+use rustc_session::Limits;
 use rustc_target::spec::PanicStrategy;
 
 use rustc_ast as ast;
index 2bdb1ccac595810209c8aad4730ee977ea4a6020..15188643d66319c3388d7ce116dff37900bd765b 100644 (file)
@@ -584,7 +584,9 @@ pub(crate) fn def_path_hash_to_def_id(
                 debug!("def_path_hash_to_def_id({:?})", hash);
                 // Check if the `DefPathHash` corresponds to a definition in the current
                 // crate
-                if let Some(def_id) = tcx.definitions.local_def_path_hash_to_def_id(hash) {
+                if let Some(def_id) =
+                    tcx.untracked_resolutions.definitions.local_def_path_hash_to_def_id(hash)
+                {
                     let def_id = def_id.to_def_id();
                     e.insert(Some(def_id));
                     return Some(def_id);
@@ -612,7 +614,11 @@ pub(crate) fn def_path_hash_to_def_id(
                 debug_assert_ne!(krate, LOCAL_CRATE);
                 // Try to find a definition in the current session, using the previous `DefIndex`
                 // as an initial guess.
-                let opt_def_id = tcx.cstore.def_path_hash_to_def_id(krate, raw_def_id.index, hash);
+                let opt_def_id = tcx.untracked_resolutions.cstore.def_path_hash_to_def_id(
+                    krate,
+                    raw_def_id.index,
+                    hash,
+                );
                 debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
                 e.insert(opt_def_id);
                 opt_def_id
index 6344327e6aa9a310f87aedda3926d0e483c4aa70..485be4c9987bd073a965567ae955e6e116ed8782 100644 (file)
@@ -206,8 +206,9 @@ pub fn struct_tail_with_normalize(
         mut ty: Ty<'tcx>,
         normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>,
     ) -> Ty<'tcx> {
+        let recursion_limit = self.recursion_limit();
         for iteration in 0.. {
-            if !self.sess.recursion_limit().value_within_limit(iteration) {
+            if !recursion_limit.value_within_limit(iteration) {
                 return self.ty_error_with_message(
                     DUMMY_SP,
                     &format!("reached the recursion limit finding the struct tail for {}", ty),
index 4be4372c0393aba6cf53c05a9635c1a7144b47bc..0b01c4efcdbd4688798487a6655b92fb4166930c 100644 (file)
@@ -13,6 +13,7 @@
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt;
 
 use crate::dataflow::drop_flag_effects;
 use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
@@ -1330,8 +1331,9 @@ fn try_report_cannot_return_reference_to_local(
 
             // to avoid panics
             if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
-                if tcx
-                    .type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
+                if self
+                    .infcx
+                    .type_implements_trait(iter_trait, return_ty, ty_params, self.param_env)
                     .must_apply_modulo_regions()
                 {
                     if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
index bf5f2c0eec23edc8382fc0819410dd4811600948..671d947d1b1321f2ac7d1797e53e9914794520d3 100644 (file)
@@ -147,7 +147,7 @@ pub(crate) fn report_mutability_error(
                     if let Some(desc) = access_place_desc {
                         item_msg = format!("`{}`", desc);
                         reason = match error_access {
-                            AccessKind::Mutate => format!(" which is behind {}", pointer_type),
+                            AccessKind::Mutate => format!(", which is behind {}", pointer_type),
                             AccessKind::MutableBorrow => {
                                 format!(", as it is behind {}", pointer_type)
                             }
@@ -897,16 +897,32 @@ fn suggest_ampmut<'tcx>(
 ) -> (Span, String) {
     if let Some(assignment_rhs_span) = opt_assignment_rhs_span {
         if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) {
+            let is_mutbl = |ty: &str| -> bool {
+                if ty.starts_with("mut") {
+                    let rest = &ty[3..];
+                    match rest.chars().next() {
+                        // e.g. `&mut x`
+                        Some(c) if c.is_whitespace() => true,
+                        // e.g. `&mut(x)`
+                        Some('(') => true,
+                        // e.g. `&mutablevar`
+                        _ => false,
+                    }
+                } else {
+                    false
+                }
+            };
             if let (true, Some(ws_pos)) =
                 (src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() }))
             {
                 let lt_name = &src[1..ws_pos];
-                let ty = &src[ws_pos..];
-                if !ty.trim_start().starts_with("mut") {
+                let ty = src[ws_pos..].trim_start();
+                if !is_mutbl(ty) {
                     return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
                 }
             } else if let Some(stripped) = src.strip_prefix('&') {
-                if !stripped.trim_start().starts_with("mut") {
+                let stripped = stripped.trim_start();
+                if !is_mutbl(stripped) {
                     return (assignment_rhs_span, format!("&mut {}", stripped));
                 }
             }
index 7a7dbe50e72f9447f808b10bce25a734863e427c..c1c26d4e810d0727b08e2e48f48001d522a34ade 100644 (file)
@@ -98,7 +98,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
         tcx,
         root_span,
         param_env,
-        CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
+        CompileTimeInterpreter::new(tcx.const_eval_limit()),
         MemoryExtra { can_access_statics },
     )
 }
@@ -300,7 +300,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
         tcx,
         tcx.def_span(def.did),
         key.param_env,
-        CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
+        CompileTimeInterpreter::new(tcx.const_eval_limit()),
         // Statics (and promoteds inside statics) may access other statics, because unlike consts
         // they do not have to behave "as if" they were evaluated at runtime.
         MemoryExtra { can_access_statics: is_static },
index 992e32e298f8e60f5c50d64e033d4b436b7ac70f..279f414e7fef14667bfb4d6e08061ccb70cf2731 100644 (file)
@@ -393,7 +393,7 @@ fn init_frame_extra(
         frame: Frame<'mir, 'tcx>,
     ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
         // Enforce stack size limit. Add 1 because this is run before the new frame is pushed.
-        if !ecx.tcx.sess.recursion_limit().value_within_limit(ecx.stack().len() + 1) {
+        if !ecx.recursion_limit.value_within_limit(ecx.stack().len() + 1) {
             throw_exhaust!(StackFrameLimitReached)
         } else {
             Ok(frame)
index 801e4b1e47850c5f99e9f0c09645eb8c8daba9f3..648a7abfdc7b12c36d3e483fa8ab1d2e6d935848 100644 (file)
@@ -13,6 +13,7 @@
 use rustc_middle::ty::{
     self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
 };
+use rustc_session::Limit;
 use rustc_span::{Pos, Span};
 use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
 
@@ -39,6 +40,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
 
     /// The virtual memory system.
     pub memory: Memory<'mir, 'tcx, M>,
+
+    /// The recursion limit (cached from `tcx.recursion_limit(())`)
+    pub recursion_limit: Limit,
 }
 
 // The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
@@ -388,12 +392,17 @@ pub fn new(
             tcx: tcx.at(root_span),
             param_env,
             memory: Memory::new(tcx, memory_extra),
+            recursion_limit: tcx.recursion_limit(),
         }
     }
 
     #[inline(always)]
     pub fn cur_span(&self) -> Span {
-        self.stack().last().map_or(self.tcx.span, |f| f.current_span())
+        self.stack()
+            .iter()
+            .rev()
+            .find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
+            .map_or(self.tcx.span, |f| f.current_span())
     }
 
     #[inline(always)]
@@ -922,7 +931,12 @@ pub fn dump_place(&'a self, place: Place<M::PointerTag>) -> PlacePrinter<'a, 'mi
     #[must_use]
     pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
         let mut frames = Vec::new();
-        for frame in self.stack().iter().rev() {
+        for frame in self
+            .stack()
+            .iter()
+            .rev()
+            .skip_while(|frame| frame.instance.def.requires_caller_location(*self.tcx))
+        {
             let lint_root = frame.current_source_info().and_then(|source_info| {
                 match &frame.body.source_scopes[source_info.scope].local_data {
                     mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
index 4e4166dad50e29b83c7b49c00905fe344941f659..ad9cf3e7d2fe9b39ff56da6088261455cf60753c 100644 (file)
@@ -472,6 +472,10 @@ pub fn emulate_intrinsic(
                     throw_ub_format!("`assume` intrinsic called with `false`");
                 }
             }
+            sym::raw_eq => {
+                let result = self.raw_eq_intrinsic(&args[0], &args[1])?;
+                self.write_scalar(result, dest)?;
+            }
             _ => return Ok(false),
         }
 
@@ -559,4 +563,19 @@ pub(crate) fn copy_intrinsic(
 
         self.memory.copy(src, align, dst, align, size, nonoverlapping)
     }
+
+    pub(crate) fn raw_eq_intrinsic(
+        &mut self,
+        lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+        rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+    ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
+        let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?;
+        assert!(!layout.is_unsized());
+
+        let lhs = self.read_scalar(lhs)?.check_init()?;
+        let rhs = self.read_scalar(rhs)?.check_init()?;
+        let lhs_bytes = self.memory.read_bytes(lhs, layout.size)?;
+        let rhs_bytes = self.memory.read_bytes(rhs, layout.size)?;
+        Ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
+    }
 }
index 4bd431dcc6a3c5d8bf46ec512c4b8d3a667977b3..ced35d47b1102a1cb8489356bcfd1d8d39650caa 100644 (file)
 use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
 use rustc_session::config::EntryFnType;
 use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
+use rustc_session::Limit;
 use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
 use rustc_target::abi::Size;
 use smallvec::SmallVec;
@@ -294,6 +295,7 @@ pub fn collect_crate_mono_items(
 
     let mut visited = MTLock::new(FxHashSet::default());
     let mut inlining_map = MTLock::new(InliningMap::new());
+    let recursion_limit = tcx.recursion_limit();
 
     {
         let visited: MTRef<'_, _> = &mut visited;
@@ -307,6 +309,7 @@ pub fn collect_crate_mono_items(
                     dummy_spanned(root),
                     visited,
                     &mut recursion_depths,
+                    recursion_limit,
                     inlining_map,
                 );
             });
@@ -350,6 +353,7 @@ fn collect_items_rec<'tcx>(
     starting_point: Spanned<MonoItem<'tcx>>,
     visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
     recursion_depths: &mut DefIdMap<usize>,
+    recursion_limit: Limit,
     inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
 ) {
     if !visited.lock_mut().insert(starting_point.node) {
@@ -409,8 +413,13 @@ fn collect_items_rec<'tcx>(
             debug_assert!(should_codegen_locally(tcx, &instance));
 
             // Keep track of the monomorphization recursion depth
-            recursion_depth_reset =
-                Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths));
+            recursion_depth_reset = Some(check_recursion_limit(
+                tcx,
+                instance,
+                starting_point.span,
+                recursion_depths,
+                recursion_limit,
+            ));
             check_type_length_limit(tcx, instance);
 
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
@@ -455,7 +464,7 @@ fn collect_items_rec<'tcx>(
     record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
 
     for neighbour in neighbors {
-        collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map);
+        collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
     }
 
     if let Some((def_id, depth)) = recursion_depth_reset {
@@ -523,6 +532,7 @@ fn check_recursion_limit<'tcx>(
     instance: Instance<'tcx>,
     span: Span,
     recursion_depths: &mut DefIdMap<usize>,
+    recursion_limit: Limit,
 ) -> (DefId, usize) {
     let def_id = instance.def_id();
     let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
@@ -539,7 +549,7 @@ fn check_recursion_limit<'tcx>(
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
-    if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
+    if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
         let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
         let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
         let mut err = tcx.sess.struct_span_fatal(span, &error);
@@ -577,7 +587,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     // which means that rustc basically hangs.
     //
     // Bail out in these cases to avoid that bad user experience.
-    if !tcx.sess.type_length_limit().value_within_limit(type_length) {
+    if !tcx.type_length_limit().value_within_limit(type_length) {
         let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
         let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
         let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
@@ -814,7 +824,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
 
     fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
         self.super_operand(operand, location);
-        let limit = self.tcx.sess.move_size_limit();
+        let limit = self.tcx.move_size_limit().0;
         if limit == 0 {
             return;
         }
index dcbc9c523dc1946f55687f59f0b8281d4f8e5d9e..fd72ec4340f9f2a7f9c462c9039f3888998e70c2 100644 (file)
@@ -397,6 +397,9 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<
     }
 }
 
+/// Comparing raw pointers for equality.
+/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
+/// allocation base addresses that are not known at compile-time.
 #[derive(Debug)]
 pub struct RawPtrComparison;
 impl NonConstOp for RawPtrComparison {
@@ -430,20 +433,22 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<
     }
 }
 
+/// Casting raw pointer or function pointer to an integer.
+/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
+/// allocation base addresses that are not known at compile-time.
 #[derive(Debug)]
 pub struct RawPtrToIntCast;
 impl NonConstOp for RawPtrToIntCast {
-    fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
-        Status::Unstable(sym::const_raw_ptr_to_usize_cast)
-    }
-
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-        feature_err(
-            &ccx.tcx.sess.parse_sess,
-            sym::const_raw_ptr_to_usize_cast,
-            span,
-            &format!("casting pointers to integers in {}s is unstable", ccx.const_kind(),),
-        )
+        let mut err = ccx
+            .tcx
+            .sess
+            .struct_span_err(span, "pointers cannot be cast to integers during const eval.");
+        err.note("at compile-time, pointers do not have an integer value");
+        err.note(
+            "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior",
+        );
+        err
     }
 }
 
index 103ddda1a1d262c45069da1fab78d78404a7776b..1ff9bd157210874391deafc577a31eb4dd435c42 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_hir::Node;
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
@@ -18,7 +17,6 @@
 pub struct UnsafetyChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     body_did: LocalDefId,
-    const_context: bool,
     violations: Vec<UnsafetyViolation>,
     source_info: SourceInfo,
     tcx: TyCtxt<'tcx>,
@@ -30,7 +28,6 @@ pub struct UnsafetyChecker<'a, 'tcx> {
 
 impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn new(
-        const_context: bool,
         body: &'a Body<'tcx>,
         body_did: LocalDefId,
         tcx: TyCtxt<'tcx>,
@@ -39,7 +36,6 @@ fn new(
         Self {
             body,
             body_did,
-            const_context,
             violations: vec![],
             source_info: SourceInfo::outermost(body.span),
             tcx,
@@ -136,25 +132,6 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                     self.register_violations(&violations, &unsafe_blocks);
                 }
             },
-            // casting pointers to ints is unsafe in const fn because the const evaluator cannot
-            // possibly know what the result of various operations like `address / 2` would be
-            // pointers during const evaluation have no integral address, only an abstract one
-            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty)
-                if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast =>
-            {
-                let operand_ty = operand.ty(self.body, self.tcx);
-                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
-                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-                match (cast_in, cast_out) {
-                    (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
-                        self.require_unsafe(
-                            UnsafetyViolationKind::General,
-                            UnsafetyViolationDetails::CastOfPointerToInt,
-                        );
-                    }
-                    _ => {}
-                }
-            }
             _ => {}
         }
         self.super_rvalue(rvalue, location);
@@ -469,13 +446,7 @@ fn unsafety_check_result<'tcx>(
 
     let param_env = tcx.param_env(def.did);
 
-    let id = tcx.hir().local_def_id_to_hir_id(def.did);
-    let const_context = match tcx.hir().body_owner_kind(id) {
-        hir::BodyOwnerKind::Closure => false,
-        hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
-        hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
-    };
-    let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env);
+    let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
     check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks);
index f62171b3c535c757fe25accb398462dfa7bce5b3..08cc87ccc349d5c51068e5203bb3b0c710c64675 100644 (file)
@@ -184,11 +184,8 @@ pub fn current_macro(&self) -> Option<Symbol> {
         self.current_macro_or_none
             .borrow_mut()
             .get_or_insert_with(|| {
-                if let ExpnKind::Macro {
-                    kind: MacroKind::Bang,
-                    name: current_macro,
-                    proc_macro: _,
-                } = self.expn_span.ctxt().outer_expn_data().kind
+                if let ExpnKind::Macro(MacroKind::Bang, current_macro) =
+                    self.expn_span.ctxt().outer_expn_data().kind
                 {
                     return Some(current_macro);
                 }
index b04c2d542d459fda4a9b5aa30f1e0208b65bede1..e5b3059a5995fee80d77c0a50a7e4bfc45e66bf6 100644 (file)
@@ -22,7 +22,7 @@
 //! are unrelated to the `TyCtxt` global. Without initializing the `Span` session globals, some
 //! basic, coverage-specific features would be impossible to test, but thankfully initializing these
 //! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument
-//! to: `rustc_span::with_default_session_globals(|| { test_here(); })`.
+//! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
 
 use super::counters;
 use super::debug;
@@ -677,7 +677,7 @@ fn synthesize_body_span_from_terminators(mir_body: &Body<'_>) -> Span {
 
 #[test]
 fn test_make_bcb_counters() {
-    rustc_span::with_default_session_globals(|| {
+    rustc_span::create_default_session_globals_then(|| {
         let mir_body = goto_switchint();
         let body_span = synthesize_body_span_from_terminators(&mir_body);
         let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
index f1c95a84ade85a04800a9af36440ba28429fbe6d..703ac39dc30802c606e73d774d8e8bb8ec4b448c 100644 (file)
@@ -284,7 +284,7 @@ fn check_codegen_attributes(
         &self,
         callsite: &CallSite<'tcx>,
         callee_attrs: &CodegenFnAttrs,
-    ) -> Result<(), &'satic str> {
+    ) -> Result<(), &'static str> {
         if let InlineAttr::Never = callee_attrs.inline {
             return Err("never inline hint");
         }
@@ -836,7 +836,7 @@ fn visit_source_scope(&mut self, scope: &mut SourceScope) {
 
     fn visit_span(&mut self, span: &mut Span) {
         let mut expn_data =
-            ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None);
+            ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None, None);
         expn_data.def_site = self.body_span;
         // Make sure that all spans track the fact that they were inlined.
         *span = self.callsite_span.fresh_expansion(expn_data);
index 295f3ec70dc7837ec008c85f9778d3941cba574d..c9eafafff57cd2f6f76f758dfa2d34faa483acf3 100644 (file)
@@ -5,6 +5,7 @@
 use rustc_middle::mir::TerminatorKind;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
+use rustc_session::Limit;
 
 // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
 // this query riddiculously often.
@@ -30,7 +31,7 @@
     );
     #[instrument(
         level = "debug",
-        skip(tcx, param_env, target, stack, seen, recursion_limiter, caller)
+        skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
     )]
     fn process(
         tcx: TyCtxt<'tcx>,
@@ -40,6 +41,7 @@ fn process(
         stack: &mut Vec<ty::Instance<'tcx>>,
         seen: &mut FxHashSet<ty::Instance<'tcx>>,
         recursion_limiter: &mut FxHashMap<DefId, usize>,
+        recursion_limit: Limit,
     ) -> bool {
         trace!(%caller);
         for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
@@ -96,11 +98,20 @@ fn process(
             if seen.insert(callee) {
                 let recursion = recursion_limiter.entry(callee.def_id()).or_default();
                 trace!(?callee, recursion = *recursion);
-                if tcx.sess.recursion_limit().value_within_limit(*recursion) {
+                if recursion_limit.value_within_limit(*recursion) {
                     *recursion += 1;
                     stack.push(callee);
                     let found_recursion = ensure_sufficient_stack(|| {
-                        process(tcx, param_env, callee, target, stack, seen, recursion_limiter)
+                        process(
+                            tcx,
+                            param_env,
+                            callee,
+                            target,
+                            stack,
+                            seen,
+                            recursion_limiter,
+                            recursion_limit,
+                        )
                     });
                     if found_recursion {
                         return true;
@@ -122,6 +133,7 @@ fn process(
         &mut Vec::new(),
         &mut FxHashSet::default(),
         &mut FxHashMap::default(),
+        tcx.recursion_limit(),
     )
 }
 
index 9bef8ac2413d6aa3027c8b6eaab4ef1566ffb0c0..38111527a4ec719e133138452ad4eea2247238a5 100644 (file)
@@ -25,7 +25,8 @@ struct UnsafetyVisitor<'a, 'tcx> {
     /// The `#[target_feature]` attributes of the body. Used for checking
     /// calls to functions with `#[target_feature]` (RFC 2396).
     body_target_features: &'tcx Vec<Symbol>,
-    is_const: bool,
+    in_possible_lhs_union_assign: bool,
+    in_union_destructure: bool,
 }
 
 impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -158,14 +159,115 @@ fn visit_block(&mut self, block: &Block) {
         }
     }
 
+    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+        use PatKind::*;
+
+        if self.in_union_destructure {
+            match *pat.kind {
+                // binding to a variable allows getting stuff out of variable
+                Binding { .. }
+                // match is conditional on having this value
+                | Constant { .. }
+                | Variant { .. }
+                | Leaf { .. }
+                | Deref { .. }
+                | Range { .. }
+                | Slice { .. }
+                | Array { .. } => {
+                    self.requires_unsafe(pat.span, AccessToUnionField);
+                    return; // don't walk pattern
+                }
+                // wildcard doesn't take anything
+                Wild |
+                // these just wrap other patterns
+                Or { .. } |
+                AscribeUserType { .. } => {}
+            }
+        };
+
+        if let ty::Adt(adt_def, _) = pat.ty.kind() {
+            // check for extracting values from union via destructuring
+            if adt_def.is_union() {
+                match *pat.kind {
+                    // assigning the whole union is okay
+                    // let x = Union { ... };
+                    // let y = x; // safe
+                    Binding { .. } |
+                    // binding to wildcard is okay since that never reads anything and stops double errors
+                    // with implict wildcard branches from `if let`s
+                    Wild |
+                    // doesn't have any effect on semantics
+                    AscribeUserType { .. } |
+                    // creating a union literal
+                    Constant { .. } => {},
+                    Leaf { .. } | Or { .. } => {
+                        // pattern matching with a union and not doing something like v = Union { bar: 5 }
+                        self.in_union_destructure = true;
+                        visit::walk_pat(self, pat);
+                        self.in_union_destructure = false;
+                        return; // don't walk pattern
+                    }
+                    Variant { .. } | Deref { .. } | Range { .. } | Slice { .. } | Array { .. } =>
+                        unreachable!("impossible union destructuring type"),
+                }
+            }
+        }
+
+        visit::walk_pat(self, pat);
+    }
+
     fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+        // could we be in a the LHS of an assignment of a union?
+        match expr.kind {
+            ExprKind::Field { .. }
+            | ExprKind::VarRef { .. }
+            | ExprKind::UpvarRef { .. }
+            | ExprKind::Scope { .. }
+            | ExprKind::Cast { .. } => {}
+
+            ExprKind::AddressOf { .. }
+            | ExprKind::Adt { .. }
+            | ExprKind::Array { .. }
+            | ExprKind::Binary { .. }
+            | ExprKind::Block { .. }
+            | ExprKind::Borrow { .. }
+            | ExprKind::Literal { .. }
+            | ExprKind::ConstBlock { .. }
+            | ExprKind::Deref { .. }
+            | ExprKind::Index { .. }
+            | ExprKind::NeverToAny { .. }
+            | ExprKind::PlaceTypeAscription { .. }
+            | ExprKind::ValueTypeAscription { .. }
+            | ExprKind::Pointer { .. }
+            | ExprKind::Repeat { .. }
+            | ExprKind::StaticRef { .. }
+            | ExprKind::ThreadLocalRef { .. }
+            | ExprKind::Tuple { .. }
+            | ExprKind::Unary { .. }
+            | ExprKind::Call { .. }
+            | ExprKind::Assign { .. }
+            | ExprKind::AssignOp { .. }
+            | ExprKind::Break { .. }
+            | ExprKind::Closure { .. }
+            | ExprKind::Continue { .. }
+            | ExprKind::Return { .. }
+            | ExprKind::Yield { .. }
+            | ExprKind::Loop { .. }
+            | ExprKind::Match { .. }
+            | ExprKind::Box { .. }
+            | ExprKind::If { .. }
+            | ExprKind::InlineAsm { .. }
+            | ExprKind::LlvmInlineAsm { .. }
+            | ExprKind::LogicalOp { .. }
+            | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false,
+        };
         match expr.kind {
             ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => {
                 let prev_id = self.hir_context;
                 self.hir_context = hir_id;
                 self.visit_expr(&self.thir[value]);
                 self.hir_context = prev_id;
-                return;
+                return; // don't visit the whole expression
             }
             ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
                 if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
@@ -212,16 +314,6 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 (Bound::Unbounded, Bound::Unbounded) => {}
                 _ => self.requires_unsafe(expr.span, InitializingTypeWith),
             },
-            ExprKind::Cast { source } => {
-                let source = &self.thir[source];
-                if self.tcx.features().const_raw_ptr_to_usize_cast
-                    && self.is_const
-                    && (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr())
-                    && expr.ty.is_integral()
-                {
-                    self.requires_unsafe(expr.span, CastOfPointerToInt);
-                }
-            }
             ExprKind::Closure {
                 closure_id,
                 substs: _,
@@ -246,9 +338,29 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 // Unsafe blocks can be used in closures, make sure to take it into account
                 self.safety_context = closure_visitor.safety_context;
             }
+            ExprKind::Field { lhs, .. } => {
+                // assigning to union field is okay for AccessToUnionField
+                if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() {
+                    if adt_def.is_union() {
+                        if self.in_possible_lhs_union_assign {
+                            // FIXME: trigger AssignToDroppingUnionField unsafety if needed
+                        } else {
+                            self.requires_unsafe(expr.span, AccessToUnionField);
+                        }
+                    }
+                }
+            }
+            // don't have any special handling for AssignOp since it causes a read *and* write to lhs
+            ExprKind::Assign { lhs, rhs } => {
+                // assigning to a union is safe, check here so it doesn't get treated as a read later
+                self.in_possible_lhs_union_assign = true;
+                visit::walk_expr(self, &self.thir()[lhs]);
+                self.in_possible_lhs_union_assign = false;
+                visit::walk_expr(self, &self.thir()[rhs]);
+                return; // don't visit the whole expression
+            }
             _ => {}
         }
-
         visit::walk_expr(self, expr);
     }
 }
@@ -290,13 +402,11 @@ enum UnsafeOpKind {
     CallToUnsafeFunction,
     UseOfInlineAssembly,
     InitializingTypeWith,
-    CastOfPointerToInt,
     UseOfMutableStatic,
     UseOfExternStatic,
     DerefOfRawPointer,
     #[allow(dead_code)] // FIXME
     AssignToDroppingUnionField,
-    #[allow(dead_code)] // FIXME
     AccessToUnionField,
     #[allow(dead_code)] // FIXME
     MutationOfLayoutConstrainedField,
@@ -324,9 +434,6 @@ pub fn description_and_note(&self) -> (&'static str, &'static str) {
                 "initializing a layout restricted type's field with a value outside the valid \
                  range is undefined behavior",
             ),
-            CastOfPointerToInt => {
-                ("cast of pointer to int", "casting pointers to integers in constants")
-            }
             UseOfMutableStatic => (
                 "use of mutable static",
                 "mutable statics can be mutated by multiple threads: aliasing violations or data \
@@ -404,11 +511,6 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
     let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
     let safety_context =
         if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
-    let is_const = match tcx.hir().body_owner_kind(hir_id) {
-        hir::BodyOwnerKind::Closure => false,
-        hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
-        hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
-    };
     let mut visitor = UnsafetyVisitor {
         tcx,
         thir,
@@ -416,7 +518,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         hir_context: hir_id,
         body_unsafety,
         body_target_features,
-        is_const,
+        in_possible_lhs_union_assign: false,
+        in_union_destructure: false,
     };
     visitor.visit_expr(&thir[expr]);
 }
index 369fff00456a79421e123c81bc41ae7acaf2c9f2..cb9c89324d6b3098b6b854dc0bd34914497b530c 100644 (file)
@@ -272,12 +272,14 @@ fn recur(
 
         let kind = match cv.ty.kind() {
             ty::Float(_) => {
-                tcx.struct_span_lint_hir(
-                    lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-                    id,
-                    span,
-                    |lint| lint.build("floating-point types cannot be used in patterns").emit(),
-                );
+                if self.include_lint_checks {
+                    tcx.struct_span_lint_hir(
+                        lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                        id,
+                        span,
+                        |lint| lint.build("floating-point types cannot be used in patterns").emit(),
+                    );
+                }
                 PatKind::Constant { value: cv }
             }
             ty::Adt(adt_def, _) if adt_def.is_union() => {
index f611bb6eb43e9e52bddad01bbd7a41e6136b4840..ce5d4362c086ccb9f9bee5e94683e520322c21b2 100644 (file)
@@ -153,8 +153,8 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
 }
 
 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
-    match stmt.kind {
-        StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
+    match &stmt.kind {
+        StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
         StmtKind::Let {
             initializer,
             remainder_scope: _,
@@ -163,7 +163,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
             lint_level: _,
         } => {
             if let Some(init) = initializer {
-                visitor.visit_expr(&visitor.thir()[init]);
+                visitor.visit_expr(&visitor.thir()[*init]);
             }
             visitor.visit_pat(pattern);
         }
index 87e60a48e4457430c2787014611412e937e658c5..98befe4066bc57a334d124bf13845855e222517a 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
-use rustc_session::lint::builtin::RESERVED_PREFIX;
+use rustc_session::lint::builtin::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{sym, Symbol};
@@ -526,7 +526,7 @@ fn report_unknown_prefix(&self, start: BytePos) {
         } else {
             // Before Rust 2021, only emit a lint for migration.
             self.sess.buffer_lint_with_diagnostic(
-                &RESERVED_PREFIX,
+                &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
                 &msg,
index 2daa9e2485b1b7a02de77e9bb064ccdc8d068759..2ce63d011f438b07467fa8726c55e02610e55e90 100644 (file)
@@ -1791,7 +1791,13 @@ pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
                     if self.check_keyword(kw::Pub) {
                         let sp = sp_start.to(self.prev_token.span);
                         if let Ok(snippet) = self.span_to_snippet(sp) {
-                            let vis = self.parse_visibility(FollowedByType::No)?;
+                            let vis = match self.parse_visibility(FollowedByType::No) {
+                                Ok(v) => v,
+                                Err(mut d) => {
+                                    d.cancel();
+                                    return Err(err);
+                                }
+                            };
                             let vs = pprust::vis_to_string(&vis);
                             let vs = vs.trim_end();
                             err.span_suggestion(
index 418122202be1b187e9e356ee0f96005ae7d7f328..566677d032aff9d3d64e963bcfb4d083245b73cc 100644 (file)
@@ -715,7 +715,6 @@ fn parse_range_end(&mut self) -> Option<Spanned<RangeEnd>> {
         } else if self.eat(&token::DotDotEq) {
             RangeEnd::Included(RangeSyntax::DotDotEq)
         } else if self.eat(&token::DotDot) {
-            self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_token.span);
             RangeEnd::Excluded
         } else {
             return None;
@@ -735,7 +734,6 @@ fn parse_pat_range_begin_with(
             Some(self.parse_pat_range_end()?)
         } else {
             // Parsing e.g. `X..`.
-            self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span));
             if let RangeEnd::Included(_) = re.node {
                 // FIXME(Centril): Consider semantic errors instead in `ast_validation`.
                 // Possibly also do this for `X..=` in *expression* contexts.
index de5a5632600e4ee39a1f6c0dd90d01f92fb5ed46..1fbf01b1b97d55ad5b3e300a2f1498d2fd7c3791 100644 (file)
@@ -393,7 +393,7 @@ fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         let and_span = self.prev_token.span;
         let mut opt_lifetime =
             if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
-        let mutbl = self.parse_mutability();
+        let mut mutbl = self.parse_mutability();
         if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
             // A lifetime is invalid here: it would be part of a bare trait bound, which requires
             // it to be followed by a plus, but we disallow plus in the pointee type.
@@ -417,6 +417,26 @@ fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
 
                 opt_lifetime = Some(self.expect_lifetime());
             }
+        } else if self.token.is_keyword(kw::Dyn)
+            && mutbl == Mutability::Not
+            && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
+        {
+            // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
+            let span = and_span.to(self.look_ahead(1, |t| t.span));
+            let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
+            err.span_suggestion(
+                span,
+                "place `mut` before `dyn`",
+                "&mut dyn".to_string(),
+                Applicability::MachineApplicable,
+            );
+            err.emit();
+
+            // Recovery
+            mutbl = Mutability::Mut;
+            let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
+            self.bump();
+            self.bump_with((dyn_tok, dyn_tok_sp));
         }
         let ty = self.parse_ty_no_plus()?;
         Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
index 9fd0497fffee59519dada7ac76c3e491396aad3b..b7693a85ad955a0365c91ffbe42829a1eabf3aff 100644 (file)
@@ -144,8 +144,7 @@ fn format_align_fill() {
 }
 #[test]
 fn format_counts() {
-    use rustc_span::{edition, SessionGlobals, SESSION_GLOBALS};
-    SESSION_GLOBALS.set(&SessionGlobals::new(edition::DEFAULT_EDITION), || {
+    rustc_span::create_default_session_globals_then(|| {
         same(
             "{:10x}",
             &[NextArgument(Argument {
index 34ea5e9abd4d522447097f9efee9c43223d60931..550f4f148fd24abc74d07c4280a6e1ebb044a8a4 100644 (file)
@@ -147,33 +147,36 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
         Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Start))
     } else if let Some((hir_id, _)) = visitor.attr_main_fn {
         Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main))
-    } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) {
-        // non-local main imports are handled below
-        if def_id.is_local() {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-            if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) {
-                tcx.sess
-                    .struct_span_err(
-                        tcx.hir().span(hir_id),
-                        "the `main` function cannot be declared in an `extern` block",
+    } else {
+        if let Some(main_def) = tcx.resolutions(()).main_def {
+            if let Some(def_id) = main_def.opt_fn_def_id() {
+                // non-local main imports are handled below
+                if def_id.is_local() {
+                    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+                    if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) {
+                        tcx.sess
+                            .struct_span_err(
+                                tcx.hir().span(hir_id),
+                                "the `main` function cannot be declared in an `extern` block",
+                            )
+                            .emit();
+                        return None;
+                    }
+                }
+
+                if main_def.is_import && !tcx.features().imported_main {
+                    let span = main_def.span;
+                    feature_err(
+                        &tcx.sess.parse_sess,
+                        sym::imported_main,
+                        span,
+                        "using an imported function as entry point `main` is experimental",
                     )
                     .emit();
-                return None;
+                }
+                return Some((def_id, EntryFnType::Main));
             }
         }
-
-        if tcx.main_def.unwrap().is_import && !tcx.features().imported_main {
-            let span = tcx.main_def.unwrap().span;
-            feature_err(
-                &tcx.sess.parse_sess,
-                sym::imported_main,
-                span,
-                "using an imported function as entry point `main` is experimental",
-            )
-            .emit();
-        }
-        Some((def_id, EntryFnType::Main))
-    } else {
         no_main_err(tcx, visitor);
         None
     }
@@ -223,7 +226,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
         err.note(&note);
     }
 
-    if let Some(main_def) = tcx.main_def {
+    if let Some(main_def) = tcx.resolutions(()).main_def {
         if main_def.opt_fn_def_id().is_none() {
             // There is something at `crate::main`, but it is not a function definition.
             err.span_label(main_def.span, &format!("non-function item at `crate::main` is found"));
index d8abffc5f64009c06468b91792e902999edd2795..3a88d1932a80a7460e29c18ffca9461ec3d98051 100644 (file)
@@ -257,9 +257,6 @@ fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span
             | LangItem::Unpin
             | LangItem::Termination
             | LangItem::Try
-            | LangItem::Send
-            | LangItem::UnwindSafe
-            | LangItem::RefUnwindSafe
                 => Some(0),
 
             // Not a trait
index 5830245e837e46d7ac608f0d0a0efd388e56f76c..42a4753c29c9b325b9f0a3585db951f35cff55db 100644 (file)
@@ -20,6 +20,7 @@
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::abi::Abi;
 
 use std::cmp::Ordering;
 use std::iter;
@@ -95,10 +96,12 @@ struct Annotator<'a, 'tcx> {
 impl<'a, 'tcx> Annotator<'a, 'tcx> {
     // Determine the stability for a node based on its attributes and inherited
     // stability. The stability is recorded in the index and used as the parent.
+    // If the node is a function, `fn_sig` is its signature
     fn annotate<F>(
         &mut self,
         hir_id: HirId,
         item_sp: Span,
+        fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
         kind: AnnotationKind,
         inherit_deprecation: InheritDeprecation,
         inherit_const_stability: InheritConstStability,
@@ -163,13 +166,30 @@ fn annotate<F>(
         }
 
         let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
+        let mut const_span = None;
 
-        let const_stab = const_stab.map(|(const_stab, _)| {
+        let const_stab = const_stab.map(|(const_stab, const_span_node)| {
             let const_stab = self.tcx.intern_const_stability(const_stab);
             self.index.const_stab_map.insert(hir_id, const_stab);
+            const_span = Some(const_span_node);
             const_stab
         });
 
+        // If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
+        // check if the function/method is const or the parent impl block is const
+        if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) {
+            if fn_sig.header.abi != Abi::RustIntrinsic
+                && fn_sig.header.abi != Abi::PlatformIntrinsic
+                && !fn_sig.header.is_const()
+            {
+                if !self.in_trait_impl
+                    || (self.in_trait_impl && !self.tcx.is_const_fn_raw(hir_id.owner.to_def_id()))
+                {
+                    missing_const_err(&self.tcx.sess, fn_sig.span, const_span);
+                }
+            }
+        }
+
         // `impl const Trait for Type` items forward their const stability to their
         // immediate children.
         if const_stab.is_none() {
@@ -367,6 +387,8 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
         let orig_in_trait_impl = self.in_trait_impl;
         let mut kind = AnnotationKind::Required;
         let mut const_stab_inherit = InheritConstStability::No;
+        let mut fn_sig = None;
+
         match i.kind {
             // Inherent impls and foreign modules serve only as containers for other items,
             // they don't have their own stability. They still can be annotated as unstable
@@ -387,6 +409,7 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
                     self.annotate(
                         ctor_hir_id,
                         i.span,
+                        None,
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
@@ -395,12 +418,16 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
                     )
                 }
             }
+            hir::ItemKind::Fn(ref item_fn_sig, _, _) => {
+                fn_sig = Some(item_fn_sig);
+            }
             _ => {}
         }
 
         self.annotate(
             i.hir_id(),
             i.span,
+            fn_sig,
             kind,
             InheritDeprecation::Yes,
             const_stab_inherit,
@@ -411,9 +438,15 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
     }
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
+        let fn_sig = match ti.kind {
+            hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
+            _ => None,
+        };
+
         self.annotate(
             ti.hir_id(),
             ti.span,
+            fn_sig,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -427,9 +460,16 @@ fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
         let kind =
             if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
+
+        let fn_sig = match ii.kind {
+            hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
+            _ => None,
+        };
+
         self.annotate(
             ii.hir_id(),
             ii.span,
+            fn_sig,
             kind,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -444,6 +484,7 @@ fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, i
         self.annotate(
             var.id,
             var.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -453,6 +494,7 @@ fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, i
                     v.annotate(
                         ctor_hir_id,
                         var.span,
+                        None,
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
@@ -470,6 +512,7 @@ fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
         self.annotate(
             s.hir_id,
             s.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -484,6 +527,7 @@ fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
         self.annotate(
             i.hir_id(),
             i.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -498,6 +542,7 @@ fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
         self.annotate(
             md.hir_id(),
             md.span,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -517,6 +562,7 @@ fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
         self.annotate(
             p.hir_id,
             p.span,
+            None,
             kind,
             InheritDeprecation::No,
             InheritConstStability::No,
@@ -687,6 +733,7 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
         annotator.annotate(
             hir::CRATE_HIR_ID,
             krate.item.inner,
+            None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -828,7 +875,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
     fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
         if let Some(def_id) = path.res.opt_def_id() {
-            self.tcx.check_stability(def_id, Some(id), path.span, None)
+            let method_span = path.segments.last().map(|s| s.ident.span);
+            self.tcx.check_stability(def_id, Some(id), path.span, method_span)
         }
         intravisit::walk_path(self, path)
     }
@@ -969,3 +1017,15 @@ fn duplicate_feature_err(sess: &Session, span: Span, feature: Symbol) {
     struct_span_err!(sess, span, E0636, "the feature `{}` has already been declared", feature)
         .emit();
 }
+
+fn missing_const_err(session: &Session, fn_sig_span: Span, const_span: Span) {
+    const ERROR_MSG: &'static str = "attributes `#[rustc_const_unstable]` \
+         and `#[rustc_const_stable]` require \
+         the function or method to be `const`";
+
+    session
+        .struct_span_err(fn_sig_span, ERROR_MSG)
+        .span_help(fn_sig_span, "make the function or method const")
+        .span_label(const_span, "attribute specified here")
+        .emit();
+}
index 5a79a9cc6ecfd1ffe1e4a1a4ca4a5439392b4f3b..d969f50c1d9185b7f5eb7af1c06e7f3450b3660a 100644 (file)
@@ -2031,7 +2031,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility {
     let def_id = def_id.expect_local();
-    match tcx.visibilities.get(&def_id) {
+    match tcx.resolutions(()).visibilities.get(&def_id) {
         Some(vis) => *vis,
         None => {
             let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
index e877034bd7b5b28d9a2ebd91900f4f6618000077..fa48df3ed45c63e2ba1fe338de8e8f2dae996155 100644 (file)
@@ -108,7 +108,7 @@ pub fn print_stats(tcx: TyCtxt<'_>) {
         queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect();
     def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap());
     eprintln!("\nLocal DefId density:");
-    let total = tcx.hir().definitions().def_index_count() as f64;
+    let total = tcx.resolutions(()).definitions.def_index_count() as f64;
     for q in def_id_density.iter().rev() {
         let local = q.local_def_id_keys.unwrap();
         eprintln!("   {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total);
index e10314a11fc1bbacd6e83a378f10aecc774fb686..f91bf0cbab727f45ad59489197d1871638f3f2bc 100644 (file)
@@ -159,6 +159,10 @@ pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
             Some(def_id) => def_id,
             None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root),
         };
+        self.macro_def_scope_from_def_id(def_id)
+    }
+
+    crate fn macro_def_scope_from_def_id(&mut self, def_id: DefId) -> Module<'a> {
         if let Some(id) = def_id.as_local() {
             self.local_macro_def_scopes[&id]
         } else {
index 83e904eb16b30d7c98a53441968c0d92db8eafa8..bcdae1cb43dbdfd8804643b4803e5f514561f48c 100644 (file)
@@ -1221,7 +1221,7 @@ pub fn new(
         let mut module_map = FxHashMap::default();
         module_map.insert(root_local_def_id, graph_root);
 
-        let definitions = Definitions::new(crate_name, session.local_crate_disambiguator());
+        let definitions = Definitions::new(session.local_stable_crate_id());
         let root = definitions.get_root_def();
 
         let mut visibilities = FxHashMap::default();
@@ -1775,11 +1775,9 @@ fn visit_scopes<T>(
                     let expn_data = expn_id.expn_data();
                     match expn_data.kind {
                         ExpnKind::Root
-                        | ExpnKind::Macro {
-                            kind: MacroKind::Bang | MacroKind::Derive,
-                            name: _,
-                            proc_macro: _,
-                        } => Scope::DeriveHelpersCompat,
+                        | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
+                            Scope::DeriveHelpersCompat
+                        }
                         _ => Scope::DeriveHelpers(expn_data.parent),
                     }
                 }
index 38d052f988c63fefa192da601a8ef0507bf09d2c..e024ade7b3c844a383df7e957ebf3b7efb115a52 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
 use rustc_feature::is_builtin_attr_name;
 use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc_hir::def_id::{self, CrateNum};
+use rustc_hir::def_id::{CrateNum, LocalDefId};
 use rustc_hir::PrimTy;
 use rustc_middle::middle::stability;
 use rustc_middle::ty;
@@ -217,26 +217,20 @@ fn expansion_for_ast_pass(
         features: &[Symbol],
         parent_module_id: Option<NodeId>,
     ) -> ExpnId {
+        let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id));
         let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable(
             ExpnKind::AstPass(pass),
             call_site,
             self.session.edition(),
             features.into(),
             None,
+            parent_module.map(LocalDefId::to_def_id),
         )));
 
-        let parent_scope = if let Some(module_id) = parent_module_id {
-            let parent_def_id = self.local_def_id(module_id);
-            self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id.to_def_id());
-            self.module_map[&parent_def_id]
-        } else {
-            self.definitions.add_parent_module_of_macro_def(
-                expn_id,
-                def_id::DefId::local(def_id::CRATE_DEF_INDEX),
-            );
-            self.empty_module
-        };
+        let parent_scope = parent_module
+            .map_or(self.empty_module, |parent_def_id| self.module_map[&parent_def_id]);
         self.ast_transform_scopes.insert(expn_id, parent_scope);
+
         expn_id
     }
 
@@ -298,12 +292,12 @@ fn resolve_macro_invocation(
             span,
             fast_print_path(path),
             res.opt_def_id(),
+            res.opt_def_id().map(|macro_def_id| {
+                self.macro_def_scope_from_def_id(macro_def_id).nearest_parent_mod
+            }),
         ));
 
         if let Res::Def(_, _) = res {
-            let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod;
-            self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
-
             // Gate macro attributes in `#[derive]` output.
             if !self.session.features_untracked().macro_attributes_in_derive_output
                 && kind == MacroKind::Attr
@@ -325,11 +319,7 @@ fn resolve_macro_invocation(
                         let expn_data = expn_id.expn_data();
                         match expn_data.kind {
                             ExpnKind::Root
-                            | ExpnKind::Macro {
-                                name: _,
-                                kind: MacroKind::Bang | MacroKind::Derive,
-                                proc_macro: _,
-                            } => {
+                            | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
                                 break;
                             }
                             _ => expn_id = expn_data.parent,
index 54b6a1215858153f3924214e466085eff3817aae..842f7f9deee38ed3e887a922be597154188857e6 100644 (file)
@@ -142,12 +142,7 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &hir::Crate<'_>) {
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
                 name: name.into(),
-                disambiguator: self
-                    .tcx
-                    .sess
-                    .local_crate_disambiguator()
-                    .to_fingerprint()
-                    .as_value(),
+                disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
index 4c3cd67ddc6efaa696b14c70a4c352b3507d3f20..0a8a88132e33de65849e710a2d069da135a1c5d6 100644 (file)
@@ -127,7 +127,10 @@ pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
                 num: n.as_u32(),
                 id: GlobalCrateId {
                     name: self.tcx.crate_name(n).to_string(),
-                    disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(),
+                    disambiguator: (
+                        self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(),
+                        0,
+                    ),
                 },
             });
         }
@@ -785,7 +788,7 @@ fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
         let callee = span.source_callee()?;
 
         let mac_name = match callee.kind {
-            ExpnKind::Macro { kind, name, proc_macro: _ } => match kind {
+            ExpnKind::Macro(kind, name) => match kind {
                 MacroKind::Bang => name,
 
                 // Ignore attribute macros, their spans are usually mangled
index 8d00a9a959e7a2c8d0577eeeba57790230ccc956..9a82ae3fc109080d4ae4c652fdd353c81ae7ce49 100644 (file)
@@ -24,3 +24,8 @@
 pub mod output;
 
 pub use getopts;
+
+/// Requirements for a `StableHashingContext` to be used in this crate.
+/// This is a hack to allow using the `HashStable_Generic` derive macro
+/// instead of implementing everything in `rustc_middle`.
+pub trait HashStableContext {}
index f792e319867792eac94c2dc63501ff2750e6ba98..8270bbbe8fd8001f15ac94b3bb0eedcc1eeb3eb8 100644 (file)
@@ -22,7 +22,8 @@
 use rustc_errors::registry::Registry;
 use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
 use rustc_lint_defs::FutureBreakage;
-pub use rustc_span::crate_disambiguator::CrateDisambiguator;
+use rustc_macros::HashStable_Generic;
+pub use rustc_span::def_id::StableCrateId;
 use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
 use rustc_span::{edition::Edition, RealFileName};
 use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
@@ -66,7 +67,7 @@ pub enum CtfeBacktrace {
 
 /// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
 /// limits are consistent throughout the compiler.
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
 pub struct Limit(pub usize);
 
 impl Limit {
@@ -111,6 +112,20 @@ fn mul(self, rhs: usize) -> Self::Output {
     }
 }
 
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
+pub struct Limits {
+    /// The maximum recursion limit for potentially infinitely recursive
+    /// operations such as auto-dereference and monomorphization.
+    pub recursion_limit: Limit,
+    /// The size at which the `large_assignments` lint starts
+    /// being emitted.
+    pub move_size_limit: Limit,
+    /// The maximum length of types during monomorphization.
+    pub type_length_limit: Limit,
+    /// The maximum blocks a const expression can evaluate.
+    pub const_eval_limit: Limit,
+}
+
 /// Represents the data associated with a compilation
 /// session for a single crate.
 pub struct Session {
@@ -133,31 +148,17 @@ pub struct Session {
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     crate_types: OnceCell<Vec<CrateType>>,
-    /// The `crate_disambiguator` is constructed out of all the `-C metadata`
-    /// arguments passed to the compiler. Its value together with the crate-name
-    /// forms a unique global identifier for the crate. It is used to allow
-    /// multiple crates with the same name to coexist. See the
+    /// The `stable_crate_id` is constructed out of the crate name and all the
+    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
+    /// global identifier for the crate. It is used to allow multiple crates
+    /// with the same name to coexist. See the
     /// `rustc_codegen_llvm::back::symbol_names` module for more information.
-    pub crate_disambiguator: OnceCell<CrateDisambiguator>,
+    pub stable_crate_id: OnceCell<StableCrateId>,
 
     features: OnceCell<rustc_feature::Features>,
 
     lint_store: OnceCell<Lrc<dyn SessionLintStore>>,
 
-    /// The maximum recursion limit for potentially infinitely recursive
-    /// operations such as auto-dereference and monomorphization.
-    pub recursion_limit: OnceCell<Limit>,
-
-    /// The size at which the `large_assignments` lint starts
-    /// being emitted.
-    pub move_size_limit: OnceCell<usize>,
-
-    /// The maximum length of types during monomorphization.
-    pub type_length_limit: OnceCell<Limit>,
-
-    /// The maximum blocks a const expression can evaluate.
-    pub const_eval_limit: OnceCell<Limit>,
-
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
     /// Used for incremental compilation tests. Will only be populated if
     /// `-Zquery-dep-graph` is specified.
@@ -323,7 +324,7 @@ fn emit_future_breakage(&self) {
             .into_iter()
             .map(|diag| {
                 let lint_name = match &diag.code {
-                    Some(DiagnosticId::Lint { name, has_future_breakage: true }) => name,
+                    Some(DiagnosticId::Lint { name, has_future_breakage: true, .. }) => name,
                     _ => panic!("Unexpected code in diagnostic {:?}", diag),
                 };
                 let lint = lint_store.name_to_lint(&lint_name);
@@ -335,8 +336,8 @@ fn emit_future_breakage(&self) {
         self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage);
     }
 
-    pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
-        self.crate_disambiguator.get().copied().unwrap()
+    pub fn local_stable_crate_id(&self) -> StableCrateId {
+        self.stable_crate_id.get().copied().unwrap()
     }
 
     pub fn crate_types(&self) -> &[CrateType] {
@@ -347,28 +348,16 @@ pub fn init_crate_types(&self, crate_types: Vec<CrateType>) {
         self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
     }
 
-    #[inline]
-    pub fn recursion_limit(&self) -> Limit {
-        self.recursion_limit.get().copied().unwrap()
-    }
-
-    #[inline]
-    pub fn move_size_limit(&self) -> usize {
-        self.move_size_limit.get().copied().unwrap()
-    }
-
-    #[inline]
-    pub fn type_length_limit(&self) -> Limit {
-        self.type_length_limit.get().copied().unwrap()
-    }
-
-    pub fn const_eval_limit(&self) -> Limit {
-        self.const_eval_limit.get().copied().unwrap()
-    }
-
     pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_warn(sp, msg)
     }
+    pub fn struct_span_force_warn<S: Into<MultiSpan>>(
+        &self,
+        sp: S,
+        msg: &str,
+    ) -> DiagnosticBuilder<'_> {
+        self.diagnostic().struct_span_force_warn(sp, msg)
+    }
     pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -380,6 +369,9 @@ pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
     pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_warn(msg)
     }
+    pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        self.diagnostic().struct_force_warn(msg)
+    }
     pub fn struct_span_allow<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_allow(sp, msg)
     }
@@ -821,12 +813,12 @@ pub fn must_emit_unwind_tables(&self) -> bool {
 
     /// Returns the symbol name for the registrar function,
     /// given the crate `Svh` and the function `DefIndex`.
-    pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
-        format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
+    pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String {
+        format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64())
     }
 
-    pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String {
-        format!("__rustc_proc_macro_decls_{}__", disambiguator.to_fingerprint().to_hex())
+    pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
+        format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
     }
 
     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
@@ -1388,13 +1380,9 @@ pub fn build_session(
         working_dir,
         one_time_diagnostics: Default::default(),
         crate_types: OnceCell::new(),
-        crate_disambiguator: OnceCell::new(),
+        stable_crate_id: OnceCell::new(),
         features: OnceCell::new(),
         lint_store: OnceCell::new(),
-        recursion_limit: OnceCell::new(),
-        move_size_limit: OnceCell::new(),
-        type_length_limit: OnceCell::new(),
-        const_eval_limit: OnceCell::new(),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         cgu_reuse_tracker,
         prof,
diff --git a/compiler/rustc_span/src/crate_disambiguator.rs b/compiler/rustc_span/src/crate_disambiguator.rs
deleted file mode 100644 (file)
index bd7d851..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// This is here because `rustc_session` wants to refer to it,
-// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`.
-
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::{base_n, impl_stable_hash_via_hash};
-
-use std::fmt;
-
-/// Hash value constructed out of all the `-C metadata` arguments passed to the
-/// compiler. Together with the crate-name forms a unique global identifier for
-/// the crate.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
-pub struct CrateDisambiguator(Fingerprint);
-
-impl CrateDisambiguator {
-    pub fn to_fingerprint(self) -> Fingerprint {
-        self.0
-    }
-}
-
-impl fmt::Display for CrateDisambiguator {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        let (a, b) = self.0.as_value();
-        let as_u128 = a as u128 | ((b as u128) << 64);
-        f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
-    }
-}
-
-impl From<Fingerprint> for CrateDisambiguator {
-    fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
-        CrateDisambiguator(fingerprint)
-    }
-}
-
-impl_stable_hash_via_hash!(CrateDisambiguator);
index bb4ac22d9c867d6ef037d4fe66a2a715b278f08d..c5d605ab57801ef752442942270b4e49fac541e7 100644 (file)
@@ -1,4 +1,3 @@
-use crate::crate_disambiguator::CrateDisambiguator;
 use crate::HashStableContext;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
@@ -127,26 +126,51 @@ fn borrow(&self) -> &Fingerprint {
     }
 }
 
-/// A [StableCrateId] is a 64 bit hash of `(crate-name, crate-disambiguator)`. It
-/// is to [CrateNum] what [DefPathHash] is to [DefId]. It is stable across
-/// compilation sessions.
+/// A [StableCrateId] is a 64 bit hash of the crate name combined with all
+/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to
+/// [DefId]. It is stable across compilation sessions.
 ///
 /// Since the ID is a hash value there is a (very small) chance that two crates
 /// end up with the same [StableCrateId]. The compiler will check for such
 /// collisions when loading crates and abort compilation in order to avoid
 /// further trouble.
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Encodable, Decodable)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
 pub struct StableCrateId(u64);
 
 impl StableCrateId {
+    pub fn to_u64(self) -> u64 {
+        self.0
+    }
+
     /// Computes the stable ID for a crate with the given name and
-    /// disambiguator.
-    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> StableCrateId {
+    /// `-Cmetadata` arguments.
+    pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
         use std::hash::Hash;
+        use std::hash::Hasher;
 
         let mut hasher = StableHasher::new();
         crate_name.hash(&mut hasher);
-        crate_disambiguator.hash(&mut hasher);
+
+        // We don't want the stable crate id to dependent on the order
+        // -C metadata arguments, so sort them:
+        metadata.sort();
+        // Every distinct -C metadata value is only incorporated once:
+        metadata.dedup();
+
+        hasher.write(b"metadata");
+        for s in &metadata {
+            // Also incorporate the length of a metadata string, so that we generate
+            // different values for `-Cmetadata=ab -Cmetadata=c` and
+            // `-Cmetadata=a -Cmetadata=bc`
+            hasher.write_usize(s.len());
+            hasher.write(s.as_bytes());
+        }
+
+        // Also incorporate crate type, so that we don't get symbol conflicts when
+        // linking against a library of the same name, if this is an executable.
+        hasher.write(if is_exe { b"exe" } else { b"lib" });
+
         StableCrateId(hasher.finish())
     }
 }
index 23efaf6f4f33d861c5d59c5a4b86c2ac72bc3e1b..78b181aa3300a55887aa9c0137baf582710d0137 100644 (file)
@@ -26,7 +26,7 @@
 
 use crate::edition::Edition;
 use crate::symbol::{kw, sym, Symbol};
-use crate::SESSION_GLOBALS;
+use crate::with_session_globals;
 use crate::{BytePos, CachingSourceMapView, ExpnIdCache, SourceFile, Span, DUMMY_SP};
 
 use crate::def_id::{CrateNum, DefId, DefPathHash, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -144,10 +144,7 @@ pub fn expansion_cause(mut self) -> Option<Span> {
             let expn_data = self.expn_data();
             // Stop going up the backtrace once include! is encountered
             if expn_data.is_root()
-                || matches!(
-                    expn_data.kind,
-                    ExpnKind::Macro { kind: MacroKind::Bang, name: sym::include, proc_macro: _ }
-                )
+                || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include)
             {
                 break;
             }
@@ -181,6 +178,7 @@ impl HygieneData {
             DUMMY_SP,
             edition,
             Some(DefId::local(CRATE_DEF_INDEX)),
+            None,
         );
         root_data.orig_id = Some(0);
 
@@ -200,7 +198,7 @@ impl HygieneData {
     }
 
     pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
-        SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
+        with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
     }
 
     fn fresh_expn(&mut self, mut expn_data: Option<ExpnData>) -> ExpnId {
@@ -687,7 +685,7 @@ pub fn mark_with_reason(
     ) -> Span {
         self.fresh_expansion(ExpnData {
             allow_internal_unstable,
-            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None)
+            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None)
         })
     }
 }
@@ -711,29 +709,6 @@ pub struct ExpnData {
     /// call_site span would have its own ExpnData, with the call_site
     /// pointing to the `foo!` invocation.
     pub call_site: Span,
-
-    // --- The part specific to the macro/desugaring definition.
-    // --- It may be reasonable to share this part between expansions with the same definition,
-    // --- but such sharing is known to bring some minor inconveniences without also bringing
-    // --- noticeable perf improvements (PR #62898).
-    /// The span of the macro definition (possibly dummy).
-    /// This span serves only informational purpose and is not used for resolution.
-    pub def_site: Span,
-    /// List of `#[unstable]`/feature-gated features that the macro is allowed to use
-    /// internally without forcing the whole crate to opt-in
-    /// to them.
-    pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
-    /// Whether the macro is allowed to use `unsafe` internally
-    /// even if the user crate has `#![forbid(unsafe_code)]`.
-    pub allow_internal_unsafe: bool,
-    /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
-    /// for a given macro.
-    pub local_inner_macros: bool,
-    /// Edition of the crate in which the macro is defined.
-    pub edition: Edition,
-    /// The `DefId` of the macro being invoked,
-    /// if this `ExpnData` corresponds to a macro invocation
-    pub macro_def_id: Option<DefId>,
     /// The crate that originally created this `ExpnData`. During
     /// metadata serialization, we only encode `ExpnData`s that were
     /// created locally - when our serialized metadata is decoded,
@@ -748,7 +723,6 @@ pub struct ExpnData {
     // be considered equivalent.
     #[stable_hasher(ignore)]
     orig_id: Option<u32>,
-
     /// Used to force two `ExpnData`s to have different `Fingerprint`s.
     /// Due to macro expansion, it's possible to end up with two `ExpnId`s
     /// that have identical `ExpnData`s. This violates the contract of `HashStable`
@@ -760,6 +734,31 @@ pub struct ExpnData {
     /// `ExpnId`s would end up with the same `Fingerprint`. Since `ExpnData` includes
     /// a `krate` field, this value only needs to be unique within a single crate.
     disambiguator: u32,
+
+    // --- The part specific to the macro/desugaring definition.
+    // --- It may be reasonable to share this part between expansions with the same definition,
+    // --- but such sharing is known to bring some minor inconveniences without also bringing
+    // --- noticeable perf improvements (PR #62898).
+    /// The span of the macro definition (possibly dummy).
+    /// This span serves only informational purpose and is not used for resolution.
+    pub def_site: Span,
+    /// List of `#[unstable]`/feature-gated features that the macro is allowed to use
+    /// internally without forcing the whole crate to opt-in
+    /// to them.
+    pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
+    /// Whether the macro is allowed to use `unsafe` internally
+    /// even if the user crate has `#![forbid(unsafe_code)]`.
+    pub allow_internal_unsafe: bool,
+    /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
+    /// for a given macro.
+    pub local_inner_macros: bool,
+    /// Edition of the crate in which the macro is defined.
+    pub edition: Edition,
+    /// The `DefId` of the macro being invoked,
+    /// if this `ExpnData` corresponds to a macro invocation
+    pub macro_def_id: Option<DefId>,
+    /// The normal module (`mod`) in which the expanded macro was defined.
+    pub parent_module: Option<DefId>,
 }
 
 // These would require special handling of `orig_id`.
@@ -777,6 +776,7 @@ pub fn new(
         local_inner_macros: bool,
         edition: Edition,
         macro_def_id: Option<DefId>,
+        parent_module: Option<DefId>,
     ) -> ExpnData {
         ExpnData {
             kind,
@@ -788,6 +788,7 @@ pub fn new(
             local_inner_macros,
             edition,
             macro_def_id,
+            parent_module,
             krate: LOCAL_CRATE,
             orig_id: None,
             disambiguator: 0,
@@ -800,6 +801,7 @@ pub fn default(
         call_site: Span,
         edition: Edition,
         macro_def_id: Option<DefId>,
+        parent_module: Option<DefId>,
     ) -> ExpnData {
         ExpnData {
             kind,
@@ -811,6 +813,7 @@ pub fn default(
             local_inner_macros: false,
             edition,
             macro_def_id,
+            parent_module,
             krate: LOCAL_CRATE,
             orig_id: None,
             disambiguator: 0,
@@ -823,10 +826,11 @@ pub fn allow_unstable(
         edition: Edition,
         allow_internal_unstable: Lrc<[Symbol]>,
         macro_def_id: Option<DefId>,
+        parent_module: Option<DefId>,
     ) -> ExpnData {
         ExpnData {
             allow_internal_unstable: Some(allow_internal_unstable),
-            ..ExpnData::default(kind, call_site, edition, macro_def_id)
+            ..ExpnData::default(kind, call_site, edition, macro_def_id, parent_module)
         }
     }
 
@@ -842,13 +846,7 @@ pub enum ExpnKind {
     /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
     Root,
     /// Expansion produced by a macro.
-    Macro {
-        kind: MacroKind,
-        name: Symbol,
-        /// If `true`, this macro is a procedural macro. This
-        /// flag is only used for diagnostic purposes
-        proc_macro: bool,
-    },
+    Macro(MacroKind, Symbol),
     /// Transform done by the compiler on the AST.
     AstPass(AstPass),
     /// Desugaring done by the compiler during HIR lowering.
@@ -861,7 +859,7 @@ impl ExpnKind {
     pub fn descr(&self) -> String {
         match *self {
             ExpnKind::Root => kw::PathRoot.to_string(),
-            ExpnKind::Macro { kind, name, proc_macro: _ } => match kind {
+            ExpnKind::Macro(macro_kind, name) => match macro_kind {
                 MacroKind::Bang => format!("{}!", name),
                 MacroKind::Attr => format!("#[{}]", name),
                 MacroKind::Derive => format!("#[derive({})]", name),
@@ -1359,8 +1357,9 @@ fn span_data_to_lines_and_cols(
         }
     }
 
-    let source_map = SESSION_GLOBALS
-        .with(|session_globals| session_globals.source_map.borrow().as_ref().unwrap().clone());
+    let source_map = with_session_globals(|session_globals| {
+        session_globals.source_map.borrow().as_ref().unwrap().clone()
+    });
 
     let mut ctx =
         DummyHashStableContext { caching_source_map: CachingSourceMapView::new(&source_map) };
index 90e20afc8f53865e79b4c3f88d80a6280f4231e2..11822e9ef974236c9784405674e178fa70a327b7 100644 (file)
@@ -21,8 +21,8 @@ fn test_lev_distance() {
 
 #[test]
 fn test_find_best_match_for_name() {
-    use crate::with_default_session_globals;
-    with_default_session_globals(|| {
+    use crate::create_default_session_globals_then;
+    create_default_session_globals_then(|| {
         let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
         assert_eq!(
             find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
index b4fe7c980de9582e9ca5ebb86d0f2fe5412b2161..84bef4b113c1532f4f435178be523e2c5d633fab 100644 (file)
@@ -45,8 +45,6 @@
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
-pub mod crate_disambiguator;
-
 pub mod symbol;
 pub use symbol::{sym, Symbol};
 
@@ -99,19 +97,65 @@ pub fn new(edition: Edition) -> SessionGlobals {
     }
 }
 
-pub fn with_session_globals<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
+#[inline]
+pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
+    assert!(
+        !SESSION_GLOBALS.is_set(),
+        "SESSION_GLOBALS should never be overwritten! \
+         Use another thread if you need another SessionGlobals"
+    );
     let session_globals = SessionGlobals::new(edition);
     SESSION_GLOBALS.set(&session_globals, f)
 }
 
-pub fn with_default_session_globals<R>(f: impl FnOnce() -> R) -> R {
-    with_session_globals(edition::DEFAULT_EDITION, f)
+#[inline]
+pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
+    assert!(
+        !SESSION_GLOBALS.is_set(),
+        "SESSION_GLOBALS should never be overwritten! \
+         Use another thread if you need another SessionGlobals"
+    );
+    SESSION_GLOBALS.set(session_globals, f)
+}
+
+#[inline]
+pub fn create_default_session_if_not_set_then<R, F>(f: F) -> R
+where
+    F: FnOnce(&SessionGlobals) -> R,
+{
+    create_session_if_not_set_then(edition::DEFAULT_EDITION, f)
+}
+
+#[inline]
+pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
+where
+    F: FnOnce(&SessionGlobals) -> R,
+{
+    if !SESSION_GLOBALS.is_set() {
+        let session_globals = SessionGlobals::new(edition);
+        SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
+    } else {
+        SESSION_GLOBALS.with(f)
+    }
+}
+
+#[inline]
+pub fn with_session_globals<R, F>(f: F) -> R
+where
+    F: FnOnce(&SessionGlobals) -> R,
+{
+    SESSION_GLOBALS.with(f)
+}
+
+#[inline]
+pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
+    create_session_globals_then(edition::DEFAULT_EDITION, f)
 }
 
 // If this ever becomes non thread-local, `decode_syntax_context`
 // and `decode_expn_id` will need to be updated to handle concurrent
 // deserialization.
-scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
+scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
 
 // FIXME: We should use this enum or something like it to get rid of the
 // use of magic `/rust/1.x/...` paths across the board.
@@ -476,10 +520,7 @@ pub fn from_expansion(self) -> bool {
 
     /// Returns `true` if `span` originates in a derive-macro's expansion.
     pub fn in_derive_expansion(self) -> bool {
-        matches!(
-            self.ctxt().outer_expn_data().kind,
-            ExpnKind::Macro { kind: MacroKind::Derive, name: _, proc_macro: _ }
-        )
+        matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
     }
 
     #[inline]
@@ -857,13 +898,13 @@ impl<D: Decoder> Decodable<D> for Span {
 /// the `SourceMap` provided to this function. If that is not available,
 /// we fall back to printing the raw `Span` field values.
 pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
-    SESSION_GLOBALS.with(|session_globals| {
+    with_session_globals(|session_globals| {
         *session_globals.source_map.borrow_mut() = Some(source_map);
     });
     struct ClearSourceMap;
     impl Drop for ClearSourceMap {
         fn drop(&mut self) {
-            SESSION_GLOBALS.with(|session_globals| {
+            with_session_globals(|session_globals| {
                 session_globals.source_map.borrow_mut().take();
             });
         }
@@ -882,7 +923,7 @@ pub fn debug_with_source_map(
 }
 
 pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    SESSION_GLOBALS.with(|session_globals| {
+    with_session_globals(|session_globals| {
         if let Some(source_map) = &*session_globals.source_map.borrow() {
             debug_with_source_map(span, f, source_map)
         } else {
@@ -1508,13 +1549,11 @@ pub fn count_lines(&self) -> usize {
     /// number. If the source_file is empty or the position is located before the
     /// first line, `None` is returned.
     pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
-        if self.lines.is_empty() {
-            return None;
+        match self.lines.binary_search(&pos) {
+            Ok(idx) => Some(idx),
+            Err(0) => None,
+            Err(idx) => Some(idx - 1),
         }
-
-        let line_index = lookup_line(&self.lines[..], pos);
-        assert!(line_index < self.lines.len() as isize);
-        if line_index >= 0 { Some(line_index as usize) } else { None }
     }
 
     pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
@@ -1913,16 +1952,6 @@ pub fn new(start: usize, end: usize) -> InnerSpan {
     }
 }
 
-// Given a slice of line start positions and a position, returns the index of
-// the line the position is on. Returns -1 if the position is located before
-// the first line.
-fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize {
-    match lines.binary_search(&pos) {
-        Ok(line) => line as isize,
-        Err(line) => line as isize - 1,
-    }
-}
-
 /// Requirements for a `StableHashingContext` to be used in this crate.
 ///
 /// This is a hack to allow using the [`HashStable_Generic`] derive macro
index 5ea39b343b5c18910b39a23be1a3f04a34e6c076..cb017709c6c7bfc071268a71779f2c230f34827f 100644 (file)
@@ -5,7 +5,6 @@
 // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
 
 use crate::hygiene::SyntaxContext;
-use crate::SESSION_GLOBALS;
 use crate::{BytePos, SpanData};
 
 use rustc_data_structures::fx::FxIndexSet;
@@ -122,5 +121,5 @@ fn intern(&mut self, span_data: &SpanData) -> u32 {
 // If an interner exists, return it. Otherwise, prepare a fresh one.
 #[inline]
 fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T {
-    SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.span_interner.lock()))
+    crate::with_session_globals(|session_globals| f(&mut *session_globals.span_interner.lock()))
 }
index be4f12c6d1cb8fef662ea29185be1aefb6a5d062..cfa0c79004c002b946f4f31ff2816f18d73e062a 100644 (file)
@@ -13,7 +13,7 @@
 use std::hash::{Hash, Hasher};
 use std::str;
 
-use crate::{Edition, Span, DUMMY_SP, SESSION_GLOBALS};
+use crate::{with_session_globals, Edition, Span, DUMMY_SP};
 
 #[cfg(test)]
 mod tests;
         FormatSpec,
         Formatter,
         From,
+        FromIterator,
         Future,
         FxHashMap,
         FxHashSet,
         minnumf64,
         mips_target_feature,
         misc,
+        mmx_reg,
         modifiers,
         module,
         module_path,
         prefetch_read_instruction,
         prefetch_write_data,
         prefetch_write_instruction,
+        preg,
         prelude,
         prelude_import,
         preserves_flags,
         quote,
         range_inclusive_new,
         raw_dylib,
+        raw_eq,
         raw_identifiers,
         raw_ref_op,
         re_rebalance_coherence,
         receiver,
         recursion_limit,
         reexport_test_harness_main,
-        ref_unwind_safe,
+        ref_unwind_safe_trait,
         reference,
         reflect,
         reg,
         self_in_typedefs,
         self_struct_ctor,
         semitransparent,
-        send,
         send_trait,
         shl,
         shl_assign,
         unused_qualifications,
         unwind,
         unwind_attributes,
-        unwind_safe,
+        unwind_safe_trait,
         unwrap,
         unwrap_or,
         use_extern_macros,
         wrapping_sub,
         wreg,
         write_bytes,
+        x87_reg,
         xmm_reg,
         ymm_reg,
         zmm_reg,
@@ -1790,7 +1794,7 @@ pub fn is_raw_guess(self) -> bool {
 
 #[inline]
 fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
-    SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
+    with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
 }
 
 /// An alternative to [`Symbol`], useful when the chars within the symbol need to
index 47da03424b7705f472e2ae95aa748065c2974c02..11dea265b4e66c6adb3769195bf6d234bbf8919f 100644 (file)
@@ -1,6 +1,6 @@
 use super::*;
 
-use crate::{edition, SessionGlobals};
+use crate::create_default_session_globals_then;
 
 #[test]
 fn interner_tests() {
@@ -18,7 +18,7 @@ fn interner_tests() {
 
 #[test]
 fn without_first_quote_test() {
-    SESSION_GLOBALS.set(&SessionGlobals::new(edition::DEFAULT_EDITION), || {
+    create_default_session_globals_then(|| {
         let i = Ident::from_str("'break");
         assert_eq!(i.without_first_quote().name, kw::Break);
     });
index 3c8eb8bcd3152ffabb10e8f54b3bc98a50f75650..11edcacc0d43ba95917ffadae0dc14d44b3cfebd 100644 (file)
@@ -2,18 +2,21 @@
 
 #[test]
 fn test_lookup_line() {
-    let lines = &[BytePos(3), BytePos(17), BytePos(28)];
+    let source = "abcdefghijklm\nabcdefghij\n...".to_owned();
+    let sf =
+        SourceFile::new(FileName::Anon(0), source, BytePos(3), SourceFileHashAlgorithm::Sha256);
+    assert_eq!(sf.lines.as_slice(), &[BytePos(3), BytePos(17), BytePos(28)]);
 
-    assert_eq!(lookup_line(lines, BytePos(0)), -1);
-    assert_eq!(lookup_line(lines, BytePos(3)), 0);
-    assert_eq!(lookup_line(lines, BytePos(4)), 0);
+    assert_eq!(sf.lookup_line(BytePos(0)), None);
+    assert_eq!(sf.lookup_line(BytePos(3)), Some(0));
+    assert_eq!(sf.lookup_line(BytePos(4)), Some(0));
 
-    assert_eq!(lookup_line(lines, BytePos(16)), 0);
-    assert_eq!(lookup_line(lines, BytePos(17)), 1);
-    assert_eq!(lookup_line(lines, BytePos(18)), 1);
+    assert_eq!(sf.lookup_line(BytePos(16)), Some(0));
+    assert_eq!(sf.lookup_line(BytePos(17)), Some(1));
+    assert_eq!(sf.lookup_line(BytePos(18)), Some(1));
 
-    assert_eq!(lookup_line(lines, BytePos(28)), 2);
-    assert_eq!(lookup_line(lines, BytePos(29)), 2);
+    assert_eq!(sf.lookup_line(BytePos(28)), Some(2));
+    assert_eq!(sf.lookup_line(BytePos(29)), Some(2));
 }
 
 #[test]
index 025eaffcbd3285ca8c012281d2f289efe5d33d1f..0c64fe6ea60a9249cbce6f5c1c98d30d77a20ab3 100644 (file)
@@ -126,8 +126,9 @@ fn get_symbol_hash<'tcx>(
         substs.hash_stable(&mut hcx, &mut hasher);
 
         if let Some(instantiating_crate) = instantiating_crate {
-            tcx.crate_name(instantiating_crate).as_str().hash_stable(&mut hcx, &mut hasher);
-            tcx.crate_disambiguator(instantiating_crate).hash_stable(&mut hcx, &mut hasher);
+            tcx.def_path_hash(instantiating_crate.as_def_id())
+                .stable_crate_id()
+                .hash_stable(&mut hcx, &mut hasher);
         }
 
         // We want to avoid accidental collision between different types of instances.
index f716ce1efce86f1d952df25a7ee5cfe5fd3d65ad..ba59ff96f6554d3e8e5f3ce9f55e448d7d73e9dc 100644 (file)
@@ -165,12 +165,12 @@ fn compute_symbol_name(
     // FIXME(eddyb) Precompute a custom symbol name based on attributes.
     let is_foreign = if let Some(def_id) = def_id.as_local() {
         if tcx.plugin_registrar_fn(()) == Some(def_id) {
-            let disambiguator = tcx.sess.local_crate_disambiguator();
-            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
+            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id);
         }
         if tcx.proc_macro_decls_static(()) == Some(def_id) {
-            let disambiguator = tcx.sess.local_crate_disambiguator();
-            return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
+            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
         }
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         matches!(tcx.hir().get(hir_id), Node::ForeignItem(_))
index 1a9d04a75ec6abac73bb84ffae25289367501be5..14442806fc0b757104c1d4fb58adae3ddf0734a0 100644 (file)
@@ -592,8 +592,8 @@ fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self:
 
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
         self.push("C");
-        let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint();
-        self.push_disambiguator(fingerprint.to_smaller_hash());
+        let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
+        self.push_disambiguator(stable_crate_id.to_u64());
         let name = self.tcx.crate_name(cnum).as_str();
         self.push_ident(&name);
         Ok(self)
index f180eea01a3bbe796f060b7c91be3dad3871ac41..76e50678314aedb90c3e36831a293d7f252bb174 100644 (file)
@@ -7,6 +7,7 @@
         reg,
         vreg,
         vreg_low16,
+        preg,
     }
 }
 
@@ -15,6 +16,7 @@ pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
         match self {
             Self::reg => &['w', 'x'],
             Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'],
+            Self::preg => &[],
         }
     }
 
@@ -40,6 +42,7 @@ pub fn suggest_modifier(
                 128 => Some(('q', "q0")),
                 _ => None,
             },
+            Self::preg => None,
         }
     }
 
@@ -47,6 +50,7 @@ pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static st
         match self {
             Self::reg => Some(('x', "x0")),
             Self::vreg | Self::vreg_low16 => Some(('v', "v0")),
+            Self::preg => None,
         }
     }
 
@@ -61,6 +65,7 @@ pub fn supported_types(
                     VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
                     VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
             },
+            Self::preg => &[],
         }
     }
 }
@@ -95,38 +100,55 @@ pub fn supported_types(
         x27: reg = ["x27", "w27"],
         x28: reg = ["x28", "w28"],
         x30: reg = ["x30", "w30", "lr", "wlr"],
-        v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0"],
-        v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1"],
-        v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2"],
-        v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3"],
-        v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4"],
-        v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5"],
-        v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6"],
-        v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7"],
-        v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8"],
-        v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9"],
-        v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10"],
-        v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11"],
-        v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12"],
-        v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13"],
-        v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14"],
-        v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15"],
-        v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16"],
-        v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17"],
-        v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18"],
-        v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19"],
-        v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20"],
-        v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21"],
-        v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22"],
-        v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23"],
-        v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24"],
-        v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25"],
-        v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26"],
-        v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27"],
-        v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28"],
-        v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29"],
-        v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30"],
-        v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31"],
+        v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"],
+        v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"],
+        v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2", "z2"],
+        v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3", "z3"],
+        v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4", "z4"],
+        v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5", "z5"],
+        v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6", "z6"],
+        v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7", "z7"],
+        v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8", "z8"],
+        v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9", "z9"],
+        v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10", "z10"],
+        v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11", "z11"],
+        v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12", "z12"],
+        v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"],
+        v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"],
+        v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"],
+        v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"],
+        v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"],
+        v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"],
+        v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"],
+        v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"],
+        v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"],
+        v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"],
+        v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"],
+        v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"],
+        v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"],
+        v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"],
+        v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"],
+        v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"],
+        v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"],
+        v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"],
+        v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"],
+        p0: preg = ["p0"],
+        p1: preg = ["p1"],
+        p2: preg = ["p2"],
+        p3: preg = ["p3"],
+        p4: preg = ["p4"],
+        p5: preg = ["p5"],
+        p6: preg = ["p6"],
+        p7: preg = ["p7"],
+        p8: preg = ["p8"],
+        p9: preg = ["p9"],
+        p10: preg = ["p10"],
+        p11: preg = ["p11"],
+        p12: preg = ["p12"],
+        p13: preg = ["p13"],
+        p14: preg = ["p14"],
+        p15: preg = ["p15"],
+        ffr: preg = ["ffr"],
         #error = ["x18", "w18"] =>
             "x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm",
         #error = ["x19", "w19"] =>
index 305ea7d50e66ea058a37d579d3223820bf4870c6..b52fa5bbcb2bae18af14da53873cd530bf9317f9 100644 (file)
@@ -533,6 +533,12 @@ pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
+
+    /// Returns whether registers in this class can only be used as clobbers
+    /// and not as inputs/outputs.
+    pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool {
+        self.supported_types(arch).is_empty()
+    }
 }
 
 #[derive(
index e276a9175f9ab5626e0a00eab52e2cf41643c69a..314bd01de12278f480cc85868e5555048bce9b44 100644 (file)
@@ -7,6 +7,7 @@
     RiscV RiscVInlineAsmRegClass {
         reg,
         freg,
+        vreg,
     }
 }
 
@@ -44,6 +45,7 @@ pub fn supported_types(
                 }
             }
             Self::freg => types! { "f": F32; "d": F64; },
+            Self::vreg => &[],
         }
     }
 }
@@ -120,6 +122,38 @@ fn not_e(
         f29: freg = ["f29", "ft9"],
         f30: freg = ["f30", "ft10"],
         f31: freg = ["f31", "ft11"],
+        v0: vreg = ["v0"],
+        v1: vreg = ["v1"],
+        v2: vreg = ["v2"],
+        v3: vreg = ["v3"],
+        v4: vreg = ["v4"],
+        v5: vreg = ["v5"],
+        v6: vreg = ["v6"],
+        v7: vreg = ["v7"],
+        v8: vreg = ["v8"],
+        v9: vreg = ["v9"],
+        v10: vreg = ["v10"],
+        v11: vreg = ["v11"],
+        v12: vreg = ["v12"],
+        v13: vreg = ["v13"],
+        v14: vreg = ["v14"],
+        v15: vreg = ["v15"],
+        v16: vreg = ["v16"],
+        v17: vreg = ["v17"],
+        v18: vreg = ["v18"],
+        v19: vreg = ["v19"],
+        v20: vreg = ["v20"],
+        v21: vreg = ["v21"],
+        v22: vreg = ["v22"],
+        v23: vreg = ["v23"],
+        v24: vreg = ["v24"],
+        v25: vreg = ["v25"],
+        v26: vreg = ["v26"],
+        v27: vreg = ["v27"],
+        v28: vreg = ["v28"],
+        v29: vreg = ["v29"],
+        v30: vreg = ["v30"],
+        v31: vreg = ["v31"],
         #error = ["x9", "s1"] =>
             "s1 is used internally by LLVM and cannot be used as an operand for inline asm",
         #error = ["x8", "s0", "fp"] =>
index 48f83ca7cd49a41c2623f210fb71568e956f03af..5e3828d7d8521063be64bf93c632b098f9460f53 100644 (file)
@@ -12,6 +12,8 @@
         ymm_reg,
         zmm_reg,
         kreg,
+        mmx_reg,
+        x87_reg,
     }
 }
 
@@ -35,6 +37,7 @@ pub fn valid_modifiers(self, arch: super::InlineAsmArch) -> &'static [char] {
             Self::reg_byte => &[],
             Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'],
             Self::kreg => &[],
+            Self::mmx_reg | Self::x87_reg => &[],
         }
     }
 
@@ -73,6 +76,7 @@ pub fn suggest_modifier(
                 _ => Some(('x', "xmm0")),
             },
             Self::kreg => None,
+            Self::mmx_reg | Self::x87_reg => None,
         }
     }
 
@@ -90,6 +94,7 @@ pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str
             Self::ymm_reg => Some(('y', "ymm0")),
             Self::zmm_reg => Some(('z', "zmm0")),
             Self::kreg => None,
+            Self::mmx_reg | Self::x87_reg => None,
         }
     }
 
@@ -125,6 +130,7 @@ pub fn supported_types(
                 "avx512f": I8, I16;
                 "avx512bw": I32, I64;
             },
+            Self::mmx_reg | Self::x87_reg => &[],
         }
     }
 }
@@ -285,16 +291,28 @@ fn esi_reserved(
         k5: kreg = ["k5"],
         k6: kreg = ["k6"],
         k7: kreg = ["k7"],
+        mm0: mmx_reg = ["mm0"],
+        mm1: mmx_reg = ["mm1"],
+        mm2: mmx_reg = ["mm2"],
+        mm3: mmx_reg = ["mm3"],
+        mm4: mmx_reg = ["mm4"],
+        mm5: mmx_reg = ["mm5"],
+        mm6: mmx_reg = ["mm6"],
+        mm7: mmx_reg = ["mm7"],
+        st0: x87_reg = ["st(0)", "st"],
+        st1: x87_reg = ["st(1)"],
+        st2: x87_reg = ["st(2)"],
+        st3: x87_reg = ["st(3)"],
+        st4: x87_reg = ["st(4)"],
+        st5: x87_reg = ["st(5)"],
+        st6: x87_reg = ["st(6)"],
+        st7: x87_reg = ["st(7)"],
         #error = ["bp", "bpl", "ebp", "rbp"] =>
             "the frame pointer cannot be used as an operand for inline asm",
         #error = ["sp", "spl", "esp", "rsp"] =>
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["ip", "eip", "rip"] =>
             "the instruction pointer cannot be used as an operand for inline asm",
-        #error = ["st", "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"] =>
-            "x87 registers are not currently supported as operands for inline asm",
-        #error = ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"] =>
-            "MMX registers are not currently supported as operands for inline asm",
         #error = ["k0"] =>
             "the k0 AVX mask register cannot be used as an operand for inline asm",
     }
index 9fa8ef69d8131e6be8d71a6cc2876fd496a0c832..e5805d9e691cbe3ff311db0ed4413b756c275b2a 100644 (file)
@@ -2,7 +2,6 @@
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::Arm64);
     Target {
         llvm_target: "arm64-apple-ios".to_string(),
         pointer_width: 64,
@@ -11,7 +10,6 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".to_string(),
             max_atomic_width: Some(128),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
             // Taken from a clang build on Xcode 11.4.1.
@@ -25,7 +23,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .to_string(),
-            ..base
+            ..opts("ios", Arch::Arm64)
         },
     }
 }
index a43eb99a1d73f5d48ca7a150b2b413c6359d74d6..d16328f00f9ab65f7137b784b009c812dcbcf690 100644 (file)
@@ -2,7 +2,6 @@
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::Arm64_macabi);
     Target {
         llvm_target: "arm64-apple-ios14.0-macabi".to_string(),
         pointer_width: 64,
@@ -11,7 +10,6 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12".to_string(),
             max_atomic_width: Some(128),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
             // Taken from a clang build on Xcode 11.4.1.
@@ -23,7 +21,7 @@ pub fn target() -> Target {
                 -disable-llvm-passes\0\
                 -Os\0"
                 .to_string(),
-            ..base
+            ..opts("ios", Arch::Arm64_macabi)
         },
     }
 }
index 586e4043d79def6f46c62d4bd23642701e33c33d..07b3453218fee47b80e7fa3d967a9ff47e5ba6b8 100644 (file)
@@ -19,7 +19,6 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".to_string(),
             max_atomic_width: Some(128),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
             // Taken from a clang build on Xcode 11.4.1.
index 934f33703690f6b85af5a606a36422cece9d91ed..b4bd72a082be7c544d7eaf08d7b36792aa417764 100644 (file)
@@ -2,7 +2,6 @@
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("tvos", Arch::Arm64);
     Target {
         llvm_target: "arm64-apple-tvos".to_string(),
         pointer_width: 64,
@@ -11,10 +10,9 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".to_string(),
             max_atomic_width: Some(128),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            ..opts("tvos", Arch::Arm64)
         },
     }
 }
index 192c4661c7ce6d90d420ae2b6b0f23582db17a49..71ee6deb07f903b5c64b9b46d8e5ec59e9c6c1bd 100644 (file)
@@ -2,19 +2,16 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_gnu_base::opts();
-    base.max_atomic_width = Some(128);
-
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu".to_string(),
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            max_atomic_width: Some(128),
             mcount: "\u{1}_mcount".to_string(),
             endian: Endian::Big,
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 5b9e9c9519c5480065e1d0d6b7be411b3d8af12b..c1adc963425ea6791eb756429f568d738d7d80f4 100644 (file)
@@ -10,11 +10,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            mcount: "\u{1}_mcount".to_string(),
-            endian: Endian::Big,
-            ..base
-        },
+        options: TargetOptions { mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, ..base },
     }
 }
index c9cb21f1eb1e9bf891250da0ce39ac50b523c7bc..56d71df6bda242af9d55c0dace7aa5d6689868dd 100644 (file)
@@ -1,15 +1,15 @@
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::fuchsia_base::opts();
-    base.max_atomic_width = Some(128);
-    base.supported_sanitizers = SanitizerSet::ADDRESS;
-
     Target {
         llvm_target: "aarch64-fuchsia".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions {
+            max_atomic_width: Some(128),
+            supported_sanitizers: SanitizerSet::ADDRESS,
+            ..super::fuchsia_base::opts()
+        },
     }
 }
index d00883ae71ad3ce61d5f44530476e2fa9be71360..409cab72ec2196898ba478fa53d379c6041cb51d 100644 (file)
@@ -4,17 +4,18 @@
 // for target ABI requirements.
 
 pub fn target() -> Target {
-    let mut base = super::android_base::opts();
-    base.max_atomic_width = Some(128);
-    // As documented in https://developer.android.com/ndk/guides/cpu-features.html
-    // the neon (ASIMD) and FP must exist on all android aarch64 targets.
-    base.features = "+neon,+fp-armv8".to_string();
-    base.supported_sanitizers = SanitizerSet::HWADDRESS;
     Target {
         llvm_target: "aarch64-linux-android".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions {
+            max_atomic_width: Some(128),
+            // As documented in https://developer.android.com/ndk/guides/cpu-features.html
+            // the neon (ASIMD) and FP must exist on all android aarch64 targets.
+            features: "+neon,+fp-armv8".to_string(),
+            supported_sanitizers: SanitizerSet::HWADDRESS,
+            ..super::android_base::opts()
+        },
     }
 }
index d48389d4a35c28e709c74029a37b6cf46d23085b..09ea7d33cfdb22e608eb5dbe7017d18b867f8ee6 100644 (file)
@@ -1,14 +1,11 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::freebsd_base::opts();
-    base.max_atomic_width = Some(128);
-
     Target {
         llvm_target: "aarch64-unknown-freebsd".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions { max_atomic_width: Some(128), ..super::freebsd_base::opts() },
     }
 }
index a07cd7db8897d190347fdb41c487cb3d27224ead..3e92ecbae054cc429c1ab49d97c698250ffeee67 100644 (file)
@@ -1,23 +1,20 @@
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_gnu_base::opts();
-    base.max_atomic_width = Some(128);
-    base.supported_sanitizers = SanitizerSet::ADDRESS
-        | SanitizerSet::LEAK
-        | SanitizerSet::MEMORY
-        | SanitizerSet::THREAD
-        | SanitizerSet::HWADDRESS;
-
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}_mcount".to_string(),
-            ..base
+            max_atomic_width: Some(128),
+            supported_sanitizers: SanitizerSet::ADDRESS
+                | SanitizerSet::LEAK
+                | SanitizerSet::MEMORY
+                | SanitizerSet::THREAD
+                | SanitizerSet::HWADDRESS,
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index f2d7576280fd98e2e1121839a10cded3891c1a61..e2618447f2810e69166efb79abbb87f2878a986e 100644 (file)
@@ -1,18 +1,15 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_gnu_base::opts();
-    base.max_atomic_width = Some(128);
-
     Target {
         llvm_target: "aarch64-unknown-linux-gnu_ilp32".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            max_atomic_width: Some(128),
             mcount: "\u{1}_mcount".to_string(),
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 7bbfc8ec0f7b058c7192b566f0b3168d23d4aa25..6a16b4ce419647f0569220f47e35f6f68540b0c1 100644 (file)
@@ -9,10 +9,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            mcount: "\u{1}_mcount".to_string(),
-            ..base
-        },
+        options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base },
     }
 }
index 09efbdbb293fea00055eacd0407cffa73488626f..4042028e2dc982a9b30065de0b33f2249ca1116e 100644 (file)
@@ -1,15 +1,15 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::netbsd_base::opts();
-    base.max_atomic_width = Some(128);
-    base.unsupported_abis = super::arm_base::unsupported_abis();
-
     Target {
         llvm_target: "aarch64-unknown-netbsd".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { mcount: "__mcount".to_string(), ..base },
+        options: TargetOptions {
+            mcount: "__mcount".to_string(),
+            max_atomic_width: Some(128),
+            ..super::netbsd_base::opts()
+        },
     }
 }
index de92b167f00ecea294a936b11b99efb7afbd0ba9..9d3652790108c685326e95b0b8131d8981556fba 100644 (file)
@@ -18,7 +18,6 @@ pub fn target() -> Target {
         disable_redzone: true,
         max_atomic_width: Some(128),
         panic_strategy: PanicStrategy::Abort,
-        unsupported_abis: super::arm_base::unsupported_abis(),
         ..Default::default()
     };
     Target {
index 2566eeae14a69ec81b2e8cc6a5fa046f3d75c3f3..482db0c53420e70ad8caeb0b705552bf263160fc 100644 (file)
@@ -18,7 +18,6 @@ pub fn target() -> Target {
         disable_redzone: true,
         max_atomic_width: Some(128),
         panic_strategy: PanicStrategy::Abort,
-        unsupported_abis: super::arm_base::unsupported_abis(),
         ..Default::default()
     };
     Target {
index 83ba1ecd1d3e3e3e22dd3eabdc63005b4f40caf3..193f98142102881345200b54185ba05c8f9d6e1d 100644 (file)
@@ -1,15 +1,11 @@
-use crate::spec::Target;
+use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::openbsd_base::opts();
-    base.max_atomic_width = Some(128);
-    base.unsupported_abis = super::arm_base::unsupported_abis();
-
     Target {
         llvm_target: "aarch64-unknown-openbsd".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: base,
+        options: TargetOptions { max_atomic_width: Some(128), ..super::openbsd_base::opts() },
     }
 }
index beb8ce30cc93ba5d164b8365d4451ac310ace329..66140060f8e33d84f6bb868ffe585e1641e025e8 100644 (file)
@@ -1,14 +1,11 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::vxworks_base::opts();
-    base.max_atomic_width = Some(128);
-
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions { max_atomic_width: Some(128), ..super::vxworks_base::opts() },
     }
 }
index a026a623f78663c4f78c33439540d7b1680597d7..ee36090c549513241c403c00020904780a90119b 100644 (file)
@@ -8,16 +8,11 @@
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum Abi {
-    // Multiplatform / generic ABIs
-    //
-    // These ABIs come first because every time we add a new ABI, we
-    // have to re-bless all the hashing tests. These are used in many
-    // places, so giving them stable values reduces test churn. The
-    // specific values are meaningless.
+    // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
+    // hashing tests. These are used in many places, so giving them stable values reduces test
+    // churn. The specific values are meaningless.
     Rust,
     C { unwind: bool },
-
-    // Single platform ABIs
     Cdecl,
     Stdcall { unwind: bool },
     Fastcall,
@@ -35,8 +30,6 @@ pub enum Abi {
     AvrNonBlockingInterrupt,
     CCmseNonSecureCall,
     Wasm,
-
-    // Multiplatform / generic ABIs
     System { unwind: bool },
     RustIntrinsic,
     RustCall,
@@ -50,48 +43,38 @@ pub struct AbiData {
 
     /// Name of this ABI as we like it called.
     name: &'static str,
-
-    /// A generic ABI is supported on all platforms.
-    generic: bool,
 }
 
 #[allow(non_upper_case_globals)]
 const AbiDatas: &[AbiData] = &[
-    // Cross-platform ABIs
-    AbiData { abi: Abi::Rust, name: "Rust", generic: true },
-    AbiData { abi: Abi::C { unwind: false }, name: "C", generic: true },
-    AbiData { abi: Abi::C { unwind: true }, name: "C-unwind", generic: true },
-    // Platform-specific ABIs
-    AbiData { abi: Abi::Cdecl, name: "cdecl", generic: false },
-    AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall", generic: false },
-    AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind", generic: false },
-    AbiData { abi: Abi::Fastcall, name: "fastcall", generic: false },
-    AbiData { abi: Abi::Vectorcall, name: "vectorcall", generic: false },
-    AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall", generic: false },
-    AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind", generic: false },
-    AbiData { abi: Abi::Aapcs, name: "aapcs", generic: false },
-    AbiData { abi: Abi::Win64, name: "win64", generic: false },
-    AbiData { abi: Abi::SysV64, name: "sysv64", generic: false },
-    AbiData { abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
-    AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false },
-    AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
-    AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false },
-    AbiData { abi: Abi::EfiApi, name: "efiapi", generic: false },
-    AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt", generic: false },
-    AbiData {
-        abi: Abi::AvrNonBlockingInterrupt,
-        name: "avr-non-blocking-interrupt",
-        generic: false,
-    },
-    AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false },
-    AbiData { abi: Abi::Wasm, name: "wasm", generic: false },
-    // Cross-platform ABIs
-    AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true },
-    AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true },
-    AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
-    AbiData { abi: Abi::RustCall, name: "rust-call", generic: true },
-    AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
-    AbiData { abi: Abi::Unadjusted, name: "unadjusted", generic: true },
+    AbiData { abi: Abi::Rust, name: "Rust" },
+    AbiData { abi: Abi::C { unwind: false }, name: "C" },
+    AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
+    AbiData { abi: Abi::Cdecl, name: "cdecl" },
+    AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" },
+    AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
+    AbiData { abi: Abi::Fastcall, name: "fastcall" },
+    AbiData { abi: Abi::Vectorcall, name: "vectorcall" },
+    AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" },
+    AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
+    AbiData { abi: Abi::Aapcs, name: "aapcs" },
+    AbiData { abi: Abi::Win64, name: "win64" },
+    AbiData { abi: Abi::SysV64, name: "sysv64" },
+    AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" },
+    AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
+    AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
+    AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" },
+    AbiData { abi: Abi::EfiApi, name: "efiapi" },
+    AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
+    AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
+    AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
+    AbiData { abi: Abi::Wasm, name: "wasm" },
+    AbiData { abi: Abi::System { unwind: false }, name: "system" },
+    AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
+    AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
+    AbiData { abi: Abi::RustCall, name: "rust-call" },
+    AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
+    AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
 ];
 
 /// Returns the ABI with the given name (if any).
@@ -163,10 +146,6 @@ pub fn data(self) -> &'static AbiData {
     pub fn name(self) -> &'static str {
         self.data().name
     }
-
-    pub fn generic(self) -> bool {
-        self.data().generic
-    }
 }
 
 impl fmt::Display for Abi {
diff --git a/compiler/rustc_target/src/spec/arm_base.rs b/compiler/rustc_target/src/spec/arm_base.rs
deleted file mode 100644 (file)
index 01f5733..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-use crate::spec::abi::Abi;
-
-// All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
-pub fn unsupported_abis() -> Vec<Abi> {
-    vec![
-        Abi::Stdcall { unwind: false },
-        Abi::Stdcall { unwind: true },
-        Abi::Fastcall,
-        Abi::Vectorcall,
-        Abi::Thiscall { unwind: false },
-        Abi::Thiscall { unwind: true },
-        Abi::Win64,
-        Abi::SysV64,
-    ]
-}
index 43537569e7d4edba75630a5c7cca003f20698d61..f2430830afca584484d819d4de987b1e0f62e490 100644 (file)
@@ -1,16 +1,16 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::android_base::opts();
-    // https://developer.android.com/ndk/guides/abis.html#armeabi
-    base.features = "+strict-align,+v5te".to_string();
-    base.max_atomic_width = Some(32);
-
     Target {
         llvm_target: "arm-linux-androideabi".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions {
+            // https://developer.android.com/ndk/guides/abis.html#armeabi
+            features: "+strict-align,+v5te".to_string(),
+            max_atomic_width: Some(32),
+            ..super::android_base::opts()
+        },
     }
 }
index c41cf6e521a1d8875623f14d22d5badda9bbfe60..225db0032a89d2d9815426c63f368381dc92f200 100644 (file)
@@ -1,19 +1,16 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_gnu_base::opts();
-    base.max_atomic_width = Some(64);
     Target {
         llvm_target: "arm-unknown-linux-gnueabi".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+strict-align,+v6".to_string(),
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index f2143966c1dcd6b06e9382bc51f9252ee25e60aa..33703195ee751a3df2fcf400a772e8c34e89db3c 100644 (file)
@@ -1,19 +1,16 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_gnu_base::opts();
-    base.max_atomic_width = Some(64);
     Target {
         llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+strict-align,+v6,+vfp2,-d32".to_string(),
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 53ff1001c204d68fd395667fcca762f671d9c1fc..850844993f95cca9337977e9e90cee5fdba87306 100644 (file)
@@ -1,12 +1,6 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_musl_base::opts();
-
-    // Most of these settings are copied from the arm_unknown_linux_gnueabi
-    // target.
-    base.features = "+strict-align,+v6".to_string();
-    base.max_atomic_width = Some(64);
     Target {
         // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
         // to determine the calling convention and float ABI, and it doesn't
@@ -16,9 +10,12 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            // Most of these settings are copied from the arm_unknown_linux_gnueabi
+            // target.
+            features: "+strict-align,+v6".to_string(),
+            max_atomic_width: Some(64),
             mcount: "\u{1}mcount".to_string(),
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index 6d8a5f9f88bbbd8339ffcbbbfa9cc5cacd2f2e6f..ff69c462e8ed233d9ef438d998f3b206d8b0e5a2 100644 (file)
@@ -1,12 +1,6 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::linux_musl_base::opts();
-
-    // Most of these settings are copied from the arm_unknown_linux_gnueabihf
-    // target.
-    base.features = "+strict-align,+v6,+vfp2,-d32".to_string();
-    base.max_atomic_width = Some(64);
     Target {
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and it
@@ -16,9 +10,12 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            // Most of these settings are copied from the arm_unknown_linux_gnueabihf
+            // target.
+            features: "+strict-align,+v6,+vfp2,-d32".to_string(),
+            max_atomic_width: Some(64),
             mcount: "\u{1}mcount".to_string(),
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index 255740cb9c045e9293086afc6454dfc7ca875b92..547f48c5d3b61d2ad92fd068f688e4e82d9c8279 100644 (file)
@@ -10,7 +10,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
@@ -19,7 +18,6 @@ pub fn target() -> Target {
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             emit_debug_gdb_scripts: false,
             ..Default::default()
         },
index eb82e4d17b0ef1ea8cf81a2751715161c4408210..f4f61e87ab9448e2072446228d00c62ba43381bb 100644 (file)
@@ -10,7 +10,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
@@ -20,7 +19,6 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             emit_debug_gdb_scripts: false,
             ..Default::default()
         },
index e1ba72bf83b9c8ad78e6f4333dd8edbeeb61b4d8..8a289fee7812f4456d9320d5bdee9cdefbf6badc 100644 (file)
@@ -1,21 +1,18 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::linux_gnu_base::opts();
     Target {
         llvm_target: "armv4t-unknown-linux-gnueabi".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+soft-float,+strict-align".to_string(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
             has_thumb_interworking: true,
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 3ac8d53564d7d73c70685b2e4a5ce99c3a4452e3..177ab453b04c49ec05d7ebe09eb9c63e20dcab3a 100644 (file)
@@ -1,21 +1,18 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::linux_gnu_base::opts();
     Target {
         llvm_target: "armv5te-unknown-linux-gnueabi".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+soft-float,+strict-align".to_string(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
             has_thumb_interworking: true,
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 40d405c30a2bd13a69f6ba3ecc4a1ea95d73376c..1f084443bd991f608504ca20b38f6c6637d4dd54 100644 (file)
@@ -1,8 +1,8 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::linux_musl_base::opts();
     Target {
+        // FIXME: this comment below does not seem applicable?
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
@@ -10,15 +10,13 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+soft-float,+strict-align".to_string(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}mcount".to_string(),
             has_thumb_interworking: true,
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index 3eb0f4db83367f8de5659d246425f08da6f1d1a9..4e5b714bded7c93f9829822ca4d774192a5697c5 100644 (file)
@@ -10,10 +10,8 @@ pub fn target() -> Target {
             features: "+soft-float,+strict-align".to_string(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
             has_thumb_interworking: true,
-
             ..super::linux_uclibc_base::opts()
         },
     }
index a149bd983b71b2f89b272dee22c8547783705f13..08fc51e8a8b57d86b1b6e95ee49ea70e976c6953 100644 (file)
@@ -1,20 +1,17 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::freebsd_base::opts();
     Target {
         llvm_target: "armv6-unknown-freebsd-gnueabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             env: "gnueabihf".to_string(),
             features: "+v6,+vfp2,-d32".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            ..base
+            ..super::freebsd_base::opts()
         },
     }
 }
index 6c81a458b9b1bdac2bdce8bb371f35101fa0bf9e..b109aa1e1ab152ab9296b71247ff7d95f5295f71 100644 (file)
@@ -1,20 +1,17 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::netbsd_base::opts();
-    base.max_atomic_width = Some(64);
     Target {
         llvm_target: "armv6-unknown-netbsdelf-eabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             env: "eabihf".to_string(),
             features: "+v6,+vfp2,-d32".to_string(),
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            max_atomic_width: Some(64),
             mcount: "__mcount".to_string(),
-            ..base
+            ..super::netbsd_base::opts()
         },
     }
 }
index 051a394657cbd466fd1125c53505a4378e492521..2f228688f43c55c43056ffc63de52982c998e6cf 100644 (file)
@@ -2,7 +2,6 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::Armv7);
     Target {
         llvm_target: "armv7-apple-ios".to_string(),
         pointer_width: 32,
@@ -11,8 +10,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            ..base
+            ..opts("ios", Arch::Armv7)
         },
     }
 }
index 02a1191463e3c0f16806d14ea5fd6f577827641a..821080ec07de8f370dad99885073d2471ce466ea 100644 (file)
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string();
-    base.max_atomic_width = Some(64);
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string());
-
     Target {
         llvm_target: "armv7-none-linux-android".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions {
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(),
+            max_atomic_width: Some(64),
+            ..base
+        },
     }
 }
index 6f24c6818fcd0c0df6d93ab4a1b035891b3a22a2..190d3bb691aab8a8ab63d3cc79f2938a18b67c6a 100644 (file)
@@ -1,20 +1,17 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::freebsd_base::opts();
     Target {
         llvm_target: "armv7-unknown-freebsd-gnueabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             env: "gnueabihf".to_string(),
             features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            ..base
+            ..super::freebsd_base::opts()
         },
     }
 }
index f6fe88de37cf6958cf4dc279bd6c9f7f5573f36d..088a8cf753402ac32b6987533828ad742cc71066 100644 (file)
@@ -4,19 +4,16 @@
 // hardfloat.
 
 pub fn target() -> Target {
-    let base = super::linux_gnu_base::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+v7,+thumb2,+soft-float,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 5f0f47dd39776517d534e4c2c8187335a2eb87bf..521053ec2d3178f76c4cd6d13bfe3b4fc09cc52b 100644 (file)
@@ -4,20 +4,17 @@
 // thumb-mode. See the thumbv7neon variant for enabling both.
 
 pub fn target() -> Target {
-    let base = super::linux_gnu_base::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index c888fc2d4a389f9fe70345ba58d40d771879ff26..0ee2c3e45e0b1d538c2ce9c7092d9f80d70ecfb1 100644 (file)
@@ -4,7 +4,6 @@
 // hardfloat.
 
 pub fn target() -> Target {
-    let base = super::linux_musl_base::opts();
     // Most of these settings are copied from the armv7_unknown_linux_gnueabi
     // target.
     Target {
@@ -19,9 +18,8 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+thumb2,+soft-float,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}mcount".to_string(),
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index 2432ea519a8ecf8e58cb3ae36bd33aad32599d84..a6ce382c7a6661caa20b80d433af52ff6ddc11df 100644 (file)
@@ -3,7 +3,6 @@
 // This target is for musl Linux on ARMv7 without thumb-mode or NEON.
 
 pub fn target() -> Target {
-    let base = super::linux_musl_base::opts();
     Target {
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
@@ -18,9 +17,8 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}mcount".to_string(),
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index 4fae3a8d0bf45b8060554d332734960e36b40bcb..e509dcaddaa371de692697c9251181c870f2e8c1 100644 (file)
@@ -1,20 +1,17 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::netbsd_base::opts();
     Target {
         llvm_target: "armv7-unknown-netbsdelf-eabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             env: "eabihf".to_string(),
             features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "__mcount".to_string(),
-            ..base
+            ..super::netbsd_base::opts()
         },
     }
 }
index 9fe7098a85f00c42c37ed3f7808ad7211ad387ce..0aabf2fe48669915b949a5c8edb3f6b17c4e16d0 100644 (file)
@@ -1,7 +1,6 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = super::vxworks_base::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
         pointer_width: 32,
@@ -11,8 +10,7 @@ pub fn target() -> Target {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            ..base
+            ..super::vxworks_base::opts()
         },
     }
 }
index 74deab0191652355a2ea14d00a23ec56e7d29275..bd703ee3e45e4f78bc61900428b9116342fdb3c3 100644 (file)
@@ -26,7 +26,6 @@ pub fn target() -> Target {
         disable_redzone: true,
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
-        unsupported_abis: super::arm_base::unsupported_abis(),
         emit_debug_gdb_scripts: false,
         ..Default::default()
     };
index c5c720f5fbde43f2d05e8901a4aace8ce36b7cd5..ad86ae1cedcc012ebd5ca66c98eecb5c1ae8dc4e 100644 (file)
@@ -17,7 +17,6 @@ pub fn target() -> Target {
         disable_redzone: true,
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
-        unsupported_abis: super::arm_base::unsupported_abis(),
         emit_debug_gdb_scripts: false,
         ..Default::default()
     };
index 3f49bd87869374a453a8b7eae7a16740b6f0b8f2..c07d6adc37eb5ceb0be80280a8387f0794a0d3ef 100644 (file)
@@ -17,7 +17,6 @@ pub fn target() -> Target {
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             emit_debug_gdb_scripts: false,
             ..Default::default()
         },
index 9b2e8a8058fe7741f4222487e5f29652ef97caff..fbf2f8e9b72786c7a71bbdf122647269ea01ae23 100644 (file)
@@ -18,7 +18,6 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             emit_debug_gdb_scripts: false,
             ..Default::default()
         },
index be74136a2d67596a577d0142d9eb7bcdf568d574..2a48e7b62143f0b4268213270488c6f3cb04eeb7 100644 (file)
@@ -2,7 +2,6 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::Armv7s);
     Target {
         llvm_target: "armv7s-apple-ios".to_string(),
         pointer_width: 32,
@@ -11,8 +10,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            ..base
+            ..opts("ios", Arch::Armv7s)
         },
     }
 }
index 764cc735d75d1b1d02b75d425b075e8153243e4e..4fa6e12f5ba86177854f80f16d0bcd74d496ad35 100644 (file)
@@ -1,5 +1,5 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions};
-use crate::{abi::Endian, spec::abi::Abi};
 
 pub fn opts(endian: Endian) -> TargetOptions {
     TargetOptions {
@@ -21,22 +21,6 @@ pub fn opts(endian: Endian) -> TargetOptions {
         requires_lto: false,
         singlethread: true,
         max_atomic_width: Some(64),
-        unsupported_abis: vec![
-            Abi::Cdecl,
-            Abi::Stdcall { unwind: false },
-            Abi::Stdcall { unwind: true },
-            Abi::Fastcall,
-            Abi::Vectorcall,
-            Abi::Thiscall { unwind: false },
-            Abi::Thiscall { unwind: true },
-            Abi::Aapcs,
-            Abi::Win64,
-            Abi::SysV64,
-            Abi::PtxKernel,
-            Abi::Msp430Interrupt,
-            Abi::X86Interrupt,
-            Abi::AmdGpuKernel,
-        ],
         ..Default::default()
     }
 }
index 110c8dd80ea77e57f2632cd5a18f3cb08d96a57b..5955baa31dbacb42e8b4bc5b72ee5c523483a407 100644 (file)
@@ -2,7 +2,6 @@
 //!
 //! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
 
-use crate::spec::abi::Abi;
 use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
 use crate::spec::{PanicStrategy, Target, TargetOptions};
 
@@ -22,16 +21,6 @@ pub fn target() -> Target {
             linker: Some("rust-lld".to_owned()),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
-            unsupported_abis: vec![
-                Abi::Stdcall { unwind: false },
-                Abi::Stdcall { unwind: true },
-                Abi::Fastcall,
-                Abi::Vectorcall,
-                Abi::Thiscall { unwind: false },
-                Abi::Thiscall { unwind: true },
-                Abi::Win64,
-                Abi::SysV64,
-            ],
             emit_debug_gdb_scripts: false,
             ..Default::default()
         },
index cfdae9623f34a7768a8960099377f11d6fc63e39..0a5f8c17c63a6cc201a779482bc12ec9ca0ff66f 100644 (file)
@@ -55,7 +55,6 @@
 mod android_base;
 mod apple_base;
 mod apple_sdk_base;
-mod arm_base;
 mod avr_gnu_base;
 mod bpf_base;
 mod dragonfly_base;
@@ -75,7 +74,6 @@
 mod netbsd_base;
 mod openbsd_base;
 mod redox_base;
-mod riscv_base;
 mod solaris_base;
 mod thumb_base;
 mod uefi_msvc_base;
@@ -1226,11 +1224,6 @@ pub struct TargetOptions {
     /// Panic strategy: "unwind" or "abort"
     pub panic_strategy: PanicStrategy,
 
-    /// A list of ABIs unsupported by the current target. Note that generic ABIs
-    /// are considered to be supported on all platforms and cannot be marked
-    /// unsupported.
-    pub unsupported_abis: Vec<Abi>,
-
     /// Whether or not linking dylibs to a static CRT is allowed.
     pub crt_static_allows_dylibs: bool,
     /// Whether or not the CRT is statically linked by default.
@@ -1412,7 +1405,6 @@ fn default() -> TargetOptions {
             max_atomic_width: None,
             atomic_cas: true,
             panic_strategy: PanicStrategy::Unwind,
-            unsupported_abis: vec![],
             crt_static_allows_dylibs: false,
             crt_static_default: false,
             crt_static_respected: false,
@@ -1465,40 +1457,88 @@ impl Target {
     /// Given a function ABI, turn it into the correct ABI for this target.
     pub fn adjust_abi(&self, abi: Abi) -> Abi {
         match abi {
-            Abi::System { unwind } => {
-                if self.is_like_windows && self.arch == "x86" {
-                    Abi::Stdcall { unwind }
-                } else {
-                    Abi::C { unwind }
-                }
-            }
-            // These ABI kinds are ignored on non-x86 Windows targets.
-            // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
-            // and the individual pages for __stdcall et al.
-            Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => {
-                if self.is_like_windows && self.arch != "x86" { Abi::C { unwind } } else { abi }
-            }
-            Abi::Fastcall | Abi::Vectorcall => {
-                if self.is_like_windows && self.arch != "x86" {
-                    Abi::C { unwind: false }
-                } else {
-                    abi
-                }
-            }
-            Abi::EfiApi => {
-                if self.arch == "x86_64" {
-                    Abi::Win64
-                } else {
-                    Abi::C { unwind: false }
-                }
+            Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
+            Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
+                Abi::Stdcall { unwind }
             }
+            Abi::System { unwind } => Abi::C { unwind },
+            Abi::EfiApi if self.arch == "x86_64" => Abi::Win64,
+            Abi::EfiApi => Abi::C { unwind: false },
 
-            Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }),
+            // See commentary in `is_abi_supported`.
+            Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
+            Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
+            Abi::Fastcall if self.arch == "x86" => abi,
+            Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
+            Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false },
 
             abi => abi,
         }
     }
 
+    /// Returns a None if the UNSUPPORTED_CALLING_CONVENTIONS lint should be emitted
+    pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
+        use Abi::*;
+        Some(match abi {
+            Rust
+            | C { .. }
+            | System { .. }
+            | RustIntrinsic
+            | RustCall
+            | PlatformIntrinsic
+            | Unadjusted
+            | Cdecl
+            | EfiApi => true,
+            X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
+            Aapcs | CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+            Win64 | SysV64 => self.arch == "x86_64",
+            PtxKernel => self.arch == "nvptx64",
+            Msp430Interrupt => self.arch == "msp430",
+            AmdGpuKernel => self.arch == "amdgcn",
+            AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
+            Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
+            // On windows these fall-back to platform native calling convention (C) when the
+            // architecture is not supported.
+            //
+            // This is I believe a historical accident that has occurred as part of Microsoft
+            // striving to allow most of the code to "just" compile when support for 64-bit x86
+            // was added and then later again, when support for ARM architectures was added.
+            //
+            // This is well documented across MSDN. Support for this in Rust has been added in
+            // #54576. This makes much more sense in context of Microsoft's C++ than it does in
+            // Rust, but there isn't much leeway remaining here to change it back at the time this
+            // comment has been written.
+            //
+            // Following are the relevant excerpts from the MSDN documentation.
+            //
+            // > The __vectorcall calling convention is only supported in native code on x86 and
+            // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
+            // > ...
+            // > On ARM machines, __vectorcall is accepted and ignored by the compiler.
+            //
+            // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
+            //
+            // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
+            //
+            // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
+            //
+            // > In most cases, keywords or compiler switches that specify an unsupported
+            // > convention on a particular platform are ignored, and the platform default
+            // > convention is used.
+            //
+            // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
+            Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall if self.is_like_windows => {
+                true
+            }
+            // Outside of Windows we want to only support these calling conventions for the
+            // architectures for which these calling conventions are actually well defined.
+            Stdcall { .. } | Fastcall | Thiscall { .. } if self.arch == "x86" => true,
+            Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
+            // Return a `None` for other cases so that we know to emit a future compat lint.
+            Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall => return None,
+        })
+    }
+
     /// Minimum integer size in bits that this target can perform atomic
     /// operations on.
     pub fn min_atomic_width(&self) -> u64 {
@@ -1511,10 +1551,6 @@ pub fn max_atomic_width(&self) -> u64 {
         self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
     }
 
-    pub fn is_abi_supported(&self, abi: Abi) -> bool {
-        abi.generic() || !self.unsupported_abis.contains(&abi)
-    }
-
     /// Loads a target descriptor from a JSON object.
     pub fn from_json(mut obj: Json) -> Result<(Target, TargetWarnings), String> {
         // While ugly, this code must remain this way to retain
@@ -1974,36 +2010,6 @@ macro_rules! key {
         key!(supported_sanitizers, SanitizerSet)?;
         key!(default_adjusted_cabi, Option<Abi>)?;
 
-        // NB: The old name is deprecated, but support for it is retained for
-        // compatibility.
-        for name in ["abi-blacklist", "unsupported-abis"].iter() {
-            if let Some(j) = obj.remove_key(name) {
-                if let Some(array) = Json::as_array(&j) {
-                    for name in array.iter().filter_map(|abi| abi.as_string()) {
-                        match lookup_abi(name) {
-                            Some(abi) => {
-                                if abi.generic() {
-                                    return Err(format!(
-                                        "The ABI \"{}\" is considered to be supported on all \
-                                        targets and cannot be marked unsupported",
-                                        abi
-                                    ));
-                                }
-
-                                base.unsupported_abis.push(abi)
-                            }
-                            None => {
-                                return Err(format!(
-                                    "Unknown ABI \"{}\" in target specification",
-                                    name
-                                ));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
         // Each field should have been read using `Json::remove_key` so any keys remaining are unused.
         let remaining_keys = obj.as_object().ok_or("Expected JSON object for target")?.keys();
         Ok((
@@ -2241,17 +2247,6 @@ macro_rules! target_option_val {
             d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
         }
 
-        if default.unsupported_abis != self.unsupported_abis {
-            d.insert(
-                "unsupported-abis".to_string(),
-                self.unsupported_abis
-                    .iter()
-                    .map(|&name| Abi::name(name).to_json())
-                    .collect::<Vec<_>>()
-                    .to_json(),
-            );
-        }
-
         Json::Object(d)
     }
 }
index 97960a75b095f43a2e6be7f738cd96d5269579f6..083262cf3514c2509eada87ea4934c46b023c3d8 100644 (file)
@@ -1,4 +1,3 @@
-use crate::spec::abi::Abi;
 use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -45,25 +44,6 @@ pub fn target() -> Target {
             // produce kernel functions that call other kernel functions.
             // This behavior is not supported by PTX ISA.
             merge_functions: MergeFunctions::Disabled,
-
-            // FIXME: enable compilation tests for the target and
-            // create the tests for this.
-            unsupported_abis: vec![
-                Abi::Cdecl,
-                Abi::Stdcall { unwind: false },
-                Abi::Stdcall { unwind: true },
-                Abi::Fastcall,
-                Abi::Vectorcall,
-                Abi::Thiscall { unwind: false },
-                Abi::Thiscall { unwind: true },
-                Abi::Aapcs,
-                Abi::Win64,
-                Abi::SysV64,
-                Abi::Msp430Interrupt,
-                Abi::X86Interrupt,
-                Abi::AmdGpuKernel,
-            ],
-
             ..Default::default()
         },
     }
index cf5e0201d08bf6b217f67a1e69fb2d8d48597b39..a9cdad1a8b1b4cd1f8384efd0d50161a682a4e77 100644 (file)
@@ -7,7 +7,6 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
         arch: "riscv32".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv32".to_string(),
             features: "+m,+a,+f,+d,+c".to_string(),
index e5fbd09297f6574064294fdd5d661d9895a62783..a64a82d55b90cef843e50a7e53a3f4ee46eaa22f 100644 (file)
@@ -7,7 +7,6 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
         arch: "riscv32".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv32".to_string(),
             features: "+m,+a,+f,+d,+c".to_string(),
index 88a22f25ff47be86adaa69c675d8ca33f80eb337..16d37218f4156ae4b2315abda1ece883dfc62925 100644 (file)
@@ -18,7 +18,6 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             eh_frame_header: false,
             ..Default::default()
         },
index b406eec1e75024d9194bb0743f127a3198849a9b..b53bae6cb56cd2b5919b7a330c1bda384719a28e 100644 (file)
@@ -18,7 +18,6 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             eh_frame_header: false,
             ..Default::default()
         },
index 89d760e082f19d05f36d7ee9887681b045a5fc4f..9a23def199676c39758eb1e9edc39f0420a6ed48 100644 (file)
@@ -19,7 +19,6 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             eh_frame_header: false,
             ..Default::default()
         },
index 84f28413fcbcea0d03729b590706a42799b21454..02d44b5ed7e7981fbf652a250634c71bfb751f67 100644 (file)
@@ -7,7 +7,6 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
         arch: "riscv64".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".to_string(),
             features: "+m,+a,+f,+d,+c".to_string(),
index 0232b15e8c2691476b1ba83b32b3c6da2dd11323..3754750e48d23e80c386949be640650cdb8beaea 100644 (file)
@@ -7,7 +7,6 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
         arch: "riscv64".to_string(),
         options: TargetOptions {
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".to_string(),
             features: "+m,+a,+f,+d,+c".to_string(),
index 481bce05a08e52208475ffddb4c496441e5acfe3..f527a6cd26d827b137666373bc947307260bfc9b 100644 (file)
@@ -20,7 +20,6 @@ pub fn target() -> Target {
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             eh_frame_header: false,
             ..Default::default()
         },
index 3e4afd446dda9eda19c81e1684a00b1cc38f152a..8b1ba88e67f27677c294afed2533349408c00363 100644 (file)
@@ -19,7 +19,6 @@ pub fn target() -> Target {
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
-            unsupported_abis: super::riscv_base::unsupported_abis(),
             eh_frame_header: false,
             ..Default::default()
         },
diff --git a/compiler/rustc_target/src/spec/riscv_base.rs b/compiler/rustc_target/src/spec/riscv_base.rs
deleted file mode 100644 (file)
index 5bcbb2e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-use crate::spec::abi::Abi;
-
-// All the calling conventions trigger an assertion(Unsupported calling
-// convention) in llvm on RISCV
-pub fn unsupported_abis() -> Vec<Abi> {
-    vec![
-        Abi::Cdecl,
-        Abi::Stdcall { unwind: false },
-        Abi::Stdcall { unwind: true },
-        Abi::Fastcall,
-        Abi::Vectorcall,
-        Abi::Thiscall { unwind: false },
-        Abi::Thiscall { unwind: true },
-        Abi::Aapcs,
-        Abi::Win64,
-        Abi::SysV64,
-        Abi::PtxKernel,
-        Abi::Msp430Interrupt,
-        Abi::X86Interrupt,
-        Abi::AmdGpuKernel,
-    ]
-}
index fbe4dd5b501801250031909865b2d6dd86b36f96..bac1203980eb010720829fe3570be0bcb8a20497 100644 (file)
@@ -43,7 +43,6 @@ pub fn opts() -> TargetOptions {
         // Similarly, one almost always never wants to use relocatable code because of the extra
         // costs it involves.
         relocation_model: RelocModel::Static,
-        unsupported_abis: super::arm_base::unsupported_abis(),
         // When this section is added a volatile load to its start address is also generated. This
         // volatile load is a footgun as it can end up loading an invalid memory address, depending
         // on how the user set up their linker scripts. This section adds pretty printer for stuff
index 1232daa577f233a3a1dfe430c108d6e105dbb3f2..369e6cd5e9326e4b85086bb0663d4e359dfea6aa 100644 (file)
@@ -2,7 +2,6 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
-
     // Prevent error LNK2013: BRANCH24(T) fixup overflow
     // The LBR optimization tries to eliminate branch islands,
     // but if the displacement is larger than can fit
@@ -17,20 +16,17 @@ pub fn target() -> Target {
         .or_default()
         .push(pre_link_args_msvc);
 
-    // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
-    // implemented for windows/arm in LLVM
-    base.panic_strategy = PanicStrategy::Abort;
-
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
         pointer_width: 32,
         data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             features: "+vfp3,+neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
+            // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+            // implemented for windows/arm in LLVM
+            panic_strategy: PanicStrategy::Abort,
             ..base
         },
     }
index e6a59f015c9935d8be0b94d209cc05412cdfadea..b44c0085005217b3cc225be14424e92ec9e62436 100644 (file)
@@ -1,14 +1,6 @@
 use crate::spec::{PanicStrategy, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::windows_uwp_msvc_base::opts();
-    base.max_atomic_width = Some(64);
-    base.has_elf_tls = true;
-
-    // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
-    // implemented for windows/arm in LLVM
-    base.panic_strategy = PanicStrategy::Abort;
-
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
         pointer_width: 32,
@@ -16,8 +8,12 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
         options: TargetOptions {
             features: "+vfp3,+neon".to_string(),
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            ..base
+            max_atomic_width: Some(64),
+            has_elf_tls: true,
+            // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+            // implemented for windows/arm in LLVM
+            panic_strategy: PanicStrategy::Abort,
+            ..super::windows_uwp_msvc_base::opts()
         },
     }
 }
index 58b0a9d22027999b5ebaab29ef48df5b164ac15e..14020b88695ac15a762739e8f31bd40e21ed98df 100644 (file)
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string();
-    base.max_atomic_width = Some(64);
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string());
-
     Target {
         llvm_target: "armv7-none-linux-android".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-        options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+        options: TargetOptions {
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
+            max_atomic_width: Some(64),
+            ..base
+        },
     }
 }
index 12d816d095b689e1ce92db232ec7b85aa30f8d87..4042d5394167695326012dc6c4a6efbc414ab384 100644 (file)
@@ -7,19 +7,16 @@
 // https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
 
 pub fn target() -> Target {
-    let base = super::linux_gnu_base::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
-
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
-            ..base
+            ..super::linux_gnu_base::opts()
         },
     }
 }
index 020de87147cb688c62a55d8f958c00516b2e0b57..318b864a9cf08ebcaf3b26319b7a8f35a98f4eb4 100644 (file)
@@ -7,7 +7,6 @@
 // https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
 
 pub fn target() -> Target {
-    let base = super::linux_musl_base::opts();
     Target {
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
@@ -22,9 +21,8 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
             max_atomic_width: Some(64),
-            unsupported_abis: super::arm_base::unsupported_abis(),
             mcount: "\u{1}mcount".to_string(),
-            ..base
+            ..super::linux_musl_base::opts()
         },
     }
 }
index ac2e0ebae32732cbe778c6e4896ffd30b5987a4c..969962e55b0df3e4fb963572e1e3e8b06b321da2 100644 (file)
@@ -53,7 +53,7 @@ fn next(&mut self) -> Option<Self::Item> {
         }
 
         // If we have reached the recursion limit, error gracefully.
-        if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) {
+        if !tcx.recursion_limit().value_within_limit(self.state.steps.len()) {
             if !self.silence_errors {
                 report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty);
             }
@@ -217,7 +217,7 @@ pub fn silence_errors(mut self) -> Self {
 
 pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
     // We've reached the recursion limit, error gracefully.
-    let suggested_limit = tcx.sess.recursion_limit() * 2;
+    let suggested_limit = tcx.recursion_limit() * 2;
     let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
     let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
     let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
index a9ffb5542b6df6aa4c36b31125145542e33a1f64..9fc907da2653e39474e300c3822a741dd2ab1d41 100644 (file)
@@ -1,13 +1,18 @@
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::outlives_bounds::InferCtxtExt as _;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
 use rustc_middle::traits::query::Fallible;
+use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::ToPredicate;
+use rustc_middle::ty::WithConstness;
 use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -32,8 +37,22 @@ fn partially_normalize_associated_types_in<T>(
     ) -> InferOk<'tcx, T>
     where
         T: TypeFoldable<'tcx>;
-}
 
+    /// Check whether a `ty` implements given trait(trait_def_id).
+    /// The inputs are:
+    ///
+    /// - the def-id of the trait
+    /// - the self type
+    /// - the *other* type parameters of the trait, excluding the self-type
+    /// - the parameter environment
+    fn type_implements_trait(
+        &self,
+        trait_def_id: DefId,
+        ty: Ty<'tcx>,
+        params: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> traits::EvaluationResult;
+}
 impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     fn type_is_copy_modulo_regions(
         &self,
@@ -79,6 +98,30 @@ fn partially_normalize_associated_types_in<T>(
         );
         InferOk { value, obligations }
     }
+
+    fn type_implements_trait(
+        &self,
+        trait_def_id: DefId,
+        ty: Ty<'tcx>,
+        params: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> traits::EvaluationResult {
+        debug!(
+            "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
+            trait_def_id, ty, params, param_env
+        );
+
+        let trait_ref =
+            ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };
+
+        let obligation = traits::Obligation {
+            cause: traits::ObligationCause::dummy(),
+            param_env,
+            recursion_depth: 0,
+            predicate: trait_ref.without_const().to_predicate(self.tcx),
+        };
+        self.evaluate_obligation_no_overflow(&obligation)
+    }
 }
 
 pub trait InferCtxtBuilderExt<'tcx> {
index dc765f5228b9dc39a39b8e1268ecdb768d28dad6..26a5a65ed360a51873534dd34250691e5022000a 100644 (file)
@@ -28,6 +28,7 @@
 use std::fmt;
 
 use super::InferCtxtPrivExt;
+use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 
@@ -687,15 +688,17 @@ fn suggest_add_reference_to_arg(
             return false;
         }
 
-        // Blacklist traits for which it would be nonsensical to suggest borrowing.
+        // List of traits for which it would be nonsensical to suggest borrowing.
         // For instance, immutable references are always Copy, so suggesting to
         // borrow would always succeed, but it's probably not what the user wanted.
-        let blacklist: Vec<_> =
-            [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized, LangItem::Send]
+        let mut never_suggest_borrow: Vec<_> =
+            [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
                 .iter()
                 .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok())
                 .collect();
 
+        never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap());
+
         let span = obligation.cause.span;
         let param_env = obligation.param_env;
         let trait_ref = trait_ref.skip_binder();
@@ -797,7 +800,7 @@ fn suggest_add_reference_to_arg(
                 ty::TraitRef::new(trait_ref.def_id, imm_substs),
                 trait_ref,
                 false,
-                &blacklist[..],
+                &never_suggest_borrow[..],
             ) {
                 return true;
             } else {
@@ -805,7 +808,7 @@ fn suggest_add_reference_to_arg(
                     ty::TraitRef::new(trait_ref.def_id, mut_substs),
                     trait_ref,
                     true,
-                    &blacklist[..],
+                    &never_suggest_borrow[..],
                 );
             }
         } else {
@@ -2310,7 +2313,7 @@ fn note_obligation_cause_code<T>(
     }
 
     fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit();
+        let current_limit = self.tcx.recursion_limit();
         let suggested_limit = current_limit * 2;
         err.help(&format!(
             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
@@ -2349,12 +2352,12 @@ fn suggest_await_before_try(
                 }
                 let self_ty = self.tcx.erase_regions(self_ty);
 
-                let impls_future = self.tcx.type_implements_trait((
+                let impls_future = self.type_implements_trait(
                     future_trait,
                     self_ty.skip_binder(),
                     ty::List::empty(),
                     obligation.param_env,
-                ));
+                );
 
                 let item_def_id = self
                     .tcx
index e48aab6f46f4b088733912ab62631e3efdeafd17..3a80e720e8c4b8560f2aed49e13628061de01430 100644 (file)
@@ -31,7 +31,7 @@
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::{
-    self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
+    self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
     COMMON_VTABLE_ENTRIES,
 };
 use rustc_span::Span;
@@ -541,44 +541,6 @@ fn vtable_trait_first_method_offset<'tcx>(
     vtable_base
 }
 
-/// Check whether a `ty` implements given trait(trait_def_id).
-/// See query definition for details.
-fn type_implements_trait<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        DefId,    // trait_def_id,
-        Ty<'tcx>, // type
-        SubstsRef<'tcx>,
-        ParamEnv<'tcx>,
-    ),
-) -> EvaluationResult {
-    let (trait_def_id, ty, params, param_env) = key;
-
-    debug!(
-        "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
-        trait_def_id, ty, params, param_env
-    );
-
-    let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };
-
-    // FIXME(#86868): If there are inference variables anywhere, just give up and assume
-    // we don't know the answer. This works around the ICEs that would result from
-    // using those inference variables within the `infer_ctxt` we create below.
-    // Really we should be using canonicalized variables, or perhaps removing
-    // this query altogether.
-    if (trait_ref, param_env).needs_infer() {
-        return EvaluationResult::EvaluatedToUnknown;
-    }
-
-    let obligation = Obligation {
-        cause: ObligationCause::dummy(),
-        param_env,
-        recursion_depth: 0,
-        predicate: trait_ref.without_const().to_predicate(tcx),
-    };
-    tcx.infer_ctxt().enter(|infcx| infcx.evaluate_obligation_no_overflow(&obligation))
-}
-
 pub fn provide(providers: &mut ty::query::Providers) {
     object_safety::provide(providers);
     structural_match::provide(providers);
@@ -587,7 +549,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         specializes: specialize::specializes,
         codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
         vtable_entries,
-        type_implements_trait,
         subst_and_check_impossible_predicates,
         mir_abstract_const: |tcx, def_id| {
             let def_id = def_id.expect_local();
index 352829234a41a2c25037fd4711bb34359ffe8b9c..0e685205069cb7cd7cd722706378973a67e3e3a8 100644 (file)
@@ -344,7 +344,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     Reveal::UserFacing => ty,
 
                     Reveal::All => {
-                        let recursion_limit = self.tcx().sess.recursion_limit();
+                        let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
@@ -726,7 +726,7 @@ fn project_type<'cx, 'tcx>(
 ) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
     debug!(?obligation, "project_type");
 
-    if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
+    if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
         debug!("project: overflow!");
         // This should really be an immediate error, but some existing code
         // relies on being able to recover from this.
index eb7ea8715c29780aee89618bc91dad1a6de66c3b..6673e021bf30897326cb1ab8586ca87ca7f3120c 100644 (file)
@@ -116,7 +116,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     Reveal::UserFacing => ty,
 
                     Reveal::All => {
-                        let recursion_limit = self.tcx().sess.recursion_limit();
+                        let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
index 6cecff4b89d9d0c26390d631c6dc6f4691d750c4..708688fa8a69d8a203052dece1fad8ee10c38209 100644 (file)
@@ -993,7 +993,7 @@ fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFolda
         obligation: &Obligation<'tcx, T>,
         error_obligation: &Obligation<'tcx, V>,
     ) -> Result<(), OverflowError> {
-        if !self.infcx.tcx.sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
+        if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
             match self.query_mode {
                 TraitQueryMode::Standard => {
                     self.infcx().report_overflow_error(error_obligation, true);
index 9d5b9d7357fc47e8c56dac714abb1a9754606d0a..4a41dfe01431eb6f1d3dd4307a4ebe0d043730ff 100644 (file)
@@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>(
 ) -> Result<(), NoSolution> {
     debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
 
-    if !tcx.sess.recursion_limit().value_within_limit(depth) {
+    if !tcx.recursion_limit().value_within_limit(depth) {
         constraints.overflows.push(ty);
         return Ok(());
     }
index bc8f10e15db8cb180ccaaf1e7898021490549763..d837af85d58ae912933b202a95a927b043026b97 100644 (file)
@@ -63,7 +63,7 @@ fn new(
             seen_tys,
             query_ty: ty,
             unchecked_tys: vec![(ty, 0)],
-            recursion_limit: tcx.sess.recursion_limit(),
+            recursion_limit: tcx.recursion_limit(),
             adt_components,
         }
     }
index 0373033bd28dbc612e36044f6e1a4a8a5e0be093..ffde9b79265a5b5bacd166aaad4ff247be71a37e 100644 (file)
@@ -1,12 +1,11 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{
     self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
 };
-use rustc_session::CrateDisambiguator;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 
@@ -388,11 +387,6 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE
     tcx.param_env(def_id).with_reveal_all_normalized(tcx)
 }
 
-fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.sess.local_crate_disambiguator()
-}
-
 fn instance_def_size_estimate<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance_def: ty::InstanceDef<'tcx>,
@@ -538,7 +532,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         param_env,
         param_env_reveal_all_normalized,
         trait_of_item,
-        crate_disambiguator,
         instance_def_size_estimate,
         issue33140_self_ty,
         impl_defaultness,
index ed62899c04ebb0a47b3b6caf091f0841b7c9e3e1..d101551085976077688375471a3592fcfe0567f5 100644 (file)
@@ -588,10 +588,17 @@ pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) {
                 fcx.write_method_call(self.call_expr.hir_id, method_callee);
             }
             None => {
-                span_bug!(
+                // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once`
+                // lang items are not defined (issue #86238).
+                let mut err = fcx.inh.tcx.sess.struct_span_err(
                     self.call_expr.span,
-                    "failed to find an overloaded call trait for closure call"
+                    "failed to find an overloaded call trait for closure call",
                 );
+                err.help(
+                    "make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \
+                     and have associated `call`/`call_mut`/`call_once` functions",
+                );
+                err.emit();
             }
         }
     }
index a09fad3b6b78ad72b0b87e5cbba12a6efdbc04c3..b3808eae1ad1155c10af372a76d9632562b005c6 100644 (file)
@@ -45,6 +45,7 @@
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 
@@ -441,8 +442,8 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                             let expr_ty = fcx.tcx.erase_regions(expr_ty);
                             let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
                             if fcx
-                                .tcx
-                                .type_implements_trait((from_trait, ty, ty_params, fcx.param_env))
+                                .infcx
+                                .type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
                                 .must_apply_modulo_regions()
                             {
                                 label = false;
index 77644ea1c3c95046ced8fbe8bf0f23263b2f3f32..496721e6f7634f54706a468573979a7a3840ea2f 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt};
-use rustc_session::lint::builtin::UNINHABITED_STATIC;
+use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, MultiSpan, Span};
 use rustc_target::spec::abi::Abi;
@@ -34,16 +34,22 @@ pub fn check_wf_new(tcx: TyCtxt<'_>) {
     tcx.hir().krate().par_visit_all_item_likes(&visit);
 }
 
-pub(super) fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
-    if !tcx.sess.target.is_abi_supported(abi) {
-        struct_span_err!(
+pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
+    match tcx.sess.target.is_abi_supported(abi) {
+        Some(true) => (),
+        Some(false) => struct_span_err!(
             tcx.sess,
             span,
             E0570,
-            "The ABI `{}` is not supported for the current target",
+            "`{}` is not a supported ABI for the current target",
             abi
         )
-        .emit()
+        .emit(),
+        None => {
+            tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
+                lint.build("use of calling convention not supported on this target").emit()
+            });
+        }
     }
 
     // This ABI is only allowed on function pointers
@@ -828,7 +834,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
         hir::ItemKind::ForeignMod { abi, items } => {
-            check_abi(tcx, it.span, abi);
+            check_abi(tcx, it.hir_id(), it.span, abi);
 
             if abi == Abi::RustIntrinsic {
                 for item in items {
index afa4d0f1c4de9067948fe5219c5e040df6f907a2..9e89804b74713bd8fdda10a1af3d4e3d2741ae95 100644 (file)
@@ -1456,11 +1456,15 @@ fn report_return_mismatched_types<'a>(
                 expected.is_unit(),
                 pointing_at_return_type,
             ) {
-                // If the block is from an external macro, then do not suggest
-                // adding a semicolon, because there's nowhere to put it.
-                // See issue #81943.
+                // If the block is from an external macro or try (`?`) desugaring, then
+                // do not suggest adding a semicolon, because there's nowhere to put it.
+                // See issues #81943 and #87051.
                 if cond_expr.span.desugaring_kind().is_none()
                     && !in_external_macro(fcx.tcx.sess, cond_expr.span)
+                    && !matches!(
+                        cond_expr.kind,
+                        hir::ExprKind::Match(.., hir::MatchSource::TryDesugar)
+                    )
                 {
                     err.span_label(cond_expr.span, "expected this to be `()`");
                     if expr.can_have_side_effects() {
index 882d5d54b7c9fa238b091d2e1df3668f3f9ac409..6661df21ed952cef4b2748a90e4748d75a6fd491 100644 (file)
@@ -380,6 +380,13 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
             sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
 
+            sym::raw_eq => {
+                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
+                let param_ty =
+                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
+                (1, vec![param_ty; 2], tcx.types.bool)
+            }
+
             other => {
                 tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
                 return;
index e8748dd062f5334beda61776ecccc603e3e628cb..f13e23914f7ab54b35a31737c680405943c000a4 100644 (file)
@@ -4,11 +4,13 @@
 use rustc_ast::Mutability;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{Ref, Ty};
-use rustc_session::lint::builtin::FUTURE_PRELUDE_COLLISION;
+use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
 use rustc_span::symbol::kw::Underscore;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 
 use crate::check::{
     method::probe::{self, Pick},
@@ -67,7 +69,7 @@ pub(super) fn lint_dot_call_from_2018(
             // Inherent impls only require not relying on autoref and autoderef in order to
             // ensure that the trait implementation won't be used
             self.tcx.struct_span_lint_hir(
-                FUTURE_PRELUDE_COLLISION,
+                RUST_2021_PRELUDE_COLLISIONS,
                 self_expr.hir_id,
                 self_expr.span,
                 |lint| {
@@ -128,7 +130,7 @@ pub(super) fn lint_dot_call_from_2018(
             // trait implementations require full disambiguation to not clash with the new prelude
             // additions (i.e. convert from dot-call to fully-qualified call)
             self.tcx.struct_span_lint_hir(
-                FUTURE_PRELUDE_COLLISION,
+                RUST_2021_PRELUDE_COLLISIONS,
                 call_expr.hir_id,
                 call_expr.span,
                 |lint| {
@@ -206,13 +208,32 @@ pub(super) fn lint_fully_qualified_call_from_2018(
             return;
         }
 
+        // For from_iter, check if the type actually implements FromIterator.
+        // If we know it does not, we don't need to warn.
+        if method_name.name == sym::from_iter {
+            if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
+                if !self
+                    .infcx
+                    .type_implements_trait(
+                        trait_def_id,
+                        self_ty,
+                        InternalSubsts::empty(),
+                        self.param_env,
+                    )
+                    .may_apply()
+                {
+                    return;
+                }
+            }
+        }
+
         // No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
         // since such methods take precedence over trait methods.
         if matches!(pick.kind, probe::PickKind::InherentImplPick) {
             return;
         }
 
-        self.tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
+        self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
             // "type" refers to either a type or, more likely, a trait from which
             // the associated function or method is from.
             let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());
index b5dc7b750b183145e29ce1e831f216deca87069b..ff7d291d3c9098a80494eb6b1e36e624d375e9a6 100644 (file)
@@ -499,7 +499,7 @@ fn typeck_with_fallback<'tcx>(
                 tcx.fn_sig(def_id)
             };
 
-            check_abi(tcx, span, fn_sig.abi());
+            check_abi(tcx, id, span, fn_sig.abi());
 
             // Compute the fty from point of view of inside the fn.
             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
index e5f18778f43e62171fd089c97972133ac20cd328..9a39a32f6d5d312d52dc2ad9f4a746705b748b66 100644 (file)
 use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{
-    self, ClosureSizeProfileData, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts,
+    self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarCapture, UpvarSubsts,
 };
 use rustc_session::lint;
 use rustc_span::sym;
 use rustc_span::{MultiSpan, Span, Symbol};
-use rustc_trait_selection::traits::{Obligation, ObligationCause};
+use rustc_trait_selection::infer::InferCtxtExt;
 
+use rustc_data_structures::stable_map::FxHashMap;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_index::vec::Idx;
 use rustc_target::abi::VariantIdx;
@@ -81,6 +82,22 @@ pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
     }
 }
 
+/// Intermediate format to store the hir_id pointing to the use that resulted in the
+/// corresponding place being captured and a String which contains the captured value's
+/// name (i.e: a.b.c)
+type CapturesInfo = (Option<hir::HirId>, String);
+
+/// Intermediate format to store information needed to generate migration lint. The tuple
+/// contains the hir_id pointing to the use that resulted in the
+/// corresponding place being captured, a String which contains the captured value's
+/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that
+/// capture
+type MigrationNeededForCapture = (Option<hir::HirId>, String, String);
+
+/// Intermediate format to store the hir id of the root variable and a HashSet containing
+/// information on why the root variable should be fully captured
+type MigrationDiagnosticInfo = (hir::HirId, Vec<MigrationNeededForCapture>);
+
 struct InferBorrowKindVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
 }
@@ -148,9 +165,6 @@ fn analyze_closure(
             fcx: self,
             closure_def_id,
             closure_span: span,
-            capture_clause,
-            current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
-            current_origin: None,
             capture_information: Default::default(),
             fake_reads: Default::default(),
         };
@@ -167,13 +181,17 @@ fn analyze_closure(
             "For closure={:?}, capture_information={:#?}",
             closure_def_id, delegate.capture_information
         );
+
         self.log_capture_analysis_first_pass(closure_def_id, &delegate.capture_information, span);
 
-        self.compute_min_captures(closure_def_id, capture_clause, delegate.capture_information);
+        let (capture_information, closure_kind, origin) = self
+            .process_collected_capture_information(capture_clause, delegate.capture_information);
+
+        self.compute_min_captures(closure_def_id, capture_information);
 
         let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
 
-        if should_do_disjoint_capture_migration_analysis(self.tcx, closure_hir_id) {
+        if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) {
             self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span);
         }
 
@@ -204,7 +222,7 @@ fn analyze_closure(
             }
 
             // This will update the min captures based on this new fake information.
-            self.compute_min_captures(closure_def_id, capture_clause, capture_information);
+            self.compute_min_captures(closure_def_id, capture_information);
         }
 
         let before_feature_tys = self.final_upvar_tys(closure_def_id);
@@ -212,14 +230,13 @@ fn analyze_closure(
         if let Some(closure_substs) = infer_kind {
             // Unify the (as yet unbound) type variable in the closure
             // substs with the kind we inferred.
-            let inferred_kind = delegate.current_closure_kind;
             let closure_kind_ty = closure_substs.as_closure().kind_ty();
-            self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
+            self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
 
             // If we have an origin, store it.
-            if let Some(origin) = delegate.current_origin.clone() {
+            if let Some(origin) = origin {
                 let origin = if enable_precise_capture(self.tcx, span) {
-                    (origin.0, restrict_capture_precision(capture_clause, origin.1))
+                    (origin.0, origin.1)
                 } else {
                     (origin.0, Place { projections: vec![], ..origin.1 })
                 };
@@ -301,17 +318,90 @@ fn final_upvar_tys(&self, closure_id: DefId) -> Vec<Ty<'tcx>> {
                     captured_place.place, upvar_ty, capture, captured_place.mutability,
                 );
 
-                match capture {
-                    ty::UpvarCapture::ByValue(_) => upvar_ty,
-                    ty::UpvarCapture::ByRef(borrow) => self.tcx.mk_ref(
-                        borrow.region,
-                        ty::TypeAndMut { ty: upvar_ty, mutbl: borrow.kind.to_mutbl_lossy() },
-                    ),
-                }
+                apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture)
             })
             .collect()
     }
 
+    /// Adjusts the closure capture information to ensure that the operations aren't unsafe,
+    /// and that the path can be captured with required capture kind (depending on use in closure,
+    /// move closure etc.)
+    ///
+    /// Returns the set of of adjusted information along with the inferred closure kind and span
+    /// associated with the closure kind inference.
+    ///
+    /// Note that we *always* infer a minimal kind, even if
+    /// we don't always *use* that in the final result (i.e., sometimes
+    /// we've taken the closure kind from the expectations instead, and
+    /// for generators we don't even implement the closure traits
+    /// really).
+    ///
+    /// If we inferred that the closure needs to be FnMut/FnOnce, last element of the returned tuple
+    /// contains a `Some()` with the `Place` that caused us to do so.
+    fn process_collected_capture_information(
+        &self,
+        capture_clause: hir::CaptureBy,
+        capture_information: InferredCaptureInformation<'tcx>,
+    ) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'tcx>)>) {
+        let mut processed: InferredCaptureInformation<'tcx> = Default::default();
+
+        let mut closure_kind = ty::ClosureKind::LATTICE_BOTTOM;
+        let mut origin: Option<(Span, Place<'tcx>)> = None;
+
+        for (place, mut capture_info) in capture_information {
+            // Apply rules for safety before inferring closure kind
+            let place = restrict_capture_precision(place);
+
+            let place = truncate_capture_for_optimization(&place);
+
+            let usage_span = if let Some(usage_expr) = capture_info.path_expr_id {
+                self.tcx.hir().span(usage_expr)
+            } else {
+                unreachable!()
+            };
+
+            let updated = match capture_info.capture_kind {
+                ty::UpvarCapture::ByValue(..) => match closure_kind {
+                    ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
+                        (ty::ClosureKind::FnOnce, Some((usage_span, place.clone())))
+                    }
+                    // If closure is already FnOnce, don't update
+                    ty::ClosureKind::FnOnce => (closure_kind, origin),
+                },
+
+                ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+                    kind: ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
+                    ..
+                }) => {
+                    match closure_kind {
+                        ty::ClosureKind::Fn => {
+                            (ty::ClosureKind::FnMut, Some((usage_span, place.clone())))
+                        }
+                        // Don't update the origin
+                        ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce => (closure_kind, origin),
+                    }
+                }
+
+                _ => (closure_kind, origin),
+            };
+
+            closure_kind = updated.0;
+            origin = updated.1;
+
+            let (place, capture_kind) = match capture_clause {
+                hir::CaptureBy::Value => adjust_for_move_closure(place, capture_info.capture_kind),
+                hir::CaptureBy::Ref => {
+                    adjust_for_non_move_closure(place, capture_info.capture_kind)
+                }
+            };
+
+            capture_info.capture_kind = capture_kind;
+            processed.insert(place, capture_info);
+        }
+
+        (processed, closure_kind, origin)
+    }
+
     /// Analyzes the information collected by `InferBorrowKind` to compute the min number of
     /// Places (and corresponding capture kind) that we need to keep track of to support all
     /// the required captured paths.
@@ -384,7 +474,6 @@ fn final_upvar_tys(&self, closure_id: DefId) -> Vec<Ty<'tcx>> {
     fn compute_min_captures(
         &self,
         closure_def_id: DefId,
-        capture_clause: hir::CaptureBy,
         capture_information: InferredCaptureInformation<'tcx>,
     ) {
         if capture_information.is_empty() {
@@ -402,8 +491,6 @@ fn compute_min_captures(
                 base => bug!("Expected upvar, found={:?}", base),
             };
 
-            let place = restrict_capture_precision(capture_clause, place);
-
             let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
                 None => {
                     let mutability = self.determine_capture_mutability(&typeck_results, &place);
@@ -504,18 +591,58 @@ fn perform_2229_migration_anaysis(
 
             let local_def_id = closure_def_id.expect_local();
             let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
+            let closure_span = self.tcx.hir().span(closure_hir_id);
+            let closure_head_span = self.tcx.sess.source_map().guess_head_span(closure_span);
             self.tcx.struct_span_lint_hir(
-                lint::builtin::DISJOINT_CAPTURE_MIGRATION,
+                lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
                 closure_hir_id,
-                span,
+                closure_head_span,
                 |lint| {
                     let mut diagnostics_builder = lint.build(
                         format!(
-                            "{} will change in Rust 2021",
+                            "changes to closure capture in Rust 2021 will affect {}",
                             reasons
                         )
                         .as_str(),
                     );
+                    for (var_hir_id, diagnostics_info) in need_migrations.iter() {
+                        // Labels all the usage of the captured variable and why they are responsible
+                        // for migration being needed
+                        for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() {
+                            if let Some(captured_hir_id) = captured_hir_id {
+                                let cause_span = self.tcx.hir().span(*captured_hir_id);
+                                diagnostics_builder.span_label(cause_span, format!("in Rust 2018, closure captures all of `{}`, but in Rust 2021, it only captures `{}`",
+                                    self.tcx.hir().name(*var_hir_id),
+                                    captured_name,
+                                ));
+                            }
+
+                            // Add a label pointing to where a captured variable affected by drop order
+                            // is dropped
+                            if reasons.contains("drop order") {
+                                let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
+
+                                diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` would be dropped here, but in Rust 2021, only `{}` would be dropped here alongside the closure",
+                                    self.tcx.hir().name(*var_hir_id),
+                                    captured_name,
+                                ));
+                            }
+
+                            // Add a label explaining why a closure no longer implements a trait
+                            if reasons.contains("trait implementation") {
+                                let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1];
+
+                                diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure would implement {} as `{}` implements {}, but in Rust 2021, this closure would no longer implement {} as `{}` does not implement {}",
+                                    missing_trait,
+                                    self.tcx.hir().name(*var_hir_id),
+                                    missing_trait,
+                                    missing_trait,
+                                    captured_name,
+                                    missing_trait,
+                                ));
+                            }
+                        }
+                    }
                     diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
                     let closure_body_span = self.tcx.hir().span(body_id.hir_id);
                     let (sugg, app) =
@@ -562,13 +689,13 @@ fn compute_2229_migrations_reasons(
 
         if auto_trait_reasons.len() > 0 {
             reasons = format!(
-                "{} trait implementation",
+                "{} trait implementation for closure",
                 auto_trait_reasons.clone().into_iter().collect::<Vec<&str>>().join(", ")
             );
         }
 
         if auto_trait_reasons.len() > 0 && drop_reason {
-            reasons = format!("{}, and ", reasons);
+            reasons = format!("{} and ", reasons);
         }
 
         if drop_reason {
@@ -578,141 +705,121 @@ fn compute_2229_migrations_reasons(
         reasons
     }
 
-    /// Returns true if `ty` may implement `trait_def_id`
-    fn ty_impls_trait(
-        &self,
-        ty: Ty<'tcx>,
-        cause: &ObligationCause<'tcx>,
-        trait_def_id: DefId,
-    ) -> bool {
-        use crate::rustc_middle::ty::ToPredicate;
-        use crate::rustc_middle::ty::WithConstness;
-        use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-        let tcx = self.infcx.tcx;
-
-        let trait_ref = TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) };
-
-        let obligation = Obligation::new(
-            cause.clone(),
-            self.param_env,
-            trait_ref.without_const().to_predicate(tcx),
-        );
-
-        self.infcx.predicate_may_hold(&obligation)
-    }
-
-    /// Returns true if migration is needed for trait for the provided var_hir_id
-    fn need_2229_migrations_for_trait(
+    /// Figures out the list of root variables (and their types) that aren't completely
+    /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits
+    /// differ between the root variable and the captured paths.
+    ///
+    /// Returns a tuple containing a HashMap of CapturesInfo that maps to a HashSet of trait names
+    /// if migration is needed for traits for the provided var_hir_id, otherwise returns None
+    fn compute_2229_migrations_for_trait(
         &self,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         var_hir_id: hir::HirId,
-        check_trait: Option<DefId>,
-    ) -> bool {
+        closure_clause: hir::CaptureBy,
+    ) -> Option<FxHashMap<CapturesInfo, FxHashSet<&str>>> {
+        let auto_traits_def_id = vec![
+            self.tcx.lang_items().clone_trait(),
+            self.tcx.lang_items().sync_trait(),
+            self.tcx.get_diagnostic_item(sym::send_trait),
+            self.tcx.lang_items().unpin_trait(),
+            self.tcx.get_diagnostic_item(sym::unwind_safe_trait),
+            self.tcx.get_diagnostic_item(sym::ref_unwind_safe_trait),
+        ];
+        let auto_traits =
+            vec!["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"];
+
         let root_var_min_capture_list = if let Some(root_var_min_capture_list) =
             min_captures.and_then(|m| m.get(&var_hir_id))
         {
             root_var_min_capture_list
         } else {
-            return false;
+            return None;
         };
 
         let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
-        let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id);
-
-        let obligation_should_hold = check_trait
-            .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
-            .unwrap_or(false);
-
-        // Check whether catpured fields also implement the trait
-
-        for capture in root_var_min_capture_list.iter() {
-            let ty = capture.place.ty();
-
-            let obligation_holds_for_capture = check_trait
-                .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
-                .unwrap_or(false);
+        let ty = match closure_clause {
+            hir::CaptureBy::Value => ty, // For move closure the capture kind should be by value
+            hir::CaptureBy::Ref => {
+                // For non move closure the capture kind is the max capture kind of all captures
+                // according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue
+                let mut max_capture_info = root_var_min_capture_list.first().unwrap().info;
+                for capture in root_var_min_capture_list.iter() {
+                    max_capture_info = determine_capture_info(max_capture_info, capture.info);
+                }
 
-            if !obligation_holds_for_capture && obligation_should_hold {
-                return true;
+                apply_capture_kind_on_capture_ty(self.tcx, ty, max_capture_info.capture_kind)
             }
-        }
-        false
-    }
+        };
 
-    /// Figures out the list of root variables (and their types) that aren't completely
-    /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits
-    /// differ between the root variable and the captured paths.
-    ///
-    /// The output list would include a root variable if:
-    /// - It would have been captured into the closure when `capture_disjoint_fields` wasn't
-    ///   enabled, **and**
-    /// - It wasn't completely captured by the closure, **and**
-    /// - One of the paths captured does not implement all the auto-traits its root variable
-    ///   implements.
-    fn compute_2229_migrations_for_trait(
-        &self,
-        min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
-        var_hir_id: hir::HirId,
-    ) -> Option<FxHashSet<&str>> {
-        let tcx = self.infcx.tcx;
-
-        // Check whether catpured fields also implement the trait
-        let mut auto_trait_reasons = FxHashSet::default();
-
-        if self.need_2229_migrations_for_trait(
-            min_captures,
-            var_hir_id,
-            tcx.lang_items().clone_trait(),
-        ) {
-            auto_trait_reasons.insert("`Clone`");
+        let mut obligations_should_hold = Vec::new();
+        // Checks if a root variable implements any of the auto traits
+        for check_trait in auto_traits_def_id.iter() {
+            obligations_should_hold.push(
+                check_trait
+                    .map(|check_trait| {
+                        self.infcx
+                            .type_implements_trait(
+                                check_trait,
+                                ty,
+                                self.tcx.mk_substs_trait(ty, &[]),
+                                self.param_env,
+                            )
+                            .must_apply_modulo_regions()
+                    })
+                    .unwrap_or(false),
+            );
         }
 
-        if self.need_2229_migrations_for_trait(
-            min_captures,
-            var_hir_id,
-            tcx.lang_items().sync_trait(),
-        ) {
-            auto_trait_reasons.insert("`Sync`");
-        }
+        let mut problematic_captures = FxHashMap::default();
+        // Check whether captured fields also implement the trait
+        for capture in root_var_min_capture_list.iter() {
+            let ty = apply_capture_kind_on_capture_ty(
+                self.tcx,
+                capture.place.ty(),
+                capture.info.capture_kind,
+            );
 
-        if self.need_2229_migrations_for_trait(
-            min_captures,
-            var_hir_id,
-            tcx.lang_items().send_trait(),
-        ) {
-            auto_trait_reasons.insert("`Send`");
-        }
+            // Checks if a capture implements any of the auto traits
+            let mut obligations_holds_for_capture = Vec::new();
+            for check_trait in auto_traits_def_id.iter() {
+                obligations_holds_for_capture.push(
+                    check_trait
+                        .map(|check_trait| {
+                            self.infcx
+                                .type_implements_trait(
+                                    check_trait,
+                                    ty,
+                                    self.tcx.mk_substs_trait(ty, &[]),
+                                    self.param_env,
+                                )
+                                .must_apply_modulo_regions()
+                        })
+                        .unwrap_or(false),
+                );
+            }
 
-        if self.need_2229_migrations_for_trait(
-            min_captures,
-            var_hir_id,
-            tcx.lang_items().unpin_trait(),
-        ) {
-            auto_trait_reasons.insert("`Unpin`");
-        }
+            let mut capture_problems = FxHashSet::default();
 
-        if self.need_2229_migrations_for_trait(
-            min_captures,
-            var_hir_id,
-            tcx.lang_items().unwind_safe_trait(),
-        ) {
-            auto_trait_reasons.insert("`UnwindSafe`");
-        }
+            // Checks if for any of the auto traits, one or more trait is implemented
+            // by the root variable but not by the capture
+            for (idx, _) in obligations_should_hold.iter().enumerate() {
+                if !obligations_holds_for_capture[idx] && obligations_should_hold[idx] {
+                    capture_problems.insert(auto_traits[idx]);
+                }
+            }
 
-        if self.need_2229_migrations_for_trait(
-            min_captures,
-            var_hir_id,
-            tcx.lang_items().ref_unwind_safe_trait(),
-        ) {
-            auto_trait_reasons.insert("`RefUnwindSafe`");
+            if capture_problems.len() > 0 {
+                problematic_captures.insert(
+                    (capture.info.path_expr_id, capture.to_string(self.tcx)),
+                    capture_problems,
+                );
+            }
         }
-
-        if auto_trait_reasons.len() > 0 {
-            return Some(auto_trait_reasons);
+        if problematic_captures.len() > 0 {
+            return Some(problematic_captures);
         }
-
-        return None;
+        None
     }
 
     /// Figures out the list of root variables (and their types) that aren't completely
@@ -725,8 +832,8 @@ fn compute_2229_migrations_for_trait(
     /// - It wasn't completely captured by the closure, **and**
     /// - One of the paths starting at this root variable, that is not captured needs Drop.
     ///
-    /// This function only returns true for significant drops. A type is considerent to have a
-    /// significant drop if it's Drop implementation is not annotated by `rustc_insignificant_dtor`.
+    /// This function only returns a HashSet of CapturesInfo for significant drops. If there
+    /// are no significant drops than None is returned
     fn compute_2229_migrations_for_drop(
         &self,
         closure_def_id: DefId,
@@ -734,11 +841,11 @@ fn compute_2229_migrations_for_drop(
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         closure_clause: hir::CaptureBy,
         var_hir_id: hir::HirId,
-    ) -> bool {
+    ) -> Option<FxHashSet<CapturesInfo>> {
         let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
         if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
-            return false;
+            return None;
         }
 
         let root_var_min_capture_list = if let Some(root_var_min_capture_list) =
@@ -751,21 +858,29 @@ fn compute_2229_migrations_for_drop(
 
             match closure_clause {
                 // Only migrate if closure is a move closure
-                hir::CaptureBy::Value => return true,
+                hir::CaptureBy::Value => return Some(FxHashSet::default()),
                 hir::CaptureBy::Ref => {}
             }
 
-            return false;
+            return None;
         };
 
-        let projections_list = root_var_min_capture_list
-            .iter()
-            .filter_map(|captured_place| match captured_place.info.capture_kind {
+        let mut projections_list = Vec::new();
+        let mut diagnostics_info = FxHashSet::default();
+
+        for captured_place in root_var_min_capture_list.iter() {
+            match captured_place.info.capture_kind {
                 // Only care about captures that are moved into the closure
-                ty::UpvarCapture::ByValue(..) => Some(captured_place.place.projections.as_slice()),
-                ty::UpvarCapture::ByRef(..) => None,
-            })
-            .collect::<Vec<_>>();
+                ty::UpvarCapture::ByValue(..) => {
+                    projections_list.push(captured_place.place.projections.as_slice());
+                    diagnostics_info.insert((
+                        captured_place.info.path_expr_id,
+                        captured_place.to_string(self.tcx),
+                    ));
+                }
+                ty::UpvarCapture::ByRef(..) => {}
+            }
+        }
 
         let is_moved = !projections_list.is_empty();
 
@@ -781,10 +896,10 @@ fn compute_2229_migrations_for_drop(
                 projections_list,
             )
         {
-            return true;
+            return Some(diagnostics_info);
         }
 
-        return false;
+        return None;
     }
 
     /// Figures out the list of root variables (and their types) that aren't completely
@@ -800,15 +915,16 @@ fn compute_2229_migrations_for_drop(
     /// - One of the paths captured does not implement all the auto-traits its root variable
     ///   implements.
     ///
-    /// Returns a tuple containing a vector of HirIds as well as a String containing the reason
-    /// why root variables whose HirId is contained in the vector should be fully captured.
+    /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String
+    /// containing the reason why root variables whose HirId is contained in the vector should
+    /// be captured
     fn compute_2229_migrations(
         &self,
         closure_def_id: DefId,
         closure_span: Span,
         closure_clause: hir::CaptureBy,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
-    ) -> (Vec<hir::HirId>, String) {
+    ) -> (Vec<MigrationDiagnosticInfo>, String) {
         let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
             upvars
         } else {
@@ -816,38 +932,79 @@ fn compute_2229_migrations(
         };
 
         let mut need_migrations = Vec::new();
-        let mut auto_trait_reasons = FxHashSet::default();
-        let mut drop_reorder_reason = false;
+        let mut auto_trait_migration_reasons = FxHashSet::default();
+        let mut drop_migration_needed = false;
 
         // Perform auto-trait analysis
         for (&var_hir_id, _) in upvars.iter() {
-            let mut need_migration = false;
-            if let Some(trait_migration_cause) =
-                self.compute_2229_migrations_for_trait(min_captures, var_hir_id)
+            let mut responsible_captured_hir_ids = Vec::new();
+
+            let auto_trait_diagnostic = if let Some(diagnostics_info) =
+                self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
             {
-                need_migration = true;
-                auto_trait_reasons.extend(trait_migration_cause);
+                diagnostics_info
+            } else {
+                FxHashMap::default()
+            };
+
+            let drop_reorder_diagnostic = if let Some(diagnostics_info) = self
+                .compute_2229_migrations_for_drop(
+                    closure_def_id,
+                    closure_span,
+                    min_captures,
+                    closure_clause,
+                    var_hir_id,
+                ) {
+                drop_migration_needed = true;
+                diagnostics_info
+            } else {
+                FxHashSet::default()
+            };
+
+            // Combine all the captures responsible for needing migrations into one HashSet
+            let mut capture_diagnostic = drop_reorder_diagnostic.clone();
+            for key in auto_trait_diagnostic.keys() {
+                capture_diagnostic.insert(key.clone());
             }
 
-            if self.compute_2229_migrations_for_drop(
-                closure_def_id,
-                closure_span,
-                min_captures,
-                closure_clause,
-                var_hir_id,
-            ) {
-                need_migration = true;
-                drop_reorder_reason = true;
+            let mut capture_diagnostic = capture_diagnostic.into_iter().collect::<Vec<_>>();
+            capture_diagnostic.sort();
+            for captured_info in capture_diagnostic.iter() {
+                // Get the auto trait reasons of why migration is needed because of that capture, if there are any
+                let capture_trait_reasons =
+                    if let Some(reasons) = auto_trait_diagnostic.get(captured_info) {
+                        reasons.clone()
+                    } else {
+                        FxHashSet::default()
+                    };
+
+                // Check if migration is needed because of drop reorder as a result of that capture
+                let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info);
+
+                // Combine all the reasons of why the root variable should be captured as a result of
+                // auto trait implementation issues
+                auto_trait_migration_reasons.extend(capture_trait_reasons.clone());
+
+                responsible_captured_hir_ids.push((
+                    captured_info.0,
+                    captured_info.1.clone(),
+                    self.compute_2229_migrations_reasons(
+                        capture_trait_reasons,
+                        capture_drop_reorder_reason,
+                    ),
+                ));
             }
 
-            if need_migration {
-                need_migrations.push(var_hir_id);
+            if capture_diagnostic.len() > 0 {
+                need_migrations.push((var_hir_id, responsible_captured_hir_ids));
             }
         }
-
         (
             need_migrations,
-            self.compute_2229_migrations_reasons(auto_trait_reasons, drop_reorder_reason),
+            self.compute_2229_migrations_reasons(
+                auto_trait_migration_reasons,
+                drop_migration_needed,
+            ),
         )
     }
 
@@ -961,13 +1118,13 @@ fn has_significant_drop_outside_of_captures(
         let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
             let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
             let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]);
-            self.tcx
-                .type_implements_trait((
+            self.infcx
+                .type_implements_trait(
                     drop_trait,
                     ty,
                     ty_params,
                     self.tcx.param_env(closure_def_id.expect_local()),
-                ))
+                )
                 .must_apply_modulo_regions()
         };
 
@@ -1295,6 +1452,39 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
     place
 }
 
+/// Returns a Ty that applies the specified capture kind on the provided capture Ty
+fn apply_capture_kind_on_capture_ty(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    capture_kind: UpvarCapture<'tcx>,
+) -> Ty<'tcx> {
+    match capture_kind {
+        ty::UpvarCapture::ByValue(_) => ty,
+        ty::UpvarCapture::ByRef(borrow) => tcx
+            .mk_ref(borrow.region, ty::TypeAndMut { ty: ty, mutbl: borrow.kind.to_mutbl_lossy() }),
+    }
+}
+
+/// Returns the Span of where the value with the provided HirId would be dropped
+fn drop_location_span(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span {
+    let owner_id = tcx.hir().get_enclosing_scope(*hir_id).unwrap();
+
+    let owner_node = tcx.hir().get(owner_id);
+    let owner_span = match owner_node {
+        hir::Node::Item(item) => match item.kind {
+            hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id),
+            _ => {
+                bug!("Drop location span error: need to handle more ItemKind {:?}", item.kind);
+            }
+        },
+        hir::Node::Block(block) => tcx.hir().span(block.hir_id),
+        _ => {
+            bug!("Drop location span error: need to handle more Node {:?}", owner_node);
+        }
+    };
+    tcx.sess.source_map().end_point(owner_span)
+}
+
 struct InferBorrowKind<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
 
@@ -1303,20 +1493,6 @@ struct InferBorrowKind<'a, 'tcx> {
 
     closure_span: Span,
 
-    capture_clause: hir::CaptureBy,
-
-    // The kind that we have inferred that the current closure
-    // requires. Note that we *always* infer a minimal kind, even if
-    // we don't always *use* that in the final result (i.e., sometimes
-    // we've taken the closure kind from the expectations instead, and
-    // for generators we don't even implement the closure traits
-    // really).
-    current_closure_kind: ty::ClosureKind,
-
-    // If we modified `current_closure_kind`, this field contains a `Some()` with the
-    // variable access that caused us to do so.
-    current_origin: Option<(Span, Place<'tcx>)>,
-
     /// For each Place that is captured by the closure, we track the minimal kind of
     /// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
     ///
@@ -1359,27 +1535,13 @@ fn adjust_upvar_borrow_kind_for_consume(
             place_with_id, diag_expr_id, mode
         );
 
-        match (self.capture_clause, mode) {
-            // In non-move closures, we only care about moves
-            (hir::CaptureBy::Ref, euv::Copy) => return,
-
-            // We want to capture Copy types that read through a ref via a reborrow
-            (hir::CaptureBy::Value, euv::Copy)
-                if place_with_id.place.deref_tys().any(ty::TyS::is_ref) =>
-            {
-                return;
-            }
-
-            (hir::CaptureBy::Ref, euv::Move) | (hir::CaptureBy::Value, euv::Move | euv::Copy) => {}
+        // Copy type being used as ByValue are equivalent to ImmBorrow and don't require any
+        // escalation.
+        match mode {
+            euv::ConsumeMode::Copy => return,
+            euv::ConsumeMode::Move => {}
         };
 
-        let place = truncate_capture_for_move(place_with_id.place.clone());
-        let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id };
-
-        if !self.capture_information.contains_key(&place) {
-            self.init_capture_info_for_place(&place_with_id, diag_expr_id);
-        }
-
         let tcx = self.fcx.tcx;
         let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
             upvar_id
@@ -1391,16 +1553,6 @@ fn adjust_upvar_borrow_kind_for_consume(
 
         let usage_span = tcx.hir().span(diag_expr_id);
 
-        if matches!(mode, euv::Move) {
-            // To move out of an upvar, this must be a FnOnce closure
-            self.adjust_closure_kind(
-                upvar_id.closure_expr_id,
-                ty::ClosureKind::FnOnce,
-                usage_span,
-                place.clone(),
-            );
-        }
-
         let capture_info = ty::CaptureInfo {
             capture_kind_expr_id: Some(diag_expr_id),
             path_expr_id: Some(diag_expr_id),
@@ -1478,22 +1630,11 @@ fn adjust_upvar_deref(
             ty::ImmBorrow => false,
         });
 
-        let tcx = self.fcx.tcx;
-
         // if this is an implicit deref of an
         // upvar, then we need to modify the
         // borrow_kind of the upvar to make sure it
         // is inferred to mutable if necessary
         self.adjust_upvar_borrow_kind(place_with_id, diag_expr_id, borrow_kind);
-
-        if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
-            self.adjust_closure_kind(
-                upvar_id.closure_expr_id,
-                ty::ClosureKind::FnMut,
-                tcx.hir().span(diag_expr_id),
-                place_with_id.place.clone(),
-            );
-        }
     }
 
     /// We infer the borrow_kind with which to borrow upvars in a stack closure.
@@ -1532,48 +1673,6 @@ fn adjust_upvar_borrow_kind(
         };
     }
 
-    fn adjust_closure_kind(
-        &mut self,
-        closure_id: LocalDefId,
-        new_kind: ty::ClosureKind,
-        upvar_span: Span,
-        place: Place<'tcx>,
-    ) {
-        debug!(
-            "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})",
-            closure_id, new_kind, upvar_span, place
-        );
-
-        // Is this the closure whose kind is currently being inferred?
-        if closure_id.to_def_id() != self.closure_def_id {
-            debug!("adjust_closure_kind: not current closure");
-            return;
-        }
-
-        // closures start out as `Fn`.
-        let existing_kind = self.current_closure_kind;
-
-        debug!(
-            "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
-            closure_id, existing_kind, new_kind
-        );
-
-        match (existing_kind, new_kind) {
-            (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
-            | (ty::ClosureKind::FnMut, ty::ClosureKind::Fn | ty::ClosureKind::FnMut)
-            | (ty::ClosureKind::FnOnce, _) => {
-                // no change needed
-            }
-
-            (ty::ClosureKind::Fn, ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce)
-            | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
-                // new kind is stronger than the old kind
-                self.current_closure_kind = new_kind;
-                self.current_origin = Some((upvar_span, place));
-            }
-        }
-    }
-
     fn init_capture_info_for_place(
         &mut self,
         place_with_id: &PlaceWithHirId<'tcx>,
@@ -1582,12 +1681,12 @@ fn init_capture_info_for_place(
         if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
             assert_eq!(self.closure_def_id.expect_local(), upvar_id.closure_expr_id);
 
-            let capture_kind = self.fcx.init_capture_kind_for_place(
-                &place_with_id.place,
-                self.capture_clause,
-                upvar_id,
-                self.closure_span,
-            );
+            // Initialize to ImmBorrow
+            // We will escalate the CaptureKind based on any uses we see or in `process_collected_capture_information`.
+            let origin = UpvarRegion(upvar_id, self.closure_span);
+            let upvar_region = self.fcx.next_region_var(origin);
+            let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region };
+            let capture_kind = ty::UpvarCapture::ByRef(upvar_borrow);
 
             let expr_id = Some(diag_expr_id);
             let capture_info = ty::CaptureInfo {
@@ -1610,7 +1709,7 @@ fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id:
         if let PlaceBase::Upvar(_) = place.base {
             // We need to restrict Fake Read precision to avoid fake reading unsafe code,
             // such as deref of a raw pointer.
-            let place = restrict_capture_precision(self.capture_clause, place);
+            let place = restrict_capture_precision(place);
             let place =
                 restrict_repr_packed_field_ref_capture(self.fcx.tcx, self.fcx.param_env, &place);
             self.fake_reads.push((place, cause, diag_expr_id));
@@ -1627,11 +1726,12 @@ fn consume(
             "consume(place_with_id={:?}, diag_expr_id={:?}, mode={:?})",
             place_with_id, diag_expr_id, mode
         );
+
         if !self.capture_information.contains_key(&place_with_id.place) {
-            self.init_capture_info_for_place(place_with_id, diag_expr_id);
+            self.init_capture_info_for_place(&place_with_id, diag_expr_id);
         }
 
-        self.adjust_upvar_borrow_kind_for_consume(place_with_id, diag_expr_id, mode);
+        self.adjust_upvar_borrow_kind_for_consume(&place_with_id, diag_expr_id, mode);
     }
 
     fn borrow(
@@ -1646,7 +1746,7 @@ fn borrow(
         );
 
         // We only want repr packed restriction to be applied to reading references into a packed
-        // struct, and not when the data is being moved. There for we call this method here instead
+        // struct, and not when the data is being moved. Therefore we call this method here instead
         // of in `restrict_capture_precision`.
         let place = restrict_repr_packed_field_ref_capture(
             self.fcx.tcx,
@@ -1678,46 +1778,11 @@ fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::H
     }
 }
 
-/// Deref of a box isn't captured in move clousres. This is motivated by:
-///   1. We only want to capture data that is on the stack
-///   2. One motivation for the user to use a box might be to reduce the amount of data that gets
-///      moved (if size of pointer < size of data). We want to make sure that this optimization that
-///      the user made is respected.
-fn restrict_precision_for_box<'tcx>(
-    capture_clause: hir::CaptureBy,
-    mut place: Place<'tcx>,
-) -> Place<'tcx> {
-    match capture_clause {
-        hir::CaptureBy::Ref => {}
-        hir::CaptureBy::Value => {
-            if ty::TyS::is_box(place.base_ty) {
-                place.projections.truncate(0);
-            } else {
-                // Either the box is the last access or there is a deref applied on the box
-                // In either case we want to stop at the box.
-                let pos = place.projections.iter().position(|proj| ty::TyS::is_box(proj.ty));
-                match pos {
-                    None => {}
-                    Some(idx) => {
-                        place.projections.truncate(idx + 1);
-                    }
-                }
-            }
-        }
-    }
-
-    place
-}
-
 /// Truncate projections so that following rules are obeyed by the captured `place`:
 /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
 ///   them completely.
 /// - No Index projections are captured, since arrays are captured completely.
-/// - Deref of a box isn't captured in move clousres.
-fn restrict_capture_precision<'tcx>(
-    capture_clause: hir::CaptureBy,
-    mut place: Place<'tcx>,
-) -> Place<'tcx> {
+fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
     if place.projections.is_empty() {
         // Nothing to do here
         return place;
@@ -1752,19 +1817,68 @@ fn restrict_capture_precision<'tcx>(
 
     place.projections.truncate(length);
 
-    // Dont't capture projections on top of a box in move closures.
-    restrict_precision_for_box(capture_clause, place)
+    place
 }
 
-/// Truncates a place so that the resultant capture doesn't move data out of a reference
-fn truncate_capture_for_move(mut place: Place<'tcx>) -> Place<'tcx> {
-    if let Some(i) = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref) {
-        // We only drop Derefs in case of move closures
-        // There might be an index projection or raw ptr ahead, so we don't stop here.
-        place.projections.truncate(i);
+/// Take ownership if data being accessed is owned by the variable used to access it
+/// (or if closure attempts to move data that it doesn’t own).
+/// Note: When taking ownership, only capture data found on the stack.
+fn adjust_for_move_closure<'tcx>(
+    mut place: Place<'tcx>,
+    kind: ty::UpvarCapture<'tcx>,
+) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+    let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
+    let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
+
+    match kind {
+        ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind),
+
+        // If there's any Deref and the data needs to be moved into the closure body,
+        // or it's a Deref of a Box, truncate the path to the first deref
+        _ if first_deref.is_some() => {
+            let place = match first_deref {
+                Some(idx) => {
+                    place.projections.truncate(idx);
+                    place
+                }
+                None => place,
+            };
+
+            // AMAN: I think we don't need the span inside the ByValue anymore
+            //       we have more detailed span in CaptureInfo
+            (place, ty::UpvarCapture::ByValue(None))
+        }
+
+        _ => (place, ty::UpvarCapture::ByValue(None)),
     }
+}
 
-    place
+/// Adjust closure capture just that if taking ownership of data, only move data
+/// from enclosing stack frame.
+fn adjust_for_non_move_closure<'tcx>(
+    mut place: Place<'tcx>,
+    kind: ty::UpvarCapture<'tcx>,
+) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+    let contains_deref =
+        place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
+
+    match kind {
+        ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => {
+            let place = match contains_deref {
+                Some(idx) => {
+                    place.projections.truncate(idx);
+                    place
+                }
+                // Because of the if guard on the match on `kind`, we should never get here.
+                None => unreachable!(),
+            };
+
+            (place, kind)
+        }
+
+        ty::UpvarCapture::ByValue(..) => (place, kind),
+        ty::UpvarCapture::ByRef(..) => (place, kind),
+    }
 }
 
 fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
@@ -1829,8 +1943,12 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
     tcx.hir().name(var_hir_id)
 }
 
-fn should_do_disjoint_capture_migration_analysis(tcx: TyCtxt<'_>, closure_id: hir::HirId) -> bool {
-    let (level, _) = tcx.lint_level_at_node(lint::builtin::DISJOINT_CAPTURE_MIGRATION, closure_id);
+fn should_do_rust_2021_incompatible_closure_captures_analysis(
+    tcx: TyCtxt<'_>,
+    closure_id: hir::HirId,
+) -> bool {
+    let (level, _) =
+        tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id);
 
     !matches!(level, lint::Level::Allow)
 }
@@ -1840,10 +1958,10 @@ fn should_do_disjoint_capture_migration_analysis(tcx: TyCtxt<'_>, closure_id: hi
 /// - s2: Comma separated names of the variables being migrated.
 fn migration_suggestion_for_2229(
     tcx: TyCtxt<'_>,
-    need_migrations: &Vec<hir::HirId>,
+    need_migrations: &Vec<MigrationDiagnosticInfo>,
 ) -> (String, String) {
     let need_migrations_variables =
-        need_migrations.iter().map(|v| var_name(tcx, *v)).collect::<Vec<_>>();
+        need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::<Vec<_>>();
 
     let migration_ref_concat =
         need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
@@ -1985,6 +2103,48 @@ fn determine_place_ancestry_relation(
     }
 }
 
+/// Reduces the precision of the captured place when the precision doesn't yeild any benefit from
+/// borrow checking prespective, allowing us to save us on the size of the capture.
+///
+///
+/// Fields that are read through a shared reference will always be read via a shared ref or a copy,
+/// and therefore capturing precise paths yields no benefit. This optimization truncates the
+/// rightmost deref of the capture if the deref is applied to a shared ref.
+///
+/// Reason we only drop the last deref is because of the following edge case:
+///
+/// ```rust
+/// struct MyStruct<'a> {
+///    a: &'static A,
+///    b: B,
+///    c: C<'a>,
+/// }
+///
+/// fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
+///     let c = || drop(&*m.a.field_of_a);
+///     // Here we really do want to capture `*m.a` because that outlives `'static`
+///
+///     // If we capture `m`, then the closure no longer outlives `'static'
+///     // it is constrained to `'a`
+/// }
+/// ```
+fn truncate_capture_for_optimization<'tcx>(place: &Place<'tcx>) -> Place<'tcx> {
+    let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
+
+    // Find the right-most deref (if any). All the projections that come after this
+    // are fields or other "in-place pointer adjustments"; these refer therefore to
+    // data owned by whatever pointer is being dereferenced here.
+    let idx = place.projections.iter().rposition(|proj| ProjectionKind::Deref == proj.kind);
+
+    match idx {
+        // If that pointer is a shared reference, then we don't need those fields.
+        Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => {
+            Place { projections: place.projections[0..=idx].to_vec(), ..place.clone() }
+        }
+        None | Some(_) => place.clone(),
+    }
+}
+
 /// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
 /// user is using Rust Edition 2021 or higher.
 ///
index 0e063c86f2f4eb208aab39215388a5eb81570140..4838d70a83186843150cf2d5b7f25a8512163a08 100644 (file)
@@ -738,15 +738,19 @@ fn check_where_clauses<'tcx, 'fcx>(
                 }
             }
             GenericParamDefKind::Const { .. } => {
-                // FIXME(const_generics_defaults): Figure out if this
-                // is the behavior we want, see the comment further below.
                 if is_our_default(&param) {
+                    // FIXME(const_generics_defaults): This
+                    // is incorrect when dealing with unused substs, for example
+                    // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
+                    // we should eagerly error.
                     let default_ct = tcx.const_param_default(param.def_id);
-                    fcx.register_wf_obligation(
-                        default_ct.into(),
-                        tcx.def_span(param.def_id),
-                        ObligationCauseCode::MiscObligation,
-                    );
+                    if !default_ct.needs_subst() {
+                        fcx.register_wf_obligation(
+                            default_ct.into(),
+                            tcx.def_span(param.def_id),
+                            ObligationCauseCode::MiscObligation,
+                        );
+                    }
                 }
             }
             // Doesn't have defaults.
@@ -783,14 +787,6 @@ fn check_where_clauses<'tcx, 'fcx>(
                 tcx.mk_param_from_def(param)
             }
             GenericParamDefKind::Const { .. } => {
-                // FIXME(const_generics_defaults): I(@lcnr) feel like always
-                // using the const parameter is the right choice here, even
-                // if it needs substs.
-                //
-                // Before stabilizing this we probably want to get some tests
-                // where this makes a difference and figure out what's the exact
-                // behavior we want here.
-
                 // If the param has a default, ...
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
index 836bed2a156354e43a1c9ca863169fe460d565de..7e5cc771b3199a20ee75774b7f6f53a2858f916d 100644 (file)
@@ -116,6 +116,8 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         crates_to_lint: &mut crates_to_lint,
     });
 
+    let extern_prelude = &tcx.resolutions(()).extern_prelude;
+
     for extern_crate in &crates_to_lint {
         let def_id = extern_crate.def_id.expect_local();
         let id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -155,7 +157,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         // If the extern crate isn't in the extern prelude,
         // there is no way it can be written as an `use`.
         let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name);
-        if !tcx.extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
+        if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
             continue;
         }
 
index b0e5453b7db924079e1c2f4dcb77d307faf42505..506ca98b96026180e84e5be71fb5b07161e4fbb3 100644 (file)
@@ -92,6 +92,7 @@ pub fn provide(providers: &mut Providers) {
         generator_kind,
         codegen_fn_attrs,
         collect_mod_item_types,
+        should_inherit_track_caller,
         ..*providers
     };
 }
@@ -2308,6 +2309,16 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
                 ));
             }
         }
+
+        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
+            // Do not look into const param defaults,
+            // these get checked when they are actually instantiated.
+            //
+            // We do not want the following to error:
+            //
+            //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
+            //     struct Bar<const N: usize>(Foo<N, 3>);
+        }
     }
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -2676,7 +2687,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
     let attrs = tcx.get_attrs(id);
 
     let mut codegen_fn_attrs = CodegenFnAttrs::new();
-    if should_inherit_track_caller(tcx, id) {
+    if tcx.should_inherit_track_caller(id) {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
index 13b42442dcf0979e6f9832f2e5913ae9a2535b85..53bfe02d0e7a31d43d8c56790a402cd3fbbfc748 100644 (file)
@@ -187,8 +187,6 @@ impl<T> Box<T> {
     /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline(always)]
-    #[doc(alias = "alloc")]
-    #[doc(alias = "malloc")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(x: T) -> Self {
         box x
@@ -239,7 +237,6 @@ pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
     #[inline]
-    #[doc(alias = "calloc")]
     #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> {
         Self::new_zeroed_in(Global)
index 544e18d1ff3911cea4f2d4295598d1b5422c6d37..2f656e4a6b4acc2d5cb18ddd5c6c3a7a7462c90c 100644 (file)
@@ -1034,7 +1034,6 @@ pub fn into_vec(self) -> Vec<T> {
     ///
     /// assert_eq!(heap.len(), 2);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.data.len()
index d7519c6d0936c186490cc0ba43f3f81e8c78d590..dfd693d13b330f51a222324e2970598f1800134d 100644 (file)
@@ -889,7 +889,6 @@ pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[doc(alias = "delete")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
     where
@@ -2165,7 +2164,6 @@ pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
     /// a.insert(1, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
     pub const fn len(&self) -> usize {
index 17568f7b005ba64d5b28e503027d0068d2ee68bf..bf3542b384d78715117c3094c2feae0ce41c7083 100644 (file)
@@ -47,14 +47,12 @@ pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a V)> {
 
     #[inline]
     pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
-        debug_assert!(self.front.is_some());
-        unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+        unsafe { self.front.as_mut().unwrap().next_unchecked() }
     }
 
     #[inline]
     pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
-        debug_assert!(self.back.is_some());
-        unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+        unsafe { self.back.as_mut().unwrap().next_back_unchecked() }
     }
 }
 
@@ -71,14 +69,12 @@ pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
 
     #[inline]
     pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
-        debug_assert!(self.front.is_some());
-        unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+        unsafe { self.front.as_mut().unwrap().next_unchecked() }
     }
 
     #[inline]
     pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
-        debug_assert!(self.back.is_some());
-        unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+        unsafe { self.back.as_mut().unwrap().next_back_unchecked() }
     }
 }
 
@@ -400,9 +396,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
     /// There must be another KV in the direction travelled.
     unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
         super::mem::replace(self, |leaf_edge| {
-            let kv = leaf_edge.next_kv();
-            debug_assert!(kv.is_ok());
-            let kv = unsafe { kv.ok().unwrap_unchecked() };
+            let kv = leaf_edge.next_kv().ok().unwrap();
             (kv.next_leaf_edge(), kv.into_kv())
         })
     }
@@ -414,9 +408,7 @@ unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
     /// There must be another KV in the direction travelled.
     unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
         super::mem::replace(self, |leaf_edge| {
-            let kv = leaf_edge.next_back_kv();
-            debug_assert!(kv.is_ok());
-            let kv = unsafe { kv.ok().unwrap_unchecked() };
+            let kv = leaf_edge.next_back_kv().ok().unwrap();
             (kv.next_back_leaf_edge(), kv.into_kv())
         })
     }
@@ -430,9 +422,7 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
     /// There must be another KV in the direction travelled.
     unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
         let kv = super::mem::replace(self, |leaf_edge| {
-            let kv = leaf_edge.next_kv();
-            debug_assert!(kv.is_ok());
-            let kv = unsafe { kv.ok().unwrap_unchecked() };
+            let kv = leaf_edge.next_kv().ok().unwrap();
             (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
         });
         // Doing this last is faster, according to benchmarks.
@@ -446,9 +436,7 @@ unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
     /// There must be another KV in the direction travelled.
     unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
         let kv = super::mem::replace(self, |leaf_edge| {
-            let kv = leaf_edge.next_back_kv();
-            debug_assert!(kv.is_ok());
-            let kv = unsafe { kv.ok().unwrap_unchecked() };
+            let kv = leaf_edge.next_back_kv().ok().unwrap();
             (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
         });
         // Doing this last is faster, according to benchmarks.
@@ -472,9 +460,7 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
     pub unsafe fn deallocating_next_unchecked(
         &mut self,
     ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
-        super::mem::replace(self, |leaf_edge| unsafe {
-            leaf_edge.deallocating_next().unwrap_unchecked()
-        })
+        super::mem::replace(self, |leaf_edge| unsafe { leaf_edge.deallocating_next().unwrap() })
     }
 
     /// Moves the leaf edge handle to the previous leaf edge and returns the key and value
@@ -493,7 +479,7 @@ unsafe fn deallocating_next_back_unchecked(
         &mut self,
     ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
         super::mem::replace(self, |leaf_edge| unsafe {
-            leaf_edge.deallocating_next_back().unwrap_unchecked()
+            leaf_edge.deallocating_next_back().unwrap()
         })
     }
 }
index 737932d931c0283647c3d06bc5ff5d201c299a9e..45ea30b538691743611a54c7fd2fdb997322e5a9 100644 (file)
@@ -810,7 +810,6 @@ pub fn replace(&mut self, value: T) -> Option<T>
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    #[doc(alias = "delete")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
     where
@@ -941,18 +940,20 @@ pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
         BTreeSet { map: self.map.split_off(key) }
     }
 
-    /// Creates an iterator which uses a closure to determine if a value should be removed.
+    /// Creates an iterator that visits all values in ascending order and uses a closure
+    /// to determine if a value should be removed.
     ///
-    /// If the closure returns true, then the value is removed and yielded.
-    /// If the closure returns false, the value will remain in the list and will not be yielded
-    /// by the iterator.
+    /// If the closure returns `true`, the value is removed from the set and yielded. If
+    /// the closure returns `false`, or panics, the value remains in the set and will
+    /// not be yielded.
     ///
-    /// If the iterator is only partially consumed or not consumed at all, each of the remaining
-    /// values will still be subjected to the closure and removed and dropped if it returns true.
+    /// If the iterator is only partially consumed or not consumed at all, each of the
+    /// remaining values is still subjected to the closure and removed and dropped if it
+    /// returns `true`.
     ///
-    /// It is unspecified how many more values will be subjected to the closure
-    /// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the
-    /// `DrainFilter` itself is leaked.
+    /// It is unspecified how many more values will be subjected to the closure if a
+    /// panic occurs in the closure, or if a panic occurs while dropping a value, or if
+    /// the `DrainFilter` itself is leaked.
     ///
     /// # Examples
     ///
@@ -1021,7 +1022,6 @@ pub fn iter(&self) -> Iter<'_, T> {
     /// v.insert(1);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
     pub const fn len(&self) -> usize {
index ea216786ea2d45a6a815565f92baa662e408b33d..588ba2de2209bcd32e1ae3425a48c87bc2b44e5d 100644 (file)
@@ -586,7 +586,6 @@ pub fn is_empty(&self) -> bool {
     /// dl.push_back(3);
     /// assert_eq!(dl.len(), 3);
     /// ```
-    #[doc(alias = "length")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
index b9b3d650ea204dae0a5b040ad41a93edc2933c23..97bfe2f3984ea2559ebcceb37ae4367c7ad9f1c4 100644 (file)
@@ -83,6 +83,7 @@ pub enum TryReserveError {
 
 #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
 impl From<LayoutError> for TryReserveError {
+    /// Always evaluates to [`TryReserveError::CapacityOverflow`].
     #[inline]
     fn from(_: LayoutError) -> Self {
         TryReserveError::CapacityOverflow
index 5d03be35e466fea7e14994ccfe7200c1d9f03c3c..461e701be054ee82b9493ef0ba0d27ec95f14668 100644 (file)
@@ -1036,7 +1036,6 @@ pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
     /// v.push_back(1);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         count(self.tail, self.head, self.cap())
index 6a64587a2237fb7059ef3af6a5770b04c481ee6a..189da9f06392add94c1ac45a83e982a28715d4f1 100644 (file)
@@ -35,8 +35,6 @@
 ///
 /// [`Vec`]: crate::vec::Vec
 #[cfg(not(test))]
-#[doc(alias = "alloc")]
-#[doc(alias = "malloc")]
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(box_syntax, liballoc_internals)]
index d0cf6244756761821cc2ad41b5d0ee791ef7fb82..0d8678291bef749536a7a30b003ff84aa6e9eab7 100644 (file)
@@ -419,8 +419,6 @@ pub const fn new() -> String {
     /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
-    #[doc(alias = "alloc")]
-    #[doc(alias = "malloc")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize) -> String {
         String { vec: Vec::with_capacity(capacity) }
@@ -1534,7 +1532,6 @@ pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
     /// assert_eq!(fancy_f.len(), 4);
     /// assert_eq!(fancy_f.chars().count(), 3);
     /// ```
-    #[doc(alias = "length")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
index 4ac28b8308e73126a111d8a21da78c0a9f349e50..61599259735c7d5a25632b46f5c58f41227a8384 100644 (file)
@@ -459,7 +459,6 @@ pub const fn new() -> Self {
     /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
-    #[doc(alias = "malloc")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize) -> Self {
         Self::with_capacity_in(capacity, Global)
@@ -799,7 +798,6 @@ pub fn capacity(&self) -> usize {
     /// assert!(vec.capacity() >= 11);
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[doc(alias = "realloc")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: usize) {
         self.buf.reserve(self.len, additional);
@@ -826,7 +824,6 @@ pub fn reserve(&mut self, additional: usize) {
     /// assert!(vec.capacity() >= 11);
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[doc(alias = "realloc")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_exact(&mut self, additional: usize) {
         self.buf.reserve_exact(self.len, additional);
@@ -864,7 +861,6 @@ pub fn reserve_exact(&mut self, additional: usize) {
     /// }
     /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
     /// ```
-    #[doc(alias = "realloc")]
     #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.buf.try_reserve(self.len, additional)
@@ -906,7 +902,6 @@ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
     /// }
     /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
     /// ```
-    #[doc(alias = "realloc")]
     #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
     pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.buf.try_reserve_exact(self.len, additional)
@@ -927,7 +922,6 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE
     /// assert!(vec.capacity() >= 3);
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[doc(alias = "realloc")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         // The capacity is never less than the length, and there's nothing to do when
@@ -958,7 +952,6 @@ pub fn shrink_to_fit(&mut self) {
     /// assert!(vec.capacity() >= 3);
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[doc(alias = "realloc")]
     #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
     pub fn shrink_to(&mut self, min_capacity: usize) {
         if self.capacity() > min_capacity {
@@ -1820,7 +1813,6 @@ pub fn clear(&mut self) {
     /// let a = vec![1, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
-    #[doc(alias = "length")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs
new file mode 100644 (file)
index 0000000..6d66b9e
--- /dev/null
@@ -0,0 +1,160 @@
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
+where
+    A: PartialEq<B>,
+{
+    #[inline]
+    fn eq(&self, other: &[B; N]) -> bool {
+        SpecArrayEq::spec_eq(self, other)
+    }
+    #[inline]
+    fn ne(&self, other: &[B; N]) -> bool {
+        SpecArrayEq::spec_ne(self, other)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
+where
+    A: PartialEq<B>,
+{
+    #[inline]
+    fn eq(&self, other: &[B]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &[B]) -> bool {
+        self[..] != other[..]
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
+where
+    B: PartialEq<A>,
+{
+    #[inline]
+    fn eq(&self, other: &[A; N]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &[A; N]) -> bool {
+        self[..] != other[..]
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<&[B]> for [A; N]
+where
+    A: PartialEq<B>,
+{
+    #[inline]
+    fn eq(&self, other: &&[B]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &&[B]) -> bool {
+        self[..] != other[..]
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[A; N]> for &[B]
+where
+    B: PartialEq<A>,
+{
+    #[inline]
+    fn eq(&self, other: &[A; N]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &[A; N]) -> bool {
+        self[..] != other[..]
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<&mut [B]> for [A; N]
+where
+    A: PartialEq<B>,
+{
+    #[inline]
+    fn eq(&self, other: &&mut [B]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &&mut [B]) -> bool {
+        self[..] != other[..]
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[A; N]> for &mut [B]
+where
+    B: PartialEq<A>,
+{
+    #[inline]
+    fn eq(&self, other: &[A; N]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &[A; N]) -> bool {
+        self[..] != other[..]
+    }
+}
+
+// NOTE: some less important impls are omitted to reduce code bloat
+// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
+// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Eq, const N: usize> Eq for [T; N] {}
+
+trait SpecArrayEq<Other, const N: usize>: Sized {
+    fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool;
+    fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool;
+}
+
+impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
+    default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool {
+        a[..] == b[..]
+    }
+    default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool {
+        a[..] != b[..]
+    }
+}
+
+impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T {
+    #[cfg(bootstrap)]
+    fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
+        a[..] == b[..]
+    }
+    #[cfg(not(bootstrap))]
+    fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
+        // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`.
+        unsafe {
+            let b = &*b.as_ptr().cast::<[T; N]>();
+            crate::intrinsics::raw_eq(a, b)
+        }
+    }
+    fn spec_ne(a: &[T; N], b: &[U; N]) -> bool {
+        !Self::spec_eq(a, b)
+    }
+}
+
+/// `U` exists on here mostly because `min_specialization` didn't let me
+/// repeat the `T` type parameter in the above specialization, so instead
+/// the `T == U` constraint comes from the impls on this.
+/// # Safety
+/// - Neither `Self` nor `U` has any padding.
+/// - `Self` and `U` have the same layout.
+/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things)
+#[rustc_specialization_trait]
+unsafe trait IsRawEqComparable<U> {}
+
+macro_rules! is_raw_comparable {
+    ($($t:ty),+) => {$(
+        unsafe impl IsRawEqComparable<$t> for $t {}
+    )+};
+}
+is_raw_comparable!(bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
index 030b42a53d05d757f0b35953ce9f268fed89e8a7..32d344010aafd3dea55d6f85f06144e0df384cc6 100644 (file)
@@ -14,6 +14,7 @@
 use crate::ops::{Index, IndexMut};
 use crate::slice::{Iter, IterMut};
 
+mod equality;
 mod iter;
 
 #[stable(feature = "array_value_iter", since = "1.51.0")]
@@ -230,118 +231,6 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
-where
-    A: PartialEq<B>,
-{
-    #[inline]
-    fn eq(&self, other: &[B; N]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &[B; N]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
-where
-    A: PartialEq<B>,
-{
-    #[inline]
-    fn eq(&self, other: &[B]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &[B]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
-where
-    B: PartialEq<A>,
-{
-    #[inline]
-    fn eq(&self, other: &[A; N]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &[A; N]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<&[B]> for [A; N]
-where
-    A: PartialEq<B>,
-{
-    #[inline]
-    fn eq(&self, other: &&[B]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &&[B]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[A; N]> for &[B]
-where
-    B: PartialEq<A>,
-{
-    #[inline]
-    fn eq(&self, other: &[A; N]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &[A; N]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<&mut [B]> for [A; N]
-where
-    A: PartialEq<B>,
-{
-    #[inline]
-    fn eq(&self, other: &&mut [B]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &&mut [B]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[A; N]> for &mut [B]
-where
-    B: PartialEq<A>,
-{
-    #[inline]
-    fn eq(&self, other: &[A; N]) -> bool {
-        self[..] == other[..]
-    }
-    #[inline]
-    fn ne(&self, other: &[A; N]) -> bool {
-        self[..] != other[..]
-    }
-}
-
-// NOTE: some less important impls are omitted to reduce code bloat
-// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
-// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq, const N: usize> Eq for [T; N] {}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
     #[inline]
index 00164c631b305799cd760426cdfda0f08c752433..dcafaae2f5b493a4a858462f589cc52ade71e76b 100644 (file)
@@ -12,7 +12,7 @@ impl bool {
     /// assert_eq!(false.then_some(0), None);
     /// assert_eq!(true.then_some(0), Some(0));
     /// ```
-    #[unstable(feature = "bool_to_option", issue = "64260")]
+    #[unstable(feature = "bool_to_option", issue = "80967")]
     #[inline]
     pub fn then_some<T>(self, t: T) -> Option<T> {
         if self { Some(t) } else { None }
index b4311bbe5f41fa6ccd3a6495776c0ed2d012ef02..238f00e41b3afae97c1b765cd753f197958b0dd5 100644 (file)
@@ -717,8 +717,14 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// Therefore, implementations must not require the user to uphold
     /// any safety invariants.
     ///
-    /// A more user-friendly and stable version of this operation is
-    /// [`std::process::abort`](../../std/process/fn.abort.html).
+    /// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible,
+    /// as its behavior is more user-friendly and more stable.
+    ///
+    /// The current implementation of `intrinsics::abort` is to invoke an invalid instruction,
+    /// on most platforms.
+    /// On Unix, the
+    /// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
+    /// `SIGBUS`.  The precise behaviour is not guaranteed and not stable.
     pub fn abort() -> !;
 
     /// Informs the optimizer that this point in the code is not reachable,
@@ -1907,6 +1913,26 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// Allocate at compile time. Should not be called at runtime.
     #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
     pub fn const_allocate(size: usize, align: usize) -> *mut u8;
+
+    /// Determines whether the raw bytes of the two values are equal.
+    ///
+    /// The is particularly handy for arrays, since it allows things like just
+    /// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`.
+    ///
+    /// Above some backend-decided threshold this will emit calls to `memcmp`,
+    /// like slice equality does, instead of causing massive code size.
+    ///
+    /// # Safety
+    ///
+    /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized.
+    /// Note that this is a stricter criterion than just the *values* being
+    /// fully-initialized: if `T` has padding, it's UB to call this intrinsic.
+    ///
+    /// (The implementation is allowed to branch on the results of comparisons,
+    /// which is UB if any of their inputs are `undef`.)
+    #[cfg(not(bootstrap))]
+    #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
+    pub fn raw_eq<T>(a: &T, b: &T) -> bool;
 }
 
 // Some functions are defined here because they accidentally got made
index e2a407509b10dce04dc3d8d901264c4e1579a6e5..7f87ead6feed6c132faec40398c48dc1912591e6 100644 (file)
@@ -89,6 +89,7 @@
                over elements of type `{A}`",
     label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
 )]
+#[rustc_diagnostic_item = "FromIterator"]
 pub trait FromIterator<A>: Sized {
     /// Creates a value from an iterator.
     ///
@@ -238,6 +239,7 @@ impl<I: Iterator> IntoIterator for I {
     type Item = I::Item;
     type IntoIter = I;
 
+    #[inline]
     fn into_iter(self) -> I {
         self
     }
index 167db3359f240de67031851341ee8edbe1fb6dff..a476799b70d6c60088f66c76c3c9c5989730faca 100644 (file)
@@ -97,7 +97,6 @@ pub trait ExactSizeIterator: Iterator {
     ///
     /// assert_eq!(5, five.len());
     /// ```
-    #[doc(alias = "length")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn len(&self) -> usize {
index 0032e8c3e47e0b61a2df2b8f443b09e981d289eb..8cb7aad28aa95e791ec479975f0fe6997c13cabf 100644 (file)
@@ -2254,7 +2254,6 @@ fn reduce<F>(mut self, f: F) -> Option<Self::Item>
     /// // we can still use `iter`, as there are more elements.
     /// assert_eq!(iter.next(), Some(&3));
     /// ```
-    #[doc(alias = "every")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn all<F>(&mut self, f: F) -> bool
index 866cd5ec535d2c5e8af3982f9ff94abdc5eb1f95..3557dbad90cc215f01af0e199f63879b0c2a3183 100644 (file)
 #![feature(no_niche)] // rust-lang/rust#68303
 #![feature(no_coverage)] // rust-lang/rust#84605
 #![deny(unsafe_op_in_unsafe_fn)]
-#![deny(or_patterns_back_compat)]
+#![cfg_attr(bootstrap, deny(or_patterns_back_compat))]
+#![cfg_attr(not(bootstrap), deny(rust_2021_incompatible_or_patterns))]
 
 // allow using `core::` in intra-doc links
 #[allow(unused_extern_crates)]
index 271565693d66e09c78de20211a40f80993982299..fb957348bebd3837dbfc60d43efa5c389fb7fb2b 100644 (file)
@@ -31,7 +31,6 @@
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")]
-#[lang = "send"]
 #[rustc_on_unimplemented(
     message = "`{Self}` cannot be sent between threads safely",
     label = "`{Self}` cannot be sent between threads safely"
index 3dfbd98fa6c7bf4c1929209eb4a7c82e7d883679..5122421ea8c852fdef7afbbba7c3f58075f49a0f 100644 (file)
@@ -79,7 +79,7 @@
 /// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
 /// let mut x = MaybeUninit::<&i32>::uninit();
 /// // Set it to a valid value.
-/// unsafe { x.as_mut_ptr().write(&0); }
+/// x.write(&0);
 /// // Extract the initialized data -- this is only allowed *after* properly
 /// // initializing `x`!
 /// let x = unsafe { x.assume_init() };
 ///     // this loop, we have a memory leak, but there is no memory safety
 ///     // issue.
 ///     for elem in &mut data[..] {
-///         *elem = MaybeUninit::new(vec![42]);
+///         elem.write(vec![42]);
 ///     }
 ///
 ///     // Everything is initialized. Transmute the array to the
 /// let mut data_len: usize = 0;
 ///
 /// for elem in &mut data[0..500] {
-///     *elem = MaybeUninit::new(String::from("hello"));
+///     elem.write(String::from("hello"));
 ///     data_len += 1;
 /// }
 ///
@@ -410,7 +410,7 @@ pub fn zeroed() -> MaybeUninit<T> {
     /// (now safely initialized) contents of `self`.
     ///
     /// As the content is stored inside a `MaybeUninit`, the destructor is not
-    /// ran for the inner data if the MaybeUninit leaves scope without a call to
+    /// run for the inner data if the MaybeUninit leaves scope without a call to
     /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives
     /// the mutable reference returned by this function needs to keep this in
     /// mind. The safety model of Rust regards leaks as safe, but they are
@@ -426,7 +426,6 @@ pub fn zeroed() -> MaybeUninit<T> {
     /// Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit_extra)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u8>>::uninit();
@@ -445,7 +444,6 @@ pub fn zeroed() -> MaybeUninit<T> {
     /// This usage of the method causes a leak:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit_extra)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<String>::uninit();
@@ -456,8 +454,38 @@ pub fn zeroed() -> MaybeUninit<T> {
     /// // x is initialized now:
     /// let s = unsafe { x.assume_init() };
     /// ```
-    #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
-    #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
+    ///
+    /// This method can be used to avoid unsafe in some cases. The example below
+    /// shows a part of an implementation of a fixed sized arena that lends out
+    /// pinned references.
+    /// With `write`, we can avoid the need to write through a raw pointer:
+    ///
+    /// ```rust
+    /// #![feature(maybe_uninit_extra)]
+    /// use core::pin::Pin;
+    /// use core::mem::MaybeUninit;
+    ///
+    /// struct PinArena<T> {
+    ///     memory: Box<[MaybeUninit<T>]>,
+    ///     len: usize,
+    /// }
+    ///
+    /// impl <T> PinArena<T> {
+    ///     pub fn capacity(&self) -> usize {
+    ///         self.memory.len()
+    ///     }
+    ///     pub fn push(&mut self, val: T) -> Pin<&mut T> {
+    ///         if self.len >= self.capacity() {
+    ///             panic!("Attempted to push to a full pin arena!");
+    ///         }
+    ///         let ref_ = self.memory[self.len].write(val);
+    ///         self.len += 1;
+    ///         unsafe { Pin::new_unchecked(ref_) }
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "maybe_uninit_write", since = "1.55.0")]
+    #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")]
     #[inline(always)]
     pub const fn write(&mut self, val: T) -> &mut T {
         *self = MaybeUninit::new(val);
@@ -478,7 +506,7 @@ pub const fn write(&mut self, val: T) -> &mut T {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
-    /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
+    /// x.write(vec![0, 1, 2]);
     /// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
     /// let x_vec = unsafe { &*x.as_ptr() };
     /// assert_eq!(x_vec.len(), 3);
@@ -515,7 +543,7 @@ pub const fn as_ptr(&self) -> *const T {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
-    /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
+    /// x.write(vec![0, 1, 2]);
     /// // Create a reference into the `MaybeUninit<Vec<u32>>`.
     /// // This is okay because we initialized it.
     /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
@@ -574,7 +602,7 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<bool>::uninit();
-    /// unsafe { x.as_mut_ptr().write(true); }
+    /// x.write(true);
     /// let x_init = unsafe { x.assume_init() };
     /// assert_eq!(x_init, true);
     /// ```
@@ -723,7 +751,7 @@ pub unsafe fn assume_init_drop(&mut self) {
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
     /// // Initialize `x`:
-    /// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
+    /// x.write(vec![1, 2, 3]);
     /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
     /// // create a shared reference to it:
     /// let x: &Vec<u32> = unsafe {
@@ -897,9 +925,9 @@ pub unsafe fn assume_init_drop(&mut self) {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array();
-    /// array[0] = MaybeUninit::new(0);
-    /// array[1] = MaybeUninit::new(1);
-    /// array[2] = MaybeUninit::new(2);
+    /// array[0].write(0);
+    /// array[1].write(1);
+    /// array[2].write(2);
     ///
     /// // SAFETY: Now safe as we initialised all elements
     /// let array = unsafe {
diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs
new file mode 100644 (file)
index 0000000..a23ca51
--- /dev/null
@@ -0,0 +1,134 @@
+mod unchecked {
+    // 0 < val <= u8::MAX
+    pub const fn u8(val: u8) -> u32 {
+        if val >= 100 {
+            2
+        } else if val >= 10 {
+            1
+        } else {
+            0
+        }
+    }
+
+    // 0 < val <= u16::MAX
+    pub const fn u16(val: u16) -> u32 {
+        if val >= 10_000 {
+            4
+        } else if val >= 1000 {
+            3
+        } else if val >= 100 {
+            2
+        } else if val >= 10 {
+            1
+        } else {
+            0
+        }
+    }
+
+    // 0 < val < 100_000_000
+    const fn less_than_8(mut val: u32) -> u32 {
+        let mut log = 0;
+        if val >= 10_000 {
+            val /= 10_000;
+            log += 4;
+        }
+        log + if val >= 1000 {
+            3
+        } else if val >= 100 {
+            2
+        } else if val >= 10 {
+            1
+        } else {
+            0
+        }
+    }
+
+    // 0 < val <= u32::MAX
+    pub const fn u32(mut val: u32) -> u32 {
+        let mut log = 0;
+        if val >= 100_000_000 {
+            val /= 100_000_000;
+            log += 8;
+        }
+        log + less_than_8(val)
+    }
+
+    // 0 < val < 10_000_000_000_000_000
+    const fn less_than_16(mut val: u64) -> u32 {
+        let mut log = 0;
+        if val >= 100_000_000 {
+            val /= 100_000_000;
+            log += 8;
+        }
+        log + less_than_8(val as u32)
+    }
+
+    // 0 < val <= u64::MAX
+    pub const fn u64(mut val: u64) -> u32 {
+        let mut log = 0;
+        if val >= 10_000_000_000_000_000 {
+            val /= 10_000_000_000_000_000;
+            log += 16;
+        }
+        log + less_than_16(val)
+    }
+
+    // 0 < val <= u128::MAX
+    pub const fn u128(mut val: u128) -> u32 {
+        let mut log = 0;
+        if val >= 100_000_000_000_000_000_000_000_000_000_000 {
+            val /= 100_000_000_000_000_000_000_000_000_000_000;
+            log += 32;
+            return log + less_than_8(val as u32);
+        }
+        if val >= 10_000_000_000_000_000 {
+            val /= 10_000_000_000_000_000;
+            log += 16;
+        }
+        log + less_than_16(val as u64)
+    }
+
+    // 0 < val <= i8::MAX
+    pub const fn i8(val: i8) -> u32 {
+        u8(val as u8)
+    }
+
+    // 0 < val <= i16::MAX
+    pub const fn i16(val: i16) -> u32 {
+        u16(val as u16)
+    }
+
+    // 0 < val <= i32::MAX
+    pub const fn i32(val: i32) -> u32 {
+        u32(val as u32)
+    }
+
+    // 0 < val <= i64::MAX
+    pub const fn i64(val: i64) -> u32 {
+        u64(val as u64)
+    }
+
+    // 0 < val <= i128::MAX
+    pub const fn i128(val: i128) -> u32 {
+        u128(val as u128)
+    }
+}
+
+macro_rules! impl_checked {
+    ($T:ident) => {
+        pub const fn $T(val: $T) -> Option<$T> {
+            if val > 0 { Some(unchecked::$T(val) as $T) } else { None }
+        }
+    };
+}
+
+impl_checked! { u8 }
+impl_checked! { u16 }
+impl_checked! { u32 }
+impl_checked! { u64 }
+impl_checked! { u128 }
+impl_checked! { i8 }
+impl_checked! { i16 }
+impl_checked! { i32 }
+impl_checked! { i64 }
+impl_checked! { i128 }
index 2e466106fe553960074c807334b6e920a218b2bd..982729388c87dc6ebbf918bbdd03685849c0abb0 100644 (file)
@@ -1744,6 +1744,197 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
             }
         }
 
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `log2` can produce results more efficiently for base 2, and `log10`
+        /// can produce results more efficiently for base 10.
+        ///
+        /// # Panics
+        ///
+        /// When the number is zero, or if the base is not at least 2; it
+        /// panics in debug mode and the return value is wrapped to 0 in release
+        /// mode (the only situation in which the method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log(self, base: Self) -> Self {
+            match self.checked_log(base) {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is zero it panics in debug mode and the return value
+        /// is wrapped to 0 in release mode (the only situation in which the
+        /// method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log2(self) -> Self {
+            match self.checked_log2() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is zero it panics in debug mode and the return value
+        /// is wrapped to 0 in release mode (the only situation in which the
+        /// method can return 0).
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log10(self) -> Self {
+            match self.checked_log10() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// Returns `None` if the number is negative or zero, or if the base is not at least 2.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `checked_log2` can produce results more efficiently for base 2, and
+        /// `checked_log10` can produce results more efficiently for base 10.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log(self, base: Self) -> Option<Self> {
+            if self <= 0 || base <= 1 {
+                None
+            } else {
+                let mut n = 0;
+                let mut r = self;
+
+                // Optimization for 128 bit wide integers.
+                if Self::BITS == 128 {
+                    let b = Self::log2(self) / (Self::log2(base) + 1);
+                    n += b;
+                    r /= base.pow(b as u32);
+                }
+
+                while r >= base {
+                    r /= base;
+                    n += 1;
+                }
+                Some(n)
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// Returns `None` if the number is negative or zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log2(self) -> Option<Self> {
+            if self <= 0 {
+                None
+            } else {
+                // SAFETY: We just checked that this number is positive
+                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                Some(log)
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// Returns `None` if the number is negative or zero.
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log10(self) -> Option<Self> {
+            match int_log10::$ActualT(self as $ActualT) {
+                Some(s) => Some(s as Self),
+                None => None,
+            }
+        }
+
         /// Computes the absolute value of `self`.
         ///
         /// # Overflow behavior
index 81d00c281ade85fd39c49d2867c2cc33144c06eb..26d84a60702c56b30dfd8f8918021627d9882b18 100644 (file)
@@ -41,6 +41,7 @@ macro_rules! unlikely {
 mod uint_macros; // import uint_impl!
 
 mod error;
+mod int_log10;
 mod nonzero;
 mod wrapping;
 
index e512d90ef3735d31311073c7378c526a04467e2b..ca1b05fdfbe48a779471995dd7709c9a8baf7d38 100644 (file)
@@ -1,5 +1,5 @@
 macro_rules! uint_impl {
-    ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr,
+    ($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr,
         $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
         $reversed:expr, $le_bytes:expr, $be_bytes:expr,
         $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
@@ -634,6 +634,197 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
             }
         }
 
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `log2` can produce results more efficiently for base 2, and `log10`
+        /// can produce results more efficiently for base 10.
+        ///
+        /// # Panics
+        ///
+        /// When the number is negative, zero, or if the base is not at least 2;
+        /// it panics in debug mode and the return value is wrapped to 0 in
+        /// release mode (the only situation in which the method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log(self, base: Self) -> Self {
+            match self.checked_log(base) {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is negative or zero it panics in debug mode and
+        /// the return value is wrapped to 0 in release mode (the only situation in
+        /// which the method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log2(self) -> Self {
+            match self.checked_log2() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is negative or zero it panics in debug mode and the
+        /// return value is wrapped to 0 in release mode (the only situation in
+        /// which the method can return 0).
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log10(self) -> Self {
+            match self.checked_log10() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// Returns `None` if the number is zero, or if the base is not at least 2.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `checked_log2` can produce results more efficiently for base 2, and
+        /// `checked_log10` can produce results more efficiently for base 10.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log(self, base: Self) -> Option<Self> {
+            if self <= 0 || base <= 1 {
+                None
+            } else {
+                let mut n = 0;
+                let mut r = self;
+
+                // Optimization for 128 bit wide integers.
+                if Self::BITS == 128 {
+                    let b = Self::log2(self) / (Self::log2(base) + 1);
+                    n += b;
+                    r /= base.pow(b as u32);
+                }
+
+                while r >= base {
+                    r /= base;
+                    n += 1;
+                }
+                Some(n)
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// Returns `None` if the number is zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log2(self) -> Option<Self> {
+            if self <= 0 {
+                None
+            } else {
+                // SAFETY: We just checked that this number is positive
+                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                Some(log)
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// Returns `None` if the number is zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log10(self) -> Option<Self> {
+            match int_log10::$ActualT(self as $ActualT) {
+                Some(s) => Some(s as Self),
+                None => None,
+            }
+        }
+
         /// Checked negation. Computes `-self`, returning `None` unless `self ==
         /// 0`.
         ///
index f4b1ec377d413c64f783c4f03f9ed1f1e30eddbd..aa654aa5570ee3500e65becfee6767ba47efac47 100644 (file)
@@ -11,7 +11,7 @@
 /// This destructor consists of two components:
 /// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type.
 /// - The automatically generated "drop glue" which recursively calls the destructors
-///     of the all fields of this value.
+///     of all the fields of this value.
 ///
 /// As Rust automatically calls the destructors of all contained fields,
 /// you don't have to implement `Drop` in most cases. But there are some cases where
index b2cb2f12bbfeb83d6797a93de8b68804e6e3feaf..5cbc6343e3a77424a85696d80abfe1941bd5211f 100644 (file)
@@ -1418,18 +1418,17 @@ fn last(self) -> Option<Self::Item> {
     #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
         let start = idx * self.chunk_size;
-        let end = match start.checked_add(self.chunk_size) {
-            None => self.v.len(),
-            Some(end) => cmp::min(end, self.v.len()),
-        };
         // SAFETY: the caller guarantees that `i` is in bounds,
         // which means that `start` must be in bounds of the
-        // underlying `self.v` slice, and we made sure that `end`
+        // underlying `self.v` slice, and we made sure that `len`
         // is also in bounds of `self.v`. Thus, `start` cannot overflow
         // an `isize`, and the slice constructed by `from_raw_parts`
         // is a subslice of `self.v` which is guaranteed to be valid
         // for the lifetime `'a` of `self.v`.
-        unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
+        unsafe {
+            let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size);
+            from_raw_parts(self.v.as_ptr().add(start), len)
+        }
     }
 }
 
@@ -1457,7 +1456,7 @@ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
         } else {
             let start = (len - 1 - n) * self.chunk_size;
             let end = match start.checked_add(self.chunk_size) {
-                Some(res) => cmp::min(res, self.v.len()),
+                Some(res) => cmp::min(self.v.len(), res),
                 None => self.v.len(),
             };
             let nth_back = &self.v[start..end];
@@ -1579,17 +1578,16 @@ fn last(self) -> Option<Self::Item> {
     #[doc(hidden)]
     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
         let start = idx * self.chunk_size;
-        let end = match start.checked_add(self.chunk_size) {
-            None => self.v.len(),
-            Some(end) => cmp::min(end, self.v.len()),
-        };
         // SAFETY: see comments for `Chunks::__iterator_get_unchecked`.
         //
         // Also note that the caller also guarantees that we're never called
         // with the same index again, and that no other methods that will
         // access this subslice are called, so it is valid for the returned
         // slice to be mutable.
-        unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
+        unsafe {
+            let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size);
+            from_raw_parts_mut(self.v.as_mut_ptr().add(start), len)
+        }
     }
 }
 
@@ -1619,7 +1617,7 @@ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
         } else {
             let start = (len - 1 - n) * self.chunk_size;
             let end = match start.checked_add(self.chunk_size) {
-                Some(res) => cmp::min(res, self.v.len()),
+                Some(res) => cmp::min(self.v.len(), res),
                 None => self.v.len(),
             };
             let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
index 27cb70d9c8e5ccd57e8397a0bd7b722400655b30..de25c984abf90fd729c1ce2556d469e2a7cf0ec7 100644 (file)
@@ -95,7 +95,6 @@ impl<T> [T] {
     /// let a = [1, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
-    #[doc(alias = "length")]
     #[cfg_attr(not(bootstrap), lang = "slice_len_fn")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
index 065acd3f38bb21ad37c3fd337a8536ae160708f5..7ca95a02dd8f482d42d1fac093e71297571cc790 100644 (file)
@@ -138,7 +138,6 @@ impl str {
     /// assert_eq!("ƒoo".len(), 4); // fancy f!
     /// assert_eq!("ƒoo".chars().count(), 3);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")]
     #[inline]
index f1a115563fd3e8f569282597f3011645a55bb37d..b673b36c10211a3c13f8d2168b64caea740d8288 100644 (file)
@@ -2648,7 +2648,11 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 ///
 ///     pub fn lock(&self) {
 ///         // Wait until the old value is `false`.
-///         while self.flag.compare_and_swap(false, true, Ordering::Relaxed) != false {}
+///         while self
+///             .flag
+///             .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed)
+///             .is_err()
+///         {}
 ///         // This fence synchronizes-with store in `unlock`.
 ///         fence(Ordering::Acquire);
 ///     }
@@ -2710,7 +2714,7 @@ pub fn fence(order: Ordering) {
 /// Without `compiler_fence`, the `assert_eq!` in following code
 /// is *not* guaranteed to succeed, despite everything happening in a single thread.
 /// To see why, remember that the compiler is free to swap the stores to
-/// `IMPORTANT_VARIABLE` and `IS_READ` since they are both
+/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both
 /// `Ordering::Relaxed`. If it does, and the signal handler is invoked right
 /// after `IS_READY` is updated, then the signal handler will see
 /// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`.
index f9d331063f4b190a00990e0e36b8232afe8f2d76..cc4ff1be563140d2b6d038ead4e0ecd07f2b499b 100644 (file)
@@ -44,6 +44,7 @@
 #![feature(try_trait_v2)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
+#![feature(int_log)]
 #![feature(iter_advance_by)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_intersperse)]
index 77a338daf7dcb45b60708d2c47d8013f92fc29ee..9eac279733af902a334f42184e7bb22d520675fa 100644 (file)
@@ -2,6 +2,7 @@
 
 #[test]
 fn smoke() {
+    #[derive(Clone)]
     struct TypeWithDrop;
     impl Drop for TypeWithDrop {
         fn drop(&mut self) {
@@ -16,4 +17,11 @@ fn drop(&mut self) {
     let x: Box<ManuallyDrop<[TypeWithDrop]>> =
         Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop]));
     drop(x);
+
+    // test clone and clone_from implementations
+    let mut x = ManuallyDrop::new(TypeWithDrop);
+    let y = x.clone();
+    x.clone_from(&y);
+    drop(x);
+    drop(y);
 }
diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs
new file mode 100644 (file)
index 0000000..51122c1
--- /dev/null
@@ -0,0 +1,153 @@
+//! This tests the `Integer::{log,log2,log10}` methods. These tests are in a
+//! separate file because there's both a large number of them, and not all tests
+//! can be run on Android. This is because in Android `log2` uses an imprecise
+//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53
+
+#[test]
+fn checked_log() {
+    assert_eq!(999u32.checked_log(10), Some(2));
+    assert_eq!(1000u32.checked_log(10), Some(3));
+    assert_eq!(555u32.checked_log(13), Some(2));
+    assert_eq!(63u32.checked_log(4), Some(2));
+    assert_eq!(64u32.checked_log(4), Some(3));
+    assert_eq!(10460353203u64.checked_log(3), Some(21));
+    assert_eq!(10460353202u64.checked_log(3), Some(20));
+    assert_eq!(147808829414345923316083210206383297601u128.checked_log(3), Some(80));
+    assert_eq!(147808829414345923316083210206383297600u128.checked_log(3), Some(79));
+    assert_eq!(22528399544939174411840147874772641u128.checked_log(19683), Some(8));
+    assert_eq!(22528399544939174411840147874772631i128.checked_log(19683), Some(7));
+
+    assert_eq!(0u8.checked_log(4), None);
+    assert_eq!(0u16.checked_log(4), None);
+    assert_eq!(0i8.checked_log(4), None);
+    assert_eq!(0i16.checked_log(4), None);
+
+    for i in i16::MIN..=0 {
+        assert_eq!(i.checked_log(4), None);
+    }
+    for i in 1..=i16::MAX {
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
+    }
+    for i in 1..=u16::MAX {
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
+    }
+}
+
+#[test]
+fn checked_log2() {
+    assert_eq!(5u32.checked_log2(), Some(2));
+    assert_eq!(0u64.checked_log2(), None);
+    assert_eq!(128i32.checked_log2(), Some(7));
+    assert_eq!((-55i16).checked_log2(), None);
+
+    assert_eq!(0u8.checked_log2(), None);
+    assert_eq!(0u16.checked_log2(), None);
+    assert_eq!(0i8.checked_log2(), None);
+    assert_eq!(0i16.checked_log2(), None);
+
+    for i in 1..=u8::MAX {
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
+    }
+    for i in 1..=u16::MAX {
+        // Guard against Android's imprecise f32::log2 implementation.
+        if i != 8192 && i != 32768 {
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
+        }
+    }
+    for i in i8::MIN..=0 {
+        assert_eq!(i.checked_log2(), None);
+    }
+    for i in 1..=i8::MAX {
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
+    }
+    for i in i16::MIN..=0 {
+        assert_eq!(i.checked_log2(), None);
+    }
+    for i in 1..=i16::MAX {
+        // Guard against Android's imprecise f32::log2 implementation.
+        if i != 8192 {
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
+        }
+    }
+}
+
+// Validate cases that fail on Android's imprecise float log2 implementation.
+#[test]
+#[cfg(not(target_os = "android"))]
+fn checked_log2_not_android() {
+    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
+    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
+    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
+}
+
+#[test]
+fn checked_log10() {
+    assert_eq!(0u8.checked_log10(), None);
+    assert_eq!(0u16.checked_log10(), None);
+    assert_eq!(0i8.checked_log10(), None);
+    assert_eq!(0i16.checked_log10(), None);
+
+    for i in i16::MIN..=0 {
+        assert_eq!(i.checked_log10(), None);
+    }
+    for i in 1..=i16::MAX {
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
+    }
+    for i in 1..=u16::MAX {
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
+    }
+}
+
+macro_rules! log10_loop {
+    ($T:ty, $log10_max:expr) => {
+        assert_eq!(<$T>::MAX.log10(), $log10_max);
+        for i in 0..=$log10_max {
+            let p = (10 as $T).pow(i as u32);
+            if p >= 10 {
+                assert_eq!((p - 9).log10(), i - 1);
+                assert_eq!((p - 1).log10(), i - 1);
+            }
+            assert_eq!(p.log10(), i);
+            assert_eq!((p + 1).log10(), i);
+            if p >= 10 {
+                assert_eq!((p + 9).log10(), i);
+            }
+
+            // also check `x.log(10)`
+            if p >= 10 {
+                assert_eq!((p - 9).log(10), i - 1);
+                assert_eq!((p - 1).log(10), i - 1);
+            }
+            assert_eq!(p.log(10), i);
+            assert_eq!((p + 1).log(10), i);
+            if p >= 10 {
+                assert_eq!((p + 9).log(10), i);
+            }
+        }
+    };
+}
+
+#[test]
+fn log10_u8() {
+    log10_loop! { u8, 2 }
+}
+
+#[test]
+fn log10_u16() {
+    log10_loop! { u16, 4 }
+}
+
+#[test]
+fn log10_u32() {
+    log10_loop! { u32, 9 }
+}
+
+#[test]
+fn log10_u64() {
+    log10_loop! { u64, 19 }
+}
+
+#[test]
+fn log10_u128() {
+    log10_loop! { u128, 38 }
+}
index bbb67667dfc057223743fe713c3a3046804de1e6..76e838cf6bfbd2b75983a0257a82759db353cd99 100644 (file)
@@ -29,6 +29,7 @@
 mod bignum;
 mod dec2flt;
 mod flt2dec;
+mod int_log;
 mod ops;
 mod wrapping;
 
index a1f52a9c2e88019534c64fe6355dfb791d1ad9c0..d7cb8a556367c9d76d0e9de505bc18f54198af92 100644 (file)
@@ -454,7 +454,6 @@ pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
     /// a.insert(1, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.base.len()
@@ -893,7 +892,6 @@ pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[doc(alias = "delete")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
index 5220c8ad70977657a13778eb4a16c174af444417..272e1c2be2b409dc9d3e3eb9ee2044e6139b81c3 100644 (file)
@@ -202,7 +202,6 @@ pub fn iter(&self) -> Iter<'_, T> {
     /// v.insert(1);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[doc(alias = "length")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
@@ -875,7 +874,6 @@ pub fn replace(&mut self, value: T) -> Option<T> {
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    #[doc(alias = "delete")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
index 21bd79611a5e519d6dc6ad6ee206d36c96502b64..e0cc6ad1d4231731b75470337b2c02260944d980 100644 (file)
@@ -324,18 +324,20 @@ pub fn powf(self, n: f32) -> f32 {
 
     /// Returns the square root of a number.
     ///
-    /// Returns NaN if `self` is a negative number.
+    /// Returns NaN if `self` is a negative number other than `-0.0`.
     ///
     /// # Examples
     ///
     /// ```
     /// let positive = 4.0_f32;
     /// let negative = -4.0_f32;
+    /// let negative_zero = -0.0_f32;
     ///
     /// let abs_difference = (positive.sqrt() - 2.0).abs();
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// assert!(negative.sqrt().is_nan());
+    /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
index 8c8cf73741b512aa4fa1f76833f7518ef94f4b8f..7ed65b7dafec5ccb2c8d7214bf27c37e6c87c916 100644 (file)
@@ -324,18 +324,20 @@ pub fn powf(self, n: f64) -> f64 {
 
     /// Returns the square root of a number.
     ///
-    /// Returns NaN if `self` is a negative number.
+    /// Returns NaN if `self` is a negative number other than `-0.0`.
     ///
     /// # Examples
     ///
     /// ```
     /// let positive = 4.0_f64;
     /// let negative = -4.0_f64;
+    /// let negative_zero = -0.0_f64;
     ///
     /// let abs_difference = (positive.sqrt() - 2.0).abs();
     ///
     /// assert!(abs_difference < 1e-10);
     /// assert!(negative.sqrt().is_nan());
+    /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
index ca391ffb3d56c489bd6735c3ccc8dfb5c6b0bacd..2a85f375ae2790250a74d9d72e823df4c04caefc 100644 (file)
@@ -694,7 +694,6 @@ pub fn is_empty(&self) -> bool {
     /// let os_str = OsStr::new("foo");
     /// assert_eq!(os_str.len(), 3);
     /// ```
-    #[doc(alias = "length")]
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
     #[inline]
     pub fn len(&self) -> usize {
index 36910143dc977831638df2f0f3ca13da87fdc8d9..fb928ea55985f8b599914a7723882f8136ba18a1 100644 (file)
@@ -1551,7 +1551,6 @@ fn as_inner(&self) -> &fs_imp::DirEntry {
 ///     Ok(())
 /// }
 /// ```
-#[doc(alias = "delete")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
     fs_imp::unlink(path.as_ref())
@@ -1737,8 +1736,11 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 ///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `linkat` function with no flags
-/// on Unix and the `CreateHardLink` function on Windows.
+/// This function currently corresponds the `CreateHardLink` function on Windows.
+/// On most Unix systems, it corresponds to the `linkat` function with no flags.
+/// On Android, VxWorks, and Redox, it instead corresponds to the `link` function.
+/// On MacOS, it uses the `linkat` function if it is available, but on very old
+/// systems where `linkat` is not available, `link` is selected at runtime instead.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
@@ -1986,7 +1988,6 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///     Ok(())
 /// }
 /// ```
-#[doc(alias = "delete")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
     fs_imp::rmdir(path.as_ref())
@@ -2024,7 +2025,6 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///     Ok(())
 /// }
 /// ```
-#[doc(alias = "delete")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
     fs_imp::remove_dir_all(path.as_ref())
index 127b7bf34a3dbe30a36ae40a839c5b7f7923de58..080b4b5d87f266fb77b0027465f93854012a57c9 100644 (file)
 use crate::os::windows::fs::{symlink_dir, symlink_file};
 #[cfg(windows)]
 use crate::sys::fs::symlink_junction;
+#[cfg(target_os = "macos")]
+use crate::sys::weak::weak;
+#[cfg(target_os = "macos")]
+use libc::{c_char, c_int};
 
 macro_rules! check {
     ($e:expr) => {
@@ -79,6 +83,17 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
     }
 }
 
+#[cfg(target_os = "macos")]
+fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
+    weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
+    linkat.get().is_some()
+}
+
+#[cfg(not(target_os = "macos"))]
+fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
+    return true;
+}
+
 #[test]
 fn file_test_io_smoke_test() {
     let message = "it's alright. have a good time";
@@ -1347,6 +1362,9 @@ fn symlink_hard_link() {
     if !got_symlink_permission(&tmpdir) {
         return;
     };
+    if !able_to_not_follow_symlinks_while_hard_linking() {
+        return;
+    }
 
     // Create "file", a file.
     check!(fs::File::create(tmpdir.join("file")));
index 04f13cdeb88e353f629c282ddf8bc904bf3d684b..ae0cea985d77c9b8314044d7eaad75e2e07581a1 100644 (file)
@@ -209,32 +209,6 @@ impl<T> Cursor<T>
 where
     T: AsRef<[u8]>,
 {
-    /// Returns the remaining length.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(cursor_remaining)]
-    /// use std::io::Cursor;
-    ///
-    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
-    ///
-    /// assert_eq!(buff.remaining(), 5);
-    ///
-    /// buff.set_position(2);
-    /// assert_eq!(buff.remaining(), 3);
-    ///
-    /// buff.set_position(4);
-    /// assert_eq!(buff.remaining(), 1);
-    ///
-    /// buff.set_position(6);
-    /// assert_eq!(buff.remaining(), 0);
-    /// ```
-    #[unstable(feature = "cursor_remaining", issue = "86369")]
-    pub fn remaining(&self) -> u64 {
-        (self.inner.as_ref().len() as u64).checked_sub(self.pos).unwrap_or(0)
-    }
-
     /// Returns the remaining slice.
     ///
     /// # Examples
index 63233613b4b2b60e833a13b69d38eab496be715c..ad8975c03f17564228ef611170eeabe27d08095e 100644 (file)
 pub use self::stdio::set_output_capture;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
 pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
@@ -1759,7 +1759,6 @@ pub trait Seek {
     /// # Example
     ///
     /// ```no_run
-    /// #![feature(seek_rewind)]
     /// use std::io::{Read, Seek, Write};
     /// use std::fs::OpenOptions;
     ///
@@ -1777,7 +1776,7 @@ pub trait Seek {
     /// f.read_to_string(&mut buf).unwrap();
     /// assert_eq!(&buf, hello);
     /// ```
-    #[unstable(feature = "seek_rewind", issue = "85149")]
+    #[stable(feature = "seek_rewind", since = "1.55.0")]
     fn rewind(&mut self) -> Result<()> {
         self.seek(SeekFrom::Start(0))?;
         Ok(())
index 293f0e31ce050e293a2fc9288dce34f3d9652570..206687e38fb9cfc402121d3c24c000124092102e 100644 (file)
@@ -347,7 +347,7 @@ pub fn stdin() -> Stdin {
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
 pub fn stdin_locked() -> StdinLock<'static> {
     stdin().into_locked()
 }
@@ -442,7 +442,7 @@ fn lock_any<'a>(&self) -> StdinLock<'a> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "stdio_locked", issue = "none")]
+    #[unstable(feature = "stdio_locked", issue = "86845")]
     pub fn into_locked(self) -> StdinLock<'static> {
         self.lock_any()
     }
@@ -668,7 +668,7 @@ pub fn stdout() -> Stdout {
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
 pub fn stdout_locked() -> StdoutLock<'static> {
     stdout().into_locked()
 }
@@ -745,7 +745,7 @@ fn lock_any<'a>(&self) -> StdoutLock<'a> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "stdio_locked", issue = "none")]
+    #[unstable(feature = "stdio_locked", issue = "86845")]
     pub fn into_locked(self) -> StdoutLock<'static> {
         self.lock_any()
     }
@@ -945,7 +945,7 @@ pub fn stderr() -> Stderr {
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
 pub fn stderr_locked() -> StderrLock<'static> {
     stderr().into_locked()
 }
@@ -1005,7 +1005,7 @@ fn lock_any<'a>(&self) -> StderrLock<'a> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "stdio_locked", issue = "none")]
+    #[unstable(feature = "stdio_locked", issue = "86845")]
     pub fn into_locked(self) -> StderrLock<'static> {
         self.lock_any()
     }
index b73bcf85fbee25cdddb446bd3dbe37e27f6c26f7..1beb72a9a5072344a696c13eca99646ea5d0e65d 100644 (file)
@@ -336,6 +336,10 @@ fn seek_position() -> io::Result<()> {
     assert_eq!(c.stream_position()?, 8);
     assert_eq!(c.stream_position()?, 8);
 
+    c.rewind()?;
+    assert_eq!(c.stream_position()?, 0);
+    assert_eq!(c.stream_position()?, 0);
+
     Ok(())
 }
 
index 6f389f000af93a52e2282333bc87b9743d3e6f42..8c120f4af288d0d0fb542515d210ffc0673964df 100644 (file)
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
 #![feature(integer_atomics)]
+#![feature(int_log)]
 #![feature(into_future)]
 #![feature(intra_doc_pointers)]
 #![feature(iter_zip)]
index 913c71d41087951b5d2ef41079fec089a6ebe821..e4ce788f74195cbcdf843367709412004dd4c2c5 100644 (file)
@@ -9,6 +9,8 @@
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner};
 // Used for `File::read` on intra-doc links
+use crate::ffi::OsStr;
+use crate::sealed::Sealed;
 #[allow(unused_imports)]
 use io::{Read, Write};
 
@@ -839,6 +841,43 @@ fn ino(&self) -> u64 {
     }
 }
 
+/// Sealed Unix-specific extension methods for [`fs::DirEntry`].
+#[unstable(feature = "dir_entry_ext2", issue = "85573")]
+pub trait DirEntryExt2: Sealed {
+    /// Returns a reference to the underlying `OsStr` of this entry's filename.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(dir_entry_ext2)]
+    /// use std::os::unix::fs::DirEntryExt2;
+    /// use std::{fs, io};
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut entries = fs::read_dir(".")?.collect::<Result<Vec<_>, io::Error>>()?;
+    ///     entries.sort_unstable_by(|a, b| a.file_name_ref().cmp(b.file_name_ref()));
+    ///
+    ///     for p in entries {
+    ///         println!("{:?}", p);
+    ///     }
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    fn file_name_ref(&self) -> &OsStr;
+}
+
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for fs::DirEntry {}
+
+#[unstable(feature = "dir_entry_ext2", issue = "85573")]
+impl DirEntryExt2 for fs::DirEntry {
+    fn file_name_ref(&self) -> &OsStr {
+        self.as_inner().file_name_os_str()
+    }
+}
+
 /// Creates a new symbolic link on the filesystem.
 ///
 /// The `link` path will be a symbolic link pointing to the `original` path.
index 67756b15531bf360b9d5bc8995e240f713a29cb6..9e7ccd015b65815336ce3cac06c3b2ed2f9cf76a 100644 (file)
@@ -2,6 +2,7 @@
 
 #![stable(feature = "process_extensions", since = "1.2.0")]
 
+use crate::ffi::OsStr;
 use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
 use crate::process;
 use crate::sealed::Sealed;
@@ -125,6 +126,13 @@ pub trait CommandExt: Sealed {
     /// [2]: <https://msdn.microsoft.com/en-us/library/17w5ykft.aspx>
     #[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")]
     fn force_quotes(&mut self, enabled: bool) -> &mut process::Command;
+
+    /// Append literal text to the command line without any quoting or escaping.
+    ///
+    /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
+    /// `CommandLineToArgvW` escaping rules.
+    #[unstable(feature = "windows_process_extensions_raw_arg", issue = "29494")]
+    fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;
 }
 
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
@@ -138,4 +146,9 @@ fn force_quotes(&mut self, enabled: bool) -> &mut process::Command {
         self.as_inner_mut().force_quotes(enabled);
         self
     }
+
+    fn raw_arg<S: AsRef<OsStr>>(&mut self, raw_text: S) -> &mut process::Command {
+        self.as_inner_mut().raw_arg(raw_text.as_ref());
+        self
+    }
 }
index ee069eefd4541e8f0fc78c81ce84efe05d0534fe..7bc987db8814bd620d26d98e11bc6e810f910fc2 100644 (file)
@@ -133,7 +133,7 @@ pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
 /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be
 /// implemented for any closed over variables passed to `catch_unwind`.
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-#[cfg_attr(not(test), lang = "unwind_safe")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")]
 #[rustc_on_unimplemented(
     message = "the type `{Self}` may not be safely transferred across an unwind boundary",
     label = "`{Self}` may not be safely transferred across an unwind boundary"
@@ -149,7 +149,7 @@ pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
 /// This is a "helper marker trait" used to provide impl blocks for the
 /// [`UnwindSafe`] trait, for more information see that documentation.
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-#[cfg_attr(not(test), lang = "ref_unwind_safe")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")]
 #[rustc_on_unimplemented(
     message = "the type `{Self}` may contain interior mutability and a reference may not be safely \
                transferrable across a catch_unwind boundary",
index b46d3dfc1e7c6ebd0a64ad95def6aa3905c94154..11a0432ce27a1ebb91e8f90724cfe87fd694a783 100644 (file)
@@ -1898,6 +1898,9 @@ pub fn exit(code: i32) -> ! {
 /// process, no destructors on the current stack or any other thread's stack
 /// will be run.
 ///
+/// Rust IO buffers (eg, from `BufWriter`) will not be flushed.
+/// Likewise, C stdio buffers will (on most platforms) not be flushed.
+///
 /// This is in contrast to the default behaviour of [`panic!`] which unwinds
 /// the current thread's stack and calls all destructors.
 /// When `panic="abort"` is set, either as an argument to `rustc` or in a
@@ -1908,6 +1911,10 @@ pub fn exit(code: i32) -> ! {
 /// this function at a known point where there are no more destructors left
 /// to run.
 ///
+/// The process's termination will be similar to that from the C `abort()`
+/// function.  On Unix, the process will terminate with signal `SIGABRT`, which
+/// typically means that the shell prints "Aborted".
+///
 /// # Examples
 ///
 /// ```no_run
index cf6aa31b7cfe331486a78d80942ec31ed5b88f4c..6a46525f682c4a69860c8f1232112519e291e708 100644 (file)
@@ -21,7 +21,7 @@
 use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
 use libc::{ftruncate, pread, pwrite};
 
-use super::{cvt, cvt_r};
+use super::{cvt, cvt_r, weak::weak};
 use crate::io;
 
 // The `log2` and `log2f` functions apparently appeared in android-18, or at
index a428ce94c8e8632ea00bbceab87abba334f471ee..5c8c94971c33c0de8d4ad71d9f30910528eac37c 100644 (file)
 use crate::sys::{cvt, cvt_r};
 use crate::sys_common::{AsInner, FromInner};
 
+#[cfg(any(
+    all(target_os = "linux", target_env = "gnu"),
+    target_os = "macos",
+    target_os = "ios",
+))]
+use crate::sys::weak::syscall;
+#[cfg(target_os = "macos")]
+use crate::sys::weak::weak;
+
 use libc::{c_int, mode_t};
 
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    all(target_os = "linux", target_env = "gnu")
+))]
+use libc::c_char;
 #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
 use libc::dirfd;
 #[cfg(any(target_os = "linux", target_os = "emscripten"))]
@@ -92,7 +107,7 @@ struct StatxExtraFields {
     // Default `stat64` contains no creation time.
     unsafe fn try_statx(
         fd: c_int,
-        path: *const libc::c_char,
+        path: *const c_char,
         flags: i32,
         mask: u32,
     ) -> Option<io::Result<FileAttr>> {
@@ -107,7 +122,7 @@ unsafe fn try_statx(
         syscall! {
             fn statx(
                 fd: c_int,
-                pathname: *const libc::c_char,
+                pathname: *const c_char,
                 flags: c_int,
                 mask: libc::c_uint,
                 statxbuf: *mut libc::statx
@@ -647,6 +662,10 @@ fn name_bytes(&self) -> &[u8] {
     fn name_bytes(&self) -> &[u8] {
         &*self.name
     }
+
+    pub fn file_name_os_str(&self) -> &OsStr {
+        OsStr::from_bytes(self.name_bytes())
+    }
 }
 
 impl OpenOptions {
@@ -752,7 +771,7 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
         cfg_has_statx! {
             if let Some(ret) = unsafe { try_statx(
                 fd,
-                b"\0" as *const _ as *const libc::c_char,
+                b"\0" as *const _ as *const c_char,
                 libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
                 libc::STATX_ALL,
             ) } {
@@ -1083,15 +1102,28 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
     let link = cstr(link)?;
     cfg_if::cfg_if! {
         if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
-            // VxWorks, Redox, and old versions of Android lack `linkat`, so use
-            // `link` instead. POSIX leaves it implementation-defined whether
-            // `link` follows symlinks, so rely on the `symlink_hard_link` test
-            // in library/std/src/fs/tests.rs to check the behavior.
+            // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX leaves
+            // it implementation-defined whether `link` follows symlinks, so rely on the
+            // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
+            // Android has `linkat` on newer versions, but we happen to know `link`
+            // always has the correct behavior, so it's here as well.
             cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+        } else if #[cfg(target_os = "macos")] {
+            // On MacOS, older versions (<=10.9) lack support for linkat while newer
+            // versions have it. We want to use linkat if it is available, so we use weak!
+            // to check. `linkat` is preferable to `link` ecause it gives us a flag to
+            // specify how symlinks should be handled. We pass 0 as the flags argument,
+            // meaning it shouldn't follow symlinks.
+            weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
+
+            if let Some(f) = linkat.get() {
+                cvt(unsafe { f(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
+            } else {
+                cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+            };
         } else {
-            // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives
-            // us a flag to specify how symlinks should be handled. Pass 0 as
-            // the flags argument, meaning don't follow symlinks.
+            // Where we can, use `linkat` instead of `link`; see the comment above
+            // this one for details on why.
             cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
         }
     }
@@ -1274,7 +1306,7 @@ fn drop(&mut self) {
         fn fclonefileat(
             srcfd: libc::c_int,
             dst_dirfd: libc::c_int,
-            dst: *const libc::c_char,
+            dst: *const c_char,
             flags: libc::c_int
         ) -> libc::c_int
     }
index 9687576bb6aeb258f0a73ddd8b53511dda5097bf..a6b43229ba6b7dd4b0aa7e3b40fb985a3c1f4901 100644 (file)
@@ -61,6 +61,7 @@
 use crate::ptr;
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
+use crate::sys::weak::syscall;
 use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
 
 #[cfg(test)]
index f3535b27128b3a599c2300a0cc01f46a980bc7d8..2da71b2a448ac1d8aea5a6f2be657faeaebf2723 100644 (file)
@@ -217,13 +217,41 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
     if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
 }
 
-// On Unix-like platforms, libc::abort will unregister signal handlers
-// including the SIGABRT handler, preventing the abort from being blocked, and
-// fclose streams, with the side effect of flushing them so libc buffered
-// output will be printed.  Additionally the shell will generally print a more
-// understandable error message like "Abort trap" rather than "Illegal
-// instruction" that intrinsics::abort would cause, as intrinsics::abort is
-// implemented as an illegal instruction.
+// libc::abort() will run the SIGABRT handler.  That's fine because anyone who
+// installs a SIGABRT handler already has to expect it to run in Very Bad
+// situations (eg, malloc crashing).
+//
+// Current glibc's abort() function unblocks SIGABRT, raises SIGABRT, clears the
+// SIGABRT handler and raises it again, and then starts to get creative.
+//
+// See the public documentation for `intrinsics::abort()` and `process::abort()`
+// for further discussion.
+//
+// There is confusion about whether libc::abort() flushes stdio streams.
+// libc::abort() is required by ISO C 99 (7.14.1.1p5) to be async-signal-safe,
+// so flushing streams is at least extremely hard, if not entirely impossible.
+//
+// However, some versions of POSIX (eg IEEE Std 1003.1-2001) required abort to
+// do so.  In 1003.1-2004 this was fixed.
+//
+// glibc's implementation did the flush, unsafely, before glibc commit
+// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian
+// Weimer.  According to glibc's NEWS:
+//
+//    The abort function terminates the process immediately, without flushing
+//    stdio streams.  Previous glibc versions used to flush streams, resulting
+//    in deadlocks and further data corruption.  This change also affects
+//    process aborts as the result of assertion failures.
+//
+// This is an accurate description of the problem.  The only solution for
+// program with nontrivial use of C stdio is a fixed libc - one which does not
+// try to flush in abort - since even libc-internal errors, and assertion
+// failures generated from C, will go via abort().
+//
+// On systems with old, buggy, libcs, the impact can be severe for a
+// multithreaded C program.  It is much less severe for Rust, because Rust
+// stdlib doesn't use libc stdio buffering.  In a typical Rust program, which
+// does not use C stdio, even a buggy libc::abort() is, in fact, safe.
 pub fn abort_internal() -> ! {
     unsafe { libc::abort() }
 }
index 71fec79347a87c9103f02733fc71b0e890106917..d3c874edf2dc472c9cb9edae7e0a716cec95a3e4 100644 (file)
@@ -23,6 +23,9 @@
 use crate::sys_common::rwlock::{StaticRWLock, StaticRWLockReadGuard};
 use crate::vec;
 
+#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+use crate::sys::weak::weak;
+
 use libc::{c_char, c_int, c_void};
 
 const TMPBUF_SZ: usize = 128;
index ed55e1aa715ae5ac5cea3b99fdce5b0d3614f4ee..c888dd0d87d8e296b76601ec6aa043ea2ef73520 100644 (file)
@@ -9,6 +9,14 @@
 use crate::sys::cvt;
 use crate::sys::process::process_common::*;
 
+#[cfg(any(
+    target_os = "macos",
+    target_os = "freebsd",
+    all(target_os = "linux", target_env = "gnu"),
+    all(target_os = "linux", target_env = "musl"),
+))]
+use crate::sys::weak::weak;
+
 #[cfg(target_os = "vxworks")]
 use libc::RTP_ID as pid_t;
 
index 44f9eabc319a0c968621c37d255fdbdb096a3a50..32895001a65bae83dd119e5735dced1dd55c084e 100644 (file)
@@ -25,6 +25,9 @@ mod imp {
     use crate::fs::File;
     use crate::io::Read;
 
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    use crate::sys::weak::syscall;
+
     #[cfg(any(target_os = "linux", target_os = "android"))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         // A weak symbol allows interposition, e.g. for perf measurements that want to
@@ -108,6 +111,7 @@ mod imp {
     use crate::fs::File;
     use crate::io::Read;
     use crate::sys::os::errno;
+    use crate::sys::weak::weak;
     use libc::{c_int, c_void, size_t};
 
     fn getentropy_fill_bytes(v: &mut [u8]) -> bool {
index df2ba0a8bc8e6289af4ce55d83f3a17c58f4d419..879d716052497f626ce5cb41c946251300ab70fa 100644 (file)
@@ -7,6 +7,8 @@
 use crate::sys::{os, stack_overflow};
 use crate::time::Duration;
 
+#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))]
+use crate::sys::weak::weak;
 #[cfg(not(any(target_os = "l4re", target_os = "vxworks")))]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
 #[cfg(target_os = "l4re")]
index 432fe4c33bcc461b40ce2a54a3a2f927fbc5479b..cad8be6d289ee166dc111013d85521d38b42de20 100644 (file)
 use crate::mem;
 use crate::sync::atomic::{self, AtomicUsize, Ordering};
 
-macro_rules! weak {
+// Temporary null documentation to work around #57569 until the fix is beta
+#[cfg_attr(bootstrap, doc = "")]
+pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+        #[allow(non_upper_case_globals)]
         static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
             crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
     )
@@ -100,8 +103,10 @@ unsafe fn fetch(name: &str) -> usize {
     libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
 }
 
+// Temporary null documentation to work around #57569 until the fix is beta
+#[cfg_attr(bootstrap, doc = "")]
 #[cfg(not(any(target_os = "linux", target_os = "android")))]
-macro_rules! syscall {
+pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name: $t),*) -> $ret {
             use super::os;
@@ -118,10 +123,12 @@ unsafe fn $name($($arg_name: $t),*) -> $ret {
     )
 }
 
+#[cfg_attr(bootstrap, doc = "")]
 #[cfg(any(target_os = "linux", target_os = "android"))]
-macro_rules! syscall {
+pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name:$t),*) -> $ret {
+            use weak;
             // This looks like a hack, but concat_idents only accepts idents
             // (not paths).
             use libc::*;
index b082e21ab3bcc893e8f9ad0d9747e338d33a6439..0fdf72c8067d25abf66ddc39df771fb5bcf9f37d 100644 (file)
@@ -137,7 +137,7 @@ fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> {
 
 pub struct Command {
     program: OsString,
-    args: Vec<OsString>,
+    args: Vec<Arg>,
     env: CommandEnv,
     cwd: Option<OsString>,
     flags: u32,
@@ -161,6 +161,14 @@ pub struct StdioPipes {
     pub stderr: Option<AnonPipe>,
 }
 
+#[derive(Debug)]
+enum Arg {
+    /// Add quotes (if needed)
+    Regular(OsString),
+    /// Append raw string without quoting
+    Raw(OsString),
+}
+
 impl Command {
     pub fn new(program: &OsStr) -> Command {
         Command {
@@ -178,7 +186,7 @@ pub fn new(program: &OsStr) -> Command {
     }
 
     pub fn arg(&mut self, arg: &OsStr) {
-        self.args.push(arg.to_os_string())
+        self.args.push(Arg::Regular(arg.to_os_string()))
     }
     pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
@@ -203,6 +211,10 @@ pub fn force_quotes(&mut self, enabled: bool) {
         self.force_quotes_enabled = enabled;
     }
 
+    pub fn raw_arg(&mut self, command_str_to_append: &OsStr) {
+        self.args.push(Arg::Raw(command_str_to_append.to_os_string()))
+    }
+
     pub fn get_program(&self) -> &OsStr {
         &self.program
     }
@@ -315,9 +327,13 @@ pub fn spawn(
 
 impl fmt::Debug for Command {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self.program)?;
+        self.program.fmt(f)?;
         for arg in &self.args {
-            write!(f, " {:?}", arg)?;
+            f.write_str(" ")?;
+            match arg {
+                Arg::Regular(s) => s.fmt(f),
+                Arg::Raw(s) => f.write_str(&s.to_string_lossy()),
+            }?;
         }
         Ok(())
     }
@@ -536,44 +552,63 @@ fn zeroed_process_information() -> c::PROCESS_INFORMATION {
     }
 }
 
+enum Quote {
+    // Every arg is quoted
+    Always,
+    // Whitespace and empty args are quoted
+    Auto,
+    // Arg appended without any changes (#29494)
+    Never,
+}
+
 // Produces a wide string *without terminating null*; returns an error if
 // `prog` or any of the `args` contain a nul.
-fn make_command_line(prog: &OsStr, args: &[OsString], force_quotes: bool) -> io::Result<Vec<u16>> {
+fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Result<Vec<u16>> {
     // Encode the command and arguments in a command line string such
     // that the spawned process may recover them using CommandLineToArgvW.
     let mut cmd: Vec<u16> = Vec::new();
     // Always quote the program name so CreateProcess doesn't interpret args as
     // part of the name if the binary wasn't found first time.
-    append_arg(&mut cmd, prog, true)?;
+    append_arg(&mut cmd, prog, Quote::Always)?;
     for arg in args {
         cmd.push(' ' as u16);
-        append_arg(&mut cmd, arg, force_quotes)?;
+        let (arg, quote) = match arg {
+            Arg::Regular(arg) => (arg, if force_quotes { Quote::Always } else { Quote::Auto }),
+            Arg::Raw(arg) => (arg, Quote::Never),
+        };
+        append_arg(&mut cmd, arg, quote)?;
     }
     return Ok(cmd);
 
-    fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, force_quotes: bool) -> io::Result<()> {
+    fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {
         // If an argument has 0 characters then we need to quote it to ensure
         // that it actually gets passed through on the command line or otherwise
         // it will be dropped entirely when parsed on the other end.
         ensure_no_nuls(arg)?;
         let arg_bytes = &arg.as_inner().inner.as_inner();
-        let quote = force_quotes
-            || arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t')
-            || arg_bytes.is_empty();
+        let (quote, escape) = match quote {
+            Quote::Always => (true, true),
+            Quote::Auto => {
+                (arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') || arg_bytes.is_empty(), true)
+            }
+            Quote::Never => (false, false),
+        };
         if quote {
             cmd.push('"' as u16);
         }
 
         let mut backslashes: usize = 0;
         for x in arg.encode_wide() {
-            if x == '\\' as u16 {
-                backslashes += 1;
-            } else {
-                if x == '"' as u16 {
-                    // Add n+1 backslashes to total 2n+1 before internal '"'.
-                    cmd.extend((0..=backslashes).map(|_| '\\' as u16));
+            if escape {
+                if x == '\\' as u16 {
+                    backslashes += 1;
+                } else {
+                    if x == '"' as u16 {
+                        // Add n+1 backslashes to total 2n+1 before internal '"'.
+                        cmd.extend((0..=backslashes).map(|_| '\\' as u16));
+                    }
+                    backslashes = 0;
                 }
-                backslashes = 0;
             }
             cmd.push(x);
         }
@@ -626,13 +661,15 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec<u16>)> {
 }
 
 pub struct CommandArgs<'a> {
-    iter: crate::slice::Iter<'a, OsString>,
+    iter: crate::slice::Iter<'a, Arg>,
 }
 
 impl<'a> Iterator for CommandArgs<'a> {
     type Item = &'a OsStr;
     fn next(&mut self) -> Option<&'a OsStr> {
-        self.iter.next().map(|s| s.as_ref())
+        self.iter.next().map(|arg| match arg {
+            Arg::Regular(s) | Arg::Raw(s) => s.as_ref(),
+        })
     }
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
index ff3f9131cc889b3303b9bc6e5dbd552ac433084b..3b65856dcaca6d4f3e017a2ba97fccf2cf8f339c 100644 (file)
@@ -1,14 +1,35 @@
 use super::make_command_line;
+use super::Arg;
 use crate::env;
 use crate::ffi::{OsStr, OsString};
 use crate::process::Command;
 
+#[test]
+fn test_raw_args() {
+    let command_line = &make_command_line(
+        OsStr::new("quoted exe"),
+        &[
+            Arg::Regular(OsString::from("quote me")),
+            Arg::Raw(OsString::from("quote me *not*")),
+            Arg::Raw(OsString::from("\t\\")),
+            Arg::Raw(OsString::from("internal \\\"backslash-\"quote")),
+            Arg::Regular(OsString::from("optional-quotes")),
+        ],
+        false,
+    )
+    .unwrap();
+    assert_eq!(
+        String::from_utf16(command_line).unwrap(),
+        "\"quoted exe\" \"quote me\" quote me *not* \t\\ internal \\\"backslash-\"quote optional-quotes"
+    );
+}
+
 #[test]
 fn test_make_command_line() {
     fn test_wrapper(prog: &str, args: &[&str], force_quotes: bool) -> String {
         let command_line = &make_command_line(
             OsStr::new(prog),
-            &args.iter().map(|a| OsString::from(a)).collect::<Vec<OsString>>(),
+            &args.iter().map(|a| Arg::Regular(OsString::from(a))).collect::<Vec<_>>(),
             force_quotes,
         )
         .unwrap();
@@ -17,6 +38,11 @@ fn test_wrapper(prog: &str, args: &[&str], force_quotes: bool) -> String {
 
     assert_eq!(test_wrapper("prog", &["aaa", "bbb", "ccc"], false), "\"prog\" aaa bbb ccc");
 
+    assert_eq!(test_wrapper("prog", &[r"C:\"], false), r#""prog" C:\"#);
+    assert_eq!(test_wrapper("prog", &[r"2slashes\\"], false), r#""prog" 2slashes\\"#);
+    assert_eq!(test_wrapper("prog", &[r" C:\"], false), r#""prog" " C:\\""#);
+    assert_eq!(test_wrapper("prog", &[r" 2slashes\\"], false), r#""prog" " 2slashes\\\\""#);
+
     assert_eq!(
         test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"], false),
         "\"C:\\Program Files\\blah\\blah.exe\" aaa"
index f7e791419038d197d42e66054f2100eaec38da07..9f7e6b95dfb90c0d496eb88ead3679226ed02379 100644 (file)
@@ -651,22 +651,23 @@ pub fn current() -> Thread {
 
 /// Cooperatively gives up a timeslice to the OS scheduler.
 ///
-/// This is used when the programmer knows that the thread will have nothing
-/// to do for some time, and thus avoid wasting computing time.
+/// This calls the underlying OS scheduler's yield primitive, signaling
+/// that the calling thread is willing to give up its remaining timeslice
+/// so that the OS may schedule other threads on the CPU.
 ///
-/// For example when polling on a resource, it is common to check that it is
-/// available, and if not to yield in order to avoid busy waiting.
+/// A drawback of yielding in a loop is that if the OS does not have any
+/// other ready threads to run on the current CPU, the thread will effectively
+/// busy-wait, which wastes CPU time and energy.
 ///
-/// Thus the pattern of `yield`ing after a failed poll is rather common when
-/// implementing low-level shared resources or synchronization primitives.
+/// Therefore, when waiting for events of interest, a programmer's first
+/// choice should be to use synchronization devices such as [`channel`]s,
+/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are
+/// implemented in a blocking manner, giving up the CPU until the event
+/// of interest has occurred which avoids repeated yielding.
 ///
-/// However programmers will usually prefer to use [`channel`]s, [`Condvar`]s,
-/// [`Mutex`]es or [`join`] for their synchronization routines, as they avoid
-/// thinking about thread scheduling.
-///
-/// Note that [`channel`]s for example are implemented using this primitive.
-/// Indeed when you call `send` or `recv`, which are blocking, they will yield
-/// if the channel is not available.
+/// `yield_now` should thus be used only rarely, mostly in situations where
+/// repeated polling is required because there is no other suitable way to
+/// learn when an event of interest has occurred.
 ///
 /// # Examples
 ///
@@ -998,11 +999,12 @@ fn new() -> ThreadId {
         static mut COUNTER: u64 = 1;
 
         unsafe {
-            let _guard = GUARD.lock();
+            let guard = GUARD.lock();
 
             // If we somehow use up all our bits, panic so that we're not
             // covering up subtle bugs of IDs being reused.
             if COUNTER == u64::MAX {
+                drop(guard); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire.
                 panic!("failed to generate unique thread ID: bitspace exhausted");
             }
 
index 7ec3c2d738a6713c031ea2c51f8c1b7dd3f44995..d3f2c87c0d22f4c966c2215889c60d4b9392be1d 100644 (file)
@@ -600,7 +600,7 @@ fn run(self, builder: &Builder<'_>) {
 }
 
 macro_rules! tool_doc {
-    ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(, binary=$bin:expr)?) => {
+    ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], binary=$bin:expr) => {
         #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
         pub struct $tool {
             stage: u32,
@@ -669,9 +669,9 @@ fn run(self, builder: &Builder<'_>) {
                     cargo.arg("-p").arg($krate);
                 )+
 
-                $(if !$bin {
+                if !$bin {
                     cargo.rustdocflag("--document-private-items");
-                })?
+                }
                 cargo.rustdocflag("--enable-index-page");
                 cargo.rustdocflag("--show-type-layout");
                 cargo.rustdocflag("-Zunstable-options");
@@ -681,7 +681,13 @@ fn run(self, builder: &Builder<'_>) {
     }
 }
 
-tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]);
+tool_doc!(
+    Rustdoc,
+    "rustdoc-tool",
+    "src/tools/rustdoc",
+    ["rustdoc", "rustdoc-json-types"],
+    binary = false
+);
 tool_doc!(
     Rustfmt,
     "rustfmt-nightly",
index b967b6dbd2daebc0acc2bf7cb110d048973821be..0be42d9b2348623abf72d4c256df3a4966d8a4fb 100644 (file)
@@ -99,6 +99,10 @@ fn dir_is_empty(dir: &Path) -> bool {
         t!(std::fs::read_dir(dir)).next().is_none()
     }
 
+    if !build.config.submodules {
+        return;
+    }
+
     // NOTE: The check for the empty directory is here because when running x.py
     // the first time, the llvm submodule won't be checked out. Check it out
     // now so we can build it.
index 64b3ee7c359e7144905ec7aed25ee59de2536049..e4d6a3f587b0526eec7eb0b5cf824e0a6bf6b6e0 100644 (file)
@@ -742,7 +742,7 @@ fn run(self, builder: &Builder<'_>) {
         let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
         let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
         cmd.arg(rustdoc.to_str().unwrap())
-            .arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap())
+            .arg(builder.src.join("src/librustdoc/html/static/css/themes").to_str().unwrap())
             .env("RUSTC_STAGE", self.compiler.stage.to_string())
             .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
             .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
index 78ac060368193964fb3fb8420e63894810802863..267c3964d0d692d2e8e975fa5868943a547c00fc 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # ignore-tidy-linelength
 
 # This is a small script that we use on CI to collect CPU usage statistics of
@@ -37,7 +37,10 @@ import datetime
 import sys
 import time
 
-if sys.platform == 'linux2':
+# Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just
+# "linux". We check here with `.startswith` to keep compatibility with older
+# Python versions (especially Python 2.7).
+if sys.platform.startswith('linux'):
     class State:
         def __init__(self):
             with open('/proc/stat', 'r') as file:
index 8066ea3a944b39543b393ac48698178cfc75b6f8..c27e42a266220a819684ddeed73be8598a3b1c74 100644 (file)
@@ -40,5 +40,5 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            /scripts/validate-toolstate.sh && \
            /scripts/validate-error-codes.sh && \
            # Runs checks to ensure that there are no ES5 issues in our JS code.
-           es-check es5 ../src/librustdoc/html/static/*.js && \
-           eslint ../src/librustdoc/html/static/*.js
+           es-check es5 ../src/librustdoc/html/static/js/*.js && \
+           eslint ../src/librustdoc/html/static/js/*.js
index 08065431f981650e7b000281c288220e80f9d4c6..853b4628fab2f3d1c487afcc46db4018ec9ae988 100755 (executable)
@@ -6,4 +6,4 @@
 set -euo pipefail
 IFS=$'\n\t'
 
-python src/ci/cpu-usage-over-time.py &> cpu-usage.csv &
+python3 src/ci/cpu-usage-over-time.py &> cpu-usage.csv &
index 55a26488ddefc8433e73a2e8352d70f7a5c7fc2b..a90f07f1e9a7fc75dc9105a6c6f16d5c13edceb0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 55a26488ddefc8433e73a2e8352d70f7a5c7fc2b
+Subproject commit a90f07f1e9a7fc75dc9105a6c6f16d5c13edceb0
index c74b2a0d6bf55774cf15d69f05dfe05408b8f81a..5d57b3832f8d308a9f478ce0a69799548f27ad4d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c74b2a0d6bf55774cf15d69f05dfe05408b8f81a
+Subproject commit 5d57b3832f8d308a9f478ce0a69799548f27ad4d
index cbec77fbd8eea0c13e390dd9eded1ae200e811d1..506840eb73b0749336e1d5274e16d6393892ee82 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cbec77fbd8eea0c13e390dd9eded1ae200e811d1
+Subproject commit 506840eb73b0749336e1d5274e16d6393892ee82
index b9ca313e687c991223e23e5520529815dc281205..7a13537f96af4b9b8e3ea296d6e5c3c7ab72ce9f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b9ca313e687c991223e23e5520529815dc281205
+Subproject commit 7a13537f96af4b9b8e3ea296d6e5c3c7ab72ce9f
index d9699fa8f3186440fdaadd703d63d8d42322c176..ab60513a3a5a0591e237fddff5d027a982648392 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d9699fa8f3186440fdaadd703d63d8d42322c176
+Subproject commit ab60513a3a5a0591e237fddff5d027a982648392
index fdeea17ed1124bde8b8453bd4c6b0a6035079074..5e09cdc5cf5cd1e7c4efbf283aeedaf3bcd3f108 100644 (file)
@@ -1,4 +1,4 @@
 % The Rust Reference has moved
 
 We've split up the reference into chapters. Please find it at its new
-home [here](reference/index.html).
+home [here](https://doc.rust-lang.org/stable/reference/introduction.html).
index 805e016c5792ad2adabb66e348233067d5ea9f10..028f93a61500fe8f746ee7cc6b204ea6c9f42935 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 805e016c5792ad2adabb66e348233067d5ea9f10
+Subproject commit 028f93a61500fe8f746ee7cc6b204ea6c9f42935
index fe34beddb41dea5cb891032512a8d5b842b99696..60e282559104035985331645907c3d9f842312c5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fe34beddb41dea5cb891032512a8d5b842b99696
+Subproject commit 60e282559104035985331645907c3d9f842312c5
diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
new file mode 100644 (file)
index 0000000..d265127
--- /dev/null
@@ -0,0 +1,26 @@
+# `exclusive_range_pattern`
+
+The tracking issue for this feature is: [#37854].
+
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+The `exclusive_range_pattern` feature allows non-inclusive range
+patterns (`0..10`) to be used in appropriate pattern matching
+contexts. It also can be combined with `#![feature(half_open_range_patterns]`
+to be able to use RangeTo patterns (`..10`).
+
+It also enabled RangeFrom patterns but that has since been
+stabilized.
+
+```rust
+#![feature(exclusive_range_pattern)]
+    let x = 5;
+    match x {
+        0..10 => println!("single digit"),
+        10 => println!("ten isn't part of the above range"),
+        _ => println!("nor is everything else.")
+    }
+```
diff --git a/src/doc/unstable-book/src/language-features/half-open-range-patterns.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md
new file mode 100644 (file)
index 0000000..3b16dd0
--- /dev/null
@@ -0,0 +1,27 @@
+# `half_open_range_patterns`
+
+The tracking issue for this feature is: [#67264]
+It is part of the `#![exclusive_range_pattern]` feature,
+tracked at [#37854].
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+The `half_open_range_patterns` feature allows RangeTo patterns
+(`..10`) to be used in appropriate pattern matching contexts.
+This requires also enabling the `exclusive_range_pattern` feature.
+
+It also enabled RangeFrom patterns but that has since been
+stabilized.
+
+```rust
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+    let x = 5;
+    match x {
+        ..0 => println!("negative!"), // "RangeTo" pattern. Unstable.
+        0 => println!("zero!"),
+        1.. => println!("positive!"), // "RangeFrom" pattern. Stable.
+    }
+```
index 2cf6801ad1c043cae4fe4e669af1a20b4ca758e5..e950891ef92bd504e4b7ed496d3a90a717e9e7bb 100644 (file)
@@ -545,9 +545,12 @@ Here is the list of currently supported register classes:
 | x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` |
 | x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` |
 | x86 | `kreg` | `k[1-7]` | `Yk` |
+| x86 | `x87_reg` | `st([0-7])` | Only clobbers |
+| x86 | `mmx_reg` | `mm[0-7]` | Only clobbers |
 | AArch64 | `reg` | `x[0-30]` | `r` |
 | AArch64 | `vreg` | `v[0-31]` | `w` |
 | AArch64 | `vreg_low16` | `v[0-15]` | `x` |
+| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers |
 | ARM | `reg` | `r[0-12]`, `r14` | `r` |
 | ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` |
 | ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` |
@@ -566,6 +569,7 @@ Here is the list of currently supported register classes:
 | NVPTX | `reg64` | None\* | `l` |
 | RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
 | RISC-V | `freg` | `f[0-31]` | `f` |
+| RISC-V | `vreg` | `v[0-31]` | Only clobbers |
 | Hexagon | `reg` | `r[0-28]` | `r` |
 | PowerPC | `reg` | `r[0-31]` | `r` |
 | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
@@ -581,6 +585,8 @@ Here is the list of currently supported register classes:
 > Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported.
 >
 > Note #4: WebAssembly doesn't have registers, so named registers are not supported.
+>
+> Note #5: Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`.
 
 Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).
 
@@ -596,8 +602,11 @@ Each register class has constraints on which value types they can be used with.
 | x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` <br> `i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` |
 | x86 | `kreg` | `axv512f` | `i8`, `i16` |
 | x86 | `kreg` | `axv512bw` | `i32`, `i64` |
+| x86 | `mmx_reg` | N/A | Only clobbers |
+| x86 | `x87_reg` | N/A | Only clobbers |
 | AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
 | AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
+| AArch64 | `preg` | N/A | Only clobbers |
 | ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` |
 | ARM | `sreg` | `vfp2` | `i32`, `f32` |
 | ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
@@ -613,6 +622,7 @@ Each register class has constraints on which value types they can be used with.
 | RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
 | RISC-V | `freg` | `f` | `f32` |
 | RISC-V | `freg` | `d` | `f64` |
+| RISC-V | `vreg` | N/A | Only clobbers |
 | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
 | PowerPC | `reg` | None | `i8`, `i16`, `i32` |
 | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
index a5a1824c84e78be919f81ea5f4119d70686b7121..292e91b4d5d6177817a4f830abd8441410d11a84 100644 (file)
@@ -5,7 +5,6 @@ from gdb_providers import *
 from rust_types import *
 
 
-rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True)
 _gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
 gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
 
@@ -52,9 +51,10 @@ def lookup(valobj):
         return StdStringProvider(valobj)
     if rust_type == RustType.STD_OS_STRING:
         return StdOsStringProvider(valobj)
-    if rust_type == RustType.STD_STR and not rust_enabled:
+    if rust_type == RustType.STD_STR:
         return StdStrProvider(valobj)
-
+    if rust_type == RustType.STD_SLICE:
+        return StdSliceProvider(valobj)
     if rust_type == RustType.STD_VEC:
         return StdVecProvider(valobj)
     if rust_type == RustType.STD_VEC_DEQUE:
index f0ce13b269c59ae2163971a523ae04ba9088b355..33d26db547efc8c2ceed8353904b81652a09bcec 100644 (file)
@@ -85,6 +85,39 @@ class StdStrProvider:
     def display_hint():
         return "string"
 
+def _enumerate_array_elements(element_ptrs):
+    for (i, element_ptr) in enumerate(element_ptrs):
+        key = "[{}]".format(i)
+        element = element_ptr.dereference()
+
+        try:
+            # rust-lang/rust#64343: passing deref expr to `str` allows
+            # catching exception on garbage pointer
+            str(element)
+        except RuntimeError:
+            yield key, "inaccessible"
+
+            break
+
+        yield key, element
+
+class StdSliceProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+        self.length = int(valobj["length"])
+        self.data_ptr = valobj["data_ptr"]
+
+    def to_string(self):
+        return "{}(size={})".format(self.valobj.type, self.length)
+
+    def children(self):
+        return _enumerate_array_elements(
+            self.data_ptr + index for index in xrange(self.length)
+        )
+
+    @staticmethod
+    def display_hint():
+        return "array"
 
 class StdVecProvider:
     def __init__(self, valobj):
@@ -96,19 +129,9 @@ class StdVecProvider:
         return "Vec(size={})".format(self.length)
 
     def children(self):
-        saw_inaccessible = False
-        for index in xrange(self.length):
-            element_ptr = self.data_ptr + index
-            if saw_inaccessible:
-                return
-            try:
-                # rust-lang/rust#64343: passing deref expr to `str` allows
-                # catching exception on garbage pointer
-                str(element_ptr.dereference())
-                yield "[{}]".format(index), element_ptr.dereference()
-            except RuntimeError:
-                saw_inaccessible = True
-                yield str(index), "inaccessible"
+        return _enumerate_array_elements(
+            self.data_ptr + index for index in xrange(self.length)
+        )
 
     @staticmethod
     def display_hint():
@@ -131,9 +154,9 @@ class StdVecDequeProvider:
         return "VecDeque(size={})".format(self.size)
 
     def children(self):
-        for index in xrange(0, self.size):
-            value = (self.data_ptr + ((self.tail + index) % self.cap)).dereference()
-            yield "[{}]".format(index), value
+        return _enumerate_array_elements(
+            (self.data_ptr + ((self.tail + index) % self.cap)) for index in xrange(self.size)
+        )
 
     @staticmethod
     def display_hint():
index b8e6c6c0c89f12361c3fab043b182e4844f4ac16..4a1204ccc4be737d0fb009d3e053c7c731f29cf3 100644 (file)
@@ -1,7 +1,7 @@
 type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
-type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&str$" --category Rust
-type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&\\[.+\\]$" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?str$" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
index cf887ffb0c01ed77341c1e028be7557997a91e04..52e5d37c83fbdc5fa5b02147239cde29392c3a26 100644 (file)
       <Synthetic Name="[...]"><DisplayString>...</DisplayString></Synthetic>
     </Expand>
   </Type>
+
+  <!-- Directly tagged enums. $T1 is the type name -->
   <Type Name="enum$&lt;*&gt;">
-    <Intrinsic Name="tag" Expression="variant0.variant$" />
+    <Intrinsic Name="tag" Expression="discriminant" />
     <DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
     <DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
     <DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
     <DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString>
 
     <Expand>
+      <Synthetic Name="[variant]">
+        <DisplayString>{tag(),en}</DisplayString>
+      </Synthetic>
       <ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
       <ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
       <ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem>
     </Expand>
   </Type>
 
-  <!-- $T1 is the name of the enum, $T2 is the low value of the dataful variant tag,
-       $T3 is the high value of the dataful variant tag, $T4 is the name of the dataful variant -->
+  <!-- Single variant enums. $T1 is the name of the enum, $T2 is the name of the variant -->
+  <Type Name="enum$&lt;*, *&gt;">
+    <DisplayString>{"$T2",sb}</DisplayString>
+    <Expand>
+      <Synthetic Name="[variant]">
+        <DisplayString>{"$T2",sb}</DisplayString>
+      </Synthetic>
+      <ExpandedItem>$T2</ExpandedItem>
+    </Expand>
+  </Type>
+
+  <!-- Niche-layout enums. $T1 is the name of the enum, $T2 is the low value of the dataful
+       variant tag, $T3 is the high value of the dataful variant tag, $T4 is the name of
+       the dataful variant -->
   <Type Name="enum$&lt;*, *, *, *&gt;">
     <Intrinsic Name="tag" Expression="discriminant" />
     <Intrinsic Name="is_dataful" Expression="tag() &gt;= $T2 &amp;&amp; tag() &lt;= $T3" />
       <Synthetic Condition="is_dataful()" Name="[variant]">
         <DisplayString>{"$T4",sb}</DisplayString>
       </Synthetic>
+      <Synthetic Condition="!is_dataful()" Name="[variant]">
+        <DisplayString>{discriminant,en}</DisplayString>
+      </Synthetic>
     </Expand>
   </Type>
 </AutoVisualizer>
index 17667770520ce0e4442fce1f661dda04a0694403..c8196d5c713b200547c43540330c1f09da520e48 100644 (file)
     </Expand>
   </Type>
 
-  <Type Name="core::option::Option&lt;*&gt;" Priority="MediumLow">
-    <DisplayString Condition="*(void**)this == nullptr">None</DisplayString>
-    <DisplayString>Some({($T1 *)this})</DisplayString>
-    <Expand>
-      <Item Name="Some" ExcludeView="simple" Condition="*(void**)this != nullptr">($T1 *)this</Item>
-    </Expand>
-  </Type>
-
   <Type Name="core::ptr::non_null::NonNull&lt;*&gt;">
     <DisplayString>{(void*) pointer}</DisplayString>
     <Expand>
index b49fd19ed4cbbbe40ba49458037bb4c2fff5e64b..bbc945a7ddab0186a913f6e9402b0357b890836e 100644 (file)
@@ -34,8 +34,8 @@ class RustType(object):
 
 
 STD_STRING_REGEX = re.compile(r"^(alloc::(\w+::)+)String$")
-STD_STR_REGEX = re.compile(r"^&str$")
-STD_SLICE_REGEX = re.compile(r"^&\[.+\]$")
+STD_STR_REGEX = re.compile(r"^&(mut )?str$")
+STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$")
 STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(\w+::)+)OsString$")
 STD_VEC_REGEX = re.compile(r"^(alloc::(\w+::)+)Vec<.+>$")
 STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(\w+::)+)VecDeque<.+>$")
index ebab3add6c55dd96ad642ec0c81be2b01a35961c..e479d162b8ffb85419057c7e8a562f4a1f28ad62 100644 (file)
@@ -113,7 +113,7 @@ fn generate_for_trait(
             name: None,
             attrs: Default::default(),
             visibility: Inherited,
-            def_id: FakeDefId::new_fake(item_def_id.krate),
+            def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
             kind: box ImplItem(Impl {
                 span: Span::dummy(),
                 unsafety: hir::Unsafety::Normal,
index dc60b5a1d58e1624604c15079a20d7354be46b4b..8f74a48547d8833c0f88a12e6ec8ac111cda1af4 100644 (file)
@@ -96,7 +96,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     name: None,
                     attrs: Default::default(),
                     visibility: Inherited,
-                    def_id: FakeDefId::new_fake(item_def_id.krate),
+                    def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                     kind: box ImplItem(Impl {
                         span: Span::from_rustc_span(self.cx.tcx.def_span(impl_def_id)),
                         unsafety: hir::Unsafety::Normal,
index 34b9cbcb6793ab608539ae722ddd8bd7de5dcbd1..275d1b3ebd938add90368a1cee9e59077a29d5cf 100644 (file)
@@ -2,8 +2,8 @@
 
 use rustc_ast::attr;
 use rustc_ast::Path;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::with_default_session_globals;
 use rustc_span::DUMMY_SP;
 
 fn word_cfg(s: &str) -> Cfg {
@@ -52,7 +52,7 @@ macro_rules! dummy_meta_item_list {
 
 #[test]
 fn test_cfg_not() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         assert_eq!(!Cfg::False, Cfg::True);
         assert_eq!(!Cfg::True, Cfg::False);
         assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test"))));
@@ -70,7 +70,7 @@ fn test_cfg_not() {
 
 #[test]
 fn test_cfg_and() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mut x = Cfg::False;
         x &= Cfg::True;
         assert_eq!(x, Cfg::False);
@@ -154,7 +154,7 @@ fn test_cfg_and() {
 
 #[test]
 fn test_cfg_or() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mut x = Cfg::True;
         x |= Cfg::False;
         assert_eq!(x, Cfg::True);
@@ -238,7 +238,7 @@ fn test_cfg_or() {
 
 #[test]
 fn test_parse_ok() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mi = dummy_meta_item_word("all");
         assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
 
@@ -271,7 +271,7 @@ fn test_parse_ok() {
 
 #[test]
 fn test_parse_err() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
         assert!(Cfg::parse(&mi).is_err());
 
@@ -303,7 +303,7 @@ fn test_parse_err() {
 
 #[test]
 fn test_render_short_html() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         assert_eq!(word_cfg("unix").render_short_html(), "Unix");
         assert_eq!(name_value_cfg("target_os", "macos").render_short_html(), "macOS");
         assert_eq!(name_value_cfg("target_pointer_width", "16").render_short_html(), "16-bit");
@@ -358,7 +358,7 @@ fn test_render_short_html() {
 
 #[test]
 fn test_render_long_html() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         assert_eq!(
             word_cfg("unix").render_long_html(),
             "This is supported on <strong>Unix</strong> only."
@@ -442,7 +442,7 @@ fn test_render_long_html() {
 fn test_simplify_with() {
     // This is a tiny subset of things that could be simplified, but it likely covers 90% of
     // real world usecases well.
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let foo = word_cfg("foo");
         let bar = word_cfg("bar");
         let baz = word_cfg("baz");
index 1edb855a5d63ef3901d718db3d44cffbf7a476ee..b3b89e6e673a29f1a438e3ce3d6d9ebaeab5e17b 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use crate::clean::{
-    self, utils, Attributes, AttributesExt, FakeDefId, GetDefId, NestedAttributesExt, Type,
+    self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -41,6 +41,7 @@
 crate fn try_inline(
     cx: &mut DocContext<'_>,
     parent_module: DefId,
+    import_def_id: Option<DefId>,
     res: Res,
     name: Symbol,
     attrs: Option<Attrs<'_>>,
             clean::ConstantItem(build_const(cx, did))
         }
         Res::Def(DefKind::Macro(kind), did) => {
-            let mac = build_macro(cx, did, name);
+            let mac = build_macro(cx, did, name, import_def_id);
 
             let type_kind = match kind {
                 MacroKind::Bang => ItemType::Macro,
 
     let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
     cx.inlined.insert(did.into());
-    ret.push(clean::Item::from_def_id_and_attrs_and_parts(
-        did,
-        Some(name),
-        kind,
-        box attrs,
-        cx,
-        cfg,
-    ));
+    let mut item =
+        clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, box attrs, cx, cfg);
+    if let Some(import_def_id) = import_def_id {
+        // The visibility needs to reflect the one from the reexport and not from the "source" DefId.
+        item.visibility = cx.tcx.visibility(import_def_id).clean(cx);
+    }
+    ret.push(item);
     Some(ret)
 }
 
@@ -483,10 +483,11 @@ fn build_module(
             }
             if let Res::PrimTy(p) = item.res {
                 // Primitive types can't be inlined so generate an import instead.
+                let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
                     name: None,
                     attrs: box clean::Attributes::default(),
-                    def_id: FakeDefId::new_fake(did.krate),
+                    def_id: ItemId::Primitive(prim_ty, did.krate),
                     visibility: clean::Public,
                     kind: box clean::ImportItem(clean::Import::new_simple(
                         item.ident.name,
@@ -495,7 +496,7 @@ fn build_module(
                                 global: false,
                                 res: item.res,
                                 segments: vec![clean::PathSegment {
-                                    name: clean::PrimitiveType::from(p).as_sym(),
+                                    name: prim_ty.as_sym(),
                                     args: clean::GenericArgs::AngleBracketed {
                                         args: Vec::new(),
                                         bindings: Vec::new(),
@@ -508,7 +509,9 @@ fn build_module(
                     )),
                     cfg: None,
                 });
-            } else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
+            } else if let Some(i) =
+                try_inline(cx, did, None, item.res, item.ident.name, None, visited)
+            {
                 items.extend(i)
             }
         }
@@ -542,21 +545,26 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St
     }
 }
 
-fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::ItemKind {
-    let imported_from = cx.tcx.crate_name(did.krate);
-    match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
-        LoadedMacro::MacroDef(def, _) => {
-            if let ast::ItemKind::MacroDef(ref def) = def.kind {
-                let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
-                let matchers = tts.chunks(4).map(|arm| &arm[0]);
-
-                let source = format!(
-                    "macro_rules! {} {{\n{}}}",
-                    name,
-                    utils::render_macro_arms(matchers, ";")
-                );
-
-                clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
+fn build_macro(
+    cx: &mut DocContext<'_>,
+    def_id: DefId,
+    name: Symbol,
+    import_def_id: Option<DefId>,
+) -> clean::ItemKind {
+    let imported_from = cx.tcx.crate_name(def_id.krate);
+    match cx.enter_resolver(|r| r.cstore().load_macro_untracked(def_id, cx.sess())) {
+        LoadedMacro::MacroDef(item_def, _) => {
+            if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
+                clean::MacroItem(clean::Macro {
+                    source: utils::display_macro_source(
+                        cx,
+                        name,
+                        def,
+                        def_id,
+                        cx.tcx.visibility(import_def_id.unwrap_or(def_id)),
+                    ),
+                    imported_from: Some(imported_from),
+                })
             } else {
                 unreachable!()
             }
index 767b14135bdfa550e558dbeea04c8b062141e3dd..80aaae1580114752da8ebe3a610719c814ce5624 100644 (file)
@@ -1971,6 +1971,7 @@ fn clean_extern_crate(
         if let Some(items) = inline::try_inline(
             cx,
             cx.tcx.parent_module(krate.hir_id()).to_def_id(),
+            Some(krate.def_id.to_def_id()),
             res,
             name,
             Some(attrs),
@@ -2026,7 +2027,8 @@ fn clean_use_statement(
     // forcefully don't inline if this is not public or if the
     // #[doc(no_inline)] attribute is present.
     // Don't inline doc(hidden) imports so they can be stripped at a later stage.
-    let mut denied = !import.vis.node.is_pub()
+    let mut denied = !(import.vis.node.is_pub()
+        || (cx.render_options.document_private && import.vis.node.is_pub_restricted()))
         || pub_underscore
         || attrs.iter().any(|a| {
             a.has_name(sym::doc)
@@ -2062,17 +2064,19 @@ fn clean_use_statement(
         }
         if !denied {
             let mut visited = FxHashSet::default();
+            let import_def_id = import.def_id.to_def_id();
 
             if let Some(mut items) = inline::try_inline(
                 cx,
                 cx.tcx.parent_module(import.hir_id()).to_def_id(),
+                Some(import_def_id),
                 path.res,
                 name,
                 Some(attrs),
                 &mut visited,
             ) {
                 items.push(Item::from_def_id_and_parts(
-                    import.def_id.to_def_id(),
+                    import_def_id,
                     None,
                     ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
                     cx,
@@ -2131,37 +2135,15 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let (item, renamed) = self;
         let name = renamed.unwrap_or(item.ident.name);
-        let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
-        // Extract the macro's matchers. They represent the "interface" of the macro.
-        let matchers = tts.chunks(4).map(|arm| &arm[0]);
-
-        let source = if item.ast.macro_rules {
-            format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
-        } else {
-            let vis = item.vis.clean(cx);
-            let def_id = item.def_id.to_def_id();
-
-            if matchers.len() <= 1 {
-                format!(
-                    "{}macro {}{} {{\n    ...\n}}",
-                    vis.to_src_with_space(cx.tcx, def_id),
-                    name,
-                    matchers.map(render_macro_matcher).collect::<String>(),
-                )
-            } else {
-                format!(
-                    "{}macro {} {{\n{}}}",
-                    vis.to_src_with_space(cx.tcx, def_id),
-                    name,
-                    render_macro_arms(matchers, ","),
-                )
-            }
-        };
+        let def_id = item.def_id.to_def_id();
 
         Item::from_hir_id_and_parts(
             item.hir_id(),
             Some(name),
-            MacroItem(Macro { source, imported_from: None }),
+            MacroItem(Macro {
+                source: display_macro_source(cx, name, &item.ast, def_id, &item.vis),
+                imported_from: None,
+            }),
             cx,
         )
     }
index 4da2f14ce8a8d9e884b3324339669faf0cf4b625..e716e09b8b3f0280985c57e4436a9fe231595b71 100644 (file)
@@ -1,4 +1,4 @@
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
 use std::default::Default;
 use std::hash::{Hash, Hasher};
 use std::iter::FromIterator;
 use self::SelfTy::*;
 use self::Type::*;
 
-crate type FakeDefIdSet = FxHashSet<FakeDefId>;
+crate type ItemIdSet = FxHashSet<ItemId>;
 
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
-crate enum FakeDefId {
-    Real(DefId),
-    Fake(DefIndex, CrateNum),
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
+crate enum ItemId {
+    /// A "normal" item that uses a [`DefId`] for identification.
+    DefId(DefId),
+    /// Identifier that is used for auto traits.
+    Auto { trait_: DefId, for_: DefId },
+    /// Identifier that is used for blanket implementations.
+    Blanket { impl_id: DefId, for_: DefId },
+    /// Identifier for primitive types.
+    Primitive(PrimitiveType, CrateNum),
 }
 
-impl FakeDefId {
-    #[cfg(parallel_compiler)]
-    crate fn new_fake(crate: CrateNum) -> Self {
-        unimplemented!("")
-    }
-
-    #[cfg(not(parallel_compiler))]
-    crate fn new_fake(krate: CrateNum) -> Self {
-        thread_local!(static FAKE_DEF_ID_COUNTER: Cell<usize> = Cell::new(0));
-        let id = FAKE_DEF_ID_COUNTER.with(|id| {
-            let tmp = id.get();
-            id.set(tmp + 1);
-            tmp
-        });
-        Self::Fake(DefIndex::from(id), krate)
-    }
-
+impl ItemId {
     #[inline]
     crate fn is_local(self) -> bool {
         match self {
-            FakeDefId::Real(id) => id.is_local(),
-            FakeDefId::Fake(_, krate) => krate == LOCAL_CRATE,
+            ItemId::Auto { for_: id, .. }
+            | ItemId::Blanket { for_: id, .. }
+            | ItemId::DefId(id) => id.is_local(),
+            ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
         }
     }
 
     #[inline]
     #[track_caller]
-    crate fn expect_real(self) -> rustc_hir::def_id::DefId {
-        self.as_real().unwrap_or_else(|| panic!("FakeDefId::expect_real: `{:?}` isn't real", self))
+    crate fn expect_def_id(self) -> DefId {
+        self.as_def_id()
+            .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
     }
 
     #[inline]
-    crate fn as_real(self) -> Option<DefId> {
+    crate fn as_def_id(self) -> Option<DefId> {
         match self {
-            FakeDefId::Real(id) => Some(id),
-            FakeDefId::Fake(_, _) => None,
+            ItemId::DefId(id) => Some(id),
+            _ => None,
         }
     }
 
     #[inline]
     crate fn krate(self) -> CrateNum {
         match self {
-            FakeDefId::Real(id) => id.krate,
-            FakeDefId::Fake(_, krate) => krate,
+            ItemId::Auto { for_: id, .. }
+            | ItemId::Blanket { for_: id, .. }
+            | ItemId::DefId(id) => id.krate,
+            ItemId::Primitive(_, krate) => krate,
         }
     }
 
     #[inline]
     crate fn index(self) -> Option<DefIndex> {
         match self {
-            FakeDefId::Real(id) => Some(id.index),
-            FakeDefId::Fake(_, _) => None,
+            ItemId::DefId(id) => Some(id.index),
+            _ => None,
         }
     }
 }
 
-impl From<DefId> for FakeDefId {
+impl From<DefId> for ItemId {
     fn from(id: DefId) -> Self {
-        Self::Real(id)
+        Self::DefId(id)
     }
 }
 
@@ -338,14 +333,14 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
     /// Information about this item that is specific to what kind of item it is.
     /// E.g., struct vs enum vs function.
     crate kind: Box<ItemKind>,
-    crate def_id: FakeDefId,
+    crate def_id: ItemId,
 
     crate cfg: Option<Arc<Cfg>>,
 }
 
 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Item, 48);
+rustc_data_structures::static_assert_size!(Item, 56);
 
 crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
     Span::from_rustc_span(def_id.as_local().map_or_else(
@@ -359,19 +354,19 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
 
 impl Item {
     crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
-        if self.is_fake() { None } else { tcx.lookup_stability(self.def_id.expect_real()) }
+        self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
     }
 
     crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
-        if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id.expect_real()) }
+        self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
     }
 
     crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
-        if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id.expect_real()) }
+        self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
     }
 
     crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
-        if self.is_fake() { false } else { tcx.get_attrs(self.def_id.expect_real()).inner_docs() }
+        self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
     }
 
     crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -383,10 +378,8 @@ impl Item {
             kind
         {
             *span
-        } else if self.is_fake() {
-            Span::dummy()
         } else {
-            rustc_span(self.def_id.expect_real(), tcx)
+            self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy())
         }
     }
 
@@ -551,7 +544,7 @@ pub fn from_def_id_and_attrs_and_parts(
     }
 
     crate fn is_crate(&self) -> bool {
-        self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX)
+        self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
     }
     crate fn is_mod(&self) -> bool {
         self.type_() == ItemType::Module
@@ -662,10 +655,6 @@ pub fn from_def_id_and_attrs_and_parts(
             _ => false,
         }
     }
-
-    crate fn is_fake(&self) -> bool {
-        matches!(self.def_id, FakeDefId::Fake(_, _))
-    }
 }
 
 #[derive(Clone, Debug)]
index fb46b81102caaf0e3b024cb56a4c150a53a1f397..7ae602c8033f8f65530936397aca0a6553b3d557 100644 (file)
@@ -3,10 +3,12 @@
 use crate::clean::{
     inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
     Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+    Visibility,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
 
+use rustc_ast as ast;
 use rustc_ast::tokenstream::TokenTree;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -577,3 +579,37 @@ pub(super) fn render_macro_arms<'a>(
 pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
     rustc_ast_pretty::pprust::tt_to_string(matcher)
 }
+
+pub(super) fn display_macro_source(
+    cx: &mut DocContext<'_>,
+    name: Symbol,
+    def: &ast::MacroDef,
+    def_id: DefId,
+    vis: impl Clean<Visibility>,
+) -> String {
+    let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
+    // Extract the spans of all matchers. They represent the "interface" of the macro.
+    let matchers = tts.chunks(4).map(|arm| &arm[0]);
+
+    if def.macro_rules {
+        format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
+    } else {
+        let vis = vis.clean(cx);
+
+        if matchers.len() <= 1 {
+            format!(
+                "{}macro {}{} {{\n    ...\n}}",
+                vis.to_src_with_space(cx.tcx, def_id),
+                name,
+                matchers.map(render_macro_matcher).collect::<String>(),
+            )
+        } else {
+            format!(
+                "{}macro {} {{\n{}}}",
+                vis.to_src_with_space(cx.tcx, def_id),
+                name,
+                render_macro_arms(matchers, ","),
+            )
+        }
+    }
+}
index 1b5a00dde59bce80aeac714e5c982662e96a13c4..4cf647a81ae4b4f12e9f5089bf7d2ef881520f6d 100644 (file)
@@ -513,7 +513,7 @@ fn println_condition(condition: Condition) {
                     ))
                     .warn("the theme may appear incorrect when loaded")
                     .help(&format!(
-                        "to see what rules are missing, call `rustdoc  --check-theme \"{}\"`",
+                        "to see what rules are missing, call `rustdoc --check-theme \"{}\"`",
                         theme_s
                     ))
                     .emit();
index 66f4f481292691662fb7d107ed9042a45b9e2837..0689d72e4e0cf7187f19059995b839bd5071f541 100644 (file)
@@ -30,7 +30,7 @@
 use std::rc::Rc;
 
 use crate::clean::inline::build_external_trait;
-use crate::clean::{self, FakeDefId, TraitWithExtraInfo};
+use crate::clean::{self, ItemId, TraitWithExtraInfo};
 use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
 use crate::formats::cache::Cache;
 use crate::passes::{self, Condition::*, ConditionalPass};
@@ -78,7 +78,7 @@
     /// This same cache is used throughout rustdoc, including in [`crate::html::render`].
     crate cache: Cache,
     /// Used by [`clean::inline`] to tell if an item has already been inlined.
-    crate inlined: FxHashSet<FakeDefId>,
+    crate inlined: FxHashSet<ItemId>,
     /// Used by `calculate_doc_coverage`.
     crate output_format: OutputFormat,
 }
@@ -128,12 +128,13 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
     /// (This avoids a slice-index-out-of-bounds panic.)
-    crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: FakeDefId) -> Option<HirId> {
+    crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option<HirId> {
         match def_id {
-            FakeDefId::Real(real_id) => {
+            ItemId::DefId(real_id) => {
                 real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
             }
-            FakeDefId::Fake(_, _) => None,
+            // FIXME: Can this be `Some` for `Auto` or `Blanket`?
+            _ => None,
         }
     }
 }
index 1281f76fd0fdc9d42739251f8799cf8ef54d87a9..cd914f05e680c72c61527471ef1f0a8788127abf 100644 (file)
@@ -513,7 +513,7 @@ fn drop(&mut self) {
     // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
     // crate already is included.
     let result = rustc_driver::catch_fatal_errors(|| {
-        rustc_span::with_session_globals(edition, || {
+        rustc_span::create_session_if_not_set_then(edition, |_| {
             use rustc_errors::emitter::{Emitter, EmitterWriter};
             use rustc_errors::Handler;
             use rustc_parse::maybe_new_parser_from_source_str;
index 1e1fc2436aac1f46acec439aeef6e66c4bd8f475..e7d6e5ac2c24be1f3d635c04165d29b02fc358cc 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
-use crate::clean::{self, FakeDefId, GetDefId};
+use crate::clean::{self, GetDefId, ItemId};
 use crate::fold::DocFolder;
 use crate::formats::item_type::ItemType;
 use crate::formats::Impl;
     /// All intra-doc links resolved so far.
     ///
     /// Links are indexed by the DefId of the item they document.
-    crate intra_doc_links: BTreeMap<FakeDefId, Vec<clean::ItemLink>>,
+    crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
 }
 
 /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
@@ -215,7 +215,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // Propagate a trait method's documentation to all implementors of the
         // trait.
         if let clean::TraitItem(ref t) = *item.kind {
-            self.cache.traits.entry(item.def_id.expect_real()).or_insert_with(|| {
+            self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
                 clean::TraitWithExtraInfo {
                     trait_: t.clone(),
                     is_notable: item.attrs.has_doc_flag(sym::notable_trait),
@@ -348,11 +348,11 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     // `public_items` map, so we can skip inserting into the
                     // paths map if there was already an entry present and we're
                     // not a public item.
-                    if !self.cache.paths.contains_key(&item.def_id.expect_real())
-                        || self.cache.access_levels.is_public(item.def_id.expect_real())
+                    if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
+                        || self.cache.access_levels.is_public(item.def_id.expect_def_id())
                     {
                         self.cache.paths.insert(
-                            item.def_id.expect_real(),
+                            item.def_id.expect_def_id(),
                             (self.cache.stack.clone(), item.type_()),
                         );
                     }
@@ -361,7 +361,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             clean::PrimitiveItem(..) => {
                 self.cache
                     .paths
-                    .insert(item.def_id.expect_real(), (self.cache.stack.clone(), item.type_()));
+                    .insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
             }
 
             clean::ExternCrateItem { .. }
@@ -391,7 +391,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             | clean::StructItem(..)
             | clean::UnionItem(..)
             | clean::VariantItem(..) => {
-                self.cache.parent_stack.push(item.def_id.expect_real());
+                self.cache.parent_stack.push(item.def_id.expect_def_id());
                 self.cache.parent_is_trait_impl = false;
                 true
             }
index 1e08aeb379a2b056a941ef2d124a6b86c3d09e76..c08fe47696bf1b85115949e7938a5afe1b0cfb7a 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_target::spec::abi::Abi;
 
 use crate::clean::{
-    self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, GetDefId, PrimitiveType,
+    self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType,
 };
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
@@ -1181,7 +1181,7 @@ fn inner_full_print(
 impl clean::Visibility {
     crate fn print_with_space<'a, 'tcx: 'a>(
         self,
-        item_did: FakeDefId,
+        item_did: ItemId,
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
         let to_print = match self {
@@ -1191,7 +1191,7 @@ impl clean::Visibility {
                 // FIXME(camelid): This may not work correctly if `item_did` is a module.
                 //                 However, rustdoc currently never displays a module's
                 //                 visibility, so it shouldn't matter.
-                let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_real());
+                let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
 
                 if vis_did.index == CRATE_DEF_INDEX {
                     "pub(crate) ".to_owned()
index a0da2c963d167312314911e4aed238f1fff62a42..a505865b149c4bc91e0ee1e4480686c38df96502 100644 (file)
@@ -1,8 +1,8 @@
 use super::write_code;
 use crate::html::format::Buffer;
 use expect_test::expect_file;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::edition::Edition;
-use rustc_span::with_default_session_globals;
 
 const STYLE: &str = r#"
 <style>
@@ -18,7 +18,7 @@
 
 #[test]
 fn test_html_highlighting() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let src = include_str!("fixtures/sample.rs");
         let html = {
             let mut out = Buffer::new();
@@ -31,7 +31,7 @@ fn test_html_highlighting() {
 
 #[test]
 fn test_dos_backline() {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let src = "pub fn foo() {\r\n\
     println!(\"foo\");\r\n\
 }\r\n";
index bafb522f363383733ab5486e354be92f027fb9bd..9fff508165a1010f9fbb5afda2ef55c68f9189cd 100644 (file)
@@ -1358,7 +1358,10 @@ pub struct IdMap {
 
 fn init_id_map() -> FxHashMap<String, usize> {
     let mut map = FxHashMap::default();
-    // This is the list of IDs used by rustdoc templates.
+    // This is the list of IDs used in Javascript.
+    map.insert("help".to_owned(), 1);
+    // This is the list of IDs used in HTML generated in Rust (including the ones
+    // used in tera template files).
     map.insert("mainThemeStyle".to_owned(), 1);
     map.insert("themeStyle".to_owned(), 1);
     map.insert("theme-picker".to_owned(), 1);
@@ -1375,14 +1378,14 @@ fn init_id_map() -> FxHashMap<String, usize> {
     map.insert("rustdoc-vars".to_owned(), 1);
     map.insert("sidebar-vars".to_owned(), 1);
     map.insert("copy-path".to_owned(), 1);
-    map.insert("help".to_owned(), 1);
     map.insert("TOC".to_owned(), 1);
-    map.insert("render-detail".to_owned(), 1);
-    // This is the list of IDs used by rustdoc sections.
+    // This is the list of IDs used by rustdoc sections (but still generated by
+    // rustdoc).
     map.insert("fields".to_owned(), 1);
     map.insert("variants".to_owned(), 1);
     map.insert("implementors-list".to_owned(), 1);
     map.insert("synthetic-implementors-list".to_owned(), 1);
+    map.insert("foreign-impls".to_owned(), 1);
     map.insert("implementations".to_owned(), 1);
     map.insert("trait-implementations".to_owned(), 1);
     map.insert("synthetic-implementations".to_owned(), 1);
@@ -1393,6 +1396,10 @@ fn init_id_map() -> FxHashMap<String, usize> {
     map.insert("provided-methods".to_owned(), 1);
     map.insert("implementors".to_owned(), 1);
     map.insert("synthetic-implementors".to_owned(), 1);
+    map.insert("trait-implementations-list".to_owned(), 1);
+    map.insert("synthetic-implementations-list".to_owned(), 1);
+    map.insert("blanket-implementations-list".to_owned(), 1);
+    map.insert("deref-methods".to_owned(), 1);
     map
 }
 
index 2085739fc46ec68e4ef80ea13878a399f59828d2..61057ff515b169aecd40f9411389021c369ada21 100644 (file)
@@ -230,7 +230,7 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
                 &self.shared.style_files,
             )
         } else {
-            if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_real()) {
+            if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_def_id()) {
                 let mut path = String::new();
                 for name in &names[..names.len() - 1] {
                     path.push_str(name);
index 0583efa92ffad2646a39581ef3f15b1fab7522fa..56d50cb407926acb97b48ef15314bf2a3a84d3d0 100644 (file)
@@ -53,7 +53,7 @@
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use crate::clean::{self, FakeDefId, GetDefId, RenderedLink, SelfTy};
+use crate::clean::{self, GetDefId, ItemId, RenderedLink, SelfTy};
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -735,7 +735,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
         AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
         AssocItemLink::Anchor(None) => anchor,
         AssocItemLink::GotoSource(did, _) => {
-            href(did.expect_real(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
+            href(did.expect_def_id(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
         }
     }
 }
@@ -867,7 +867,7 @@ fn method(
                     ItemType::TyMethod
                 };
 
-                href(did.expect_real(), cx)
+                href(did.expect_def_id(), cx)
                     .map(|p| format!("{}#{}.{}", p.0, ty, name))
                     .unwrap_or_else(|| format!("#{}.{}", ty, name))
             }
@@ -987,7 +987,7 @@ fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) {
 #[derive(Copy, Clone)]
 enum AssocItemLink<'a> {
     Anchor(Option<&'a str>),
-    GotoSource(FakeDefId, &'a FxHashSet<Symbol>),
+    GotoSource(ItemId, &'a FxHashSet<Symbol>),
 }
 
 impl<'a> AssocItemLink<'a> {
@@ -1027,7 +1027,7 @@ fn render_assoc_items(
                 write!(
                     w,
                     "<h2 id=\"deref-methods\" class=\"small-section-header\">\
-                         Methods from {trait_}&lt;Target = {type_}&gt;\
+                         <span>Methods from {trait_}&lt;Target = {type_}&gt;</span>\
                          <a href=\"#deref-methods\" class=\"anchor\"></a>\
                      </h2>",
                     trait_ = trait_.print(cx),
@@ -1819,7 +1819,7 @@ fn small_url_encode(s: String) -> String {
 }
 
 fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
-    let did = it.def_id.expect_real();
+    let did = it.def_id.expect_def_id();
     if let Some(v) = cx.cache.impls.get(&did) {
         let mut used_links = FxHashSet::default();
         let cache = cx.cache();
@@ -2109,7 +2109,7 @@ fn print_sidebar_section(
         "</div>",
     );
 
-    if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) {
+    if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
         let cache = cx.cache();
         let mut res = implementors
             .iter()
index ea141c5104824e2cd4252d650e6872bdc410d7e0..f7073a8751fa18723622c06d15c6e26a29adae86 100644 (file)
@@ -133,7 +133,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
         clean::StructItem(ref s) => item_struct(buf, cx, item, s),
         clean::UnionItem(ref s) => item_union(buf, cx, item, s),
         clean::EnumItem(ref e) => item_enum(buf, cx, item, e),
-        clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t),
+        clean::TypedefItem(ref t, is_associated) => item_typedef(buf, cx, item, t, is_associated),
         clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
         clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
         clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
@@ -289,7 +289,7 @@ fn cmp(
                         w,
                         "<div class=\"item-left\"><code>{}extern crate {} as {};",
                         myitem.visibility.print_with_space(myitem.def_id, cx),
-                        anchor(myitem.def_id.expect_real(), &*src.as_str(), cx),
+                        anchor(myitem.def_id.expect_def_id(), &*src.as_str(), cx),
                         myitem.name.as_ref().unwrap(),
                     ),
                     None => write!(
@@ -297,7 +297,7 @@ fn cmp(
                         "<div class=\"item-left\"><code>{}extern crate {};",
                         myitem.visibility.print_with_space(myitem.def_id, cx),
                         anchor(
-                            myitem.def_id.expect_real(),
+                            myitem.def_id.expect_def_id(),
                             &*myitem.name.as_ref().unwrap().as_str(),
                             cx
                         ),
@@ -669,9 +669,9 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
     }
 
     // If there are methods directly on this trait object, render them here.
-    render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All);
+    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
 
-    if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) {
+    if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
@@ -787,7 +787,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         path = if it.def_id.is_local() {
             cx.current.join("/")
         } else {
-            let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_real()];
+            let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_def_id()];
             path[..path.len() - 1].join("/")
         },
         ty = it.type_(),
@@ -813,7 +813,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
@@ -834,12 +834,21 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
 }
 
-fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
+fn item_typedef(
+    w: &mut Buffer,
+    cx: &Context<'_>,
+    it: &clean::Item,
+    t: &clean::Typedef,
+    is_associated: bool,
+) {
     w.write_str("<pre class=\"rust typedef\">");
     render_attributes_in_pre(w, it, "");
+    if !is_associated {
+        write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
+    }
     write!(
         w,
         "type {}{}{where_clause} = {type_};</pre>",
@@ -851,7 +860,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
 
     document(w, cx, it, None);
 
-    let def_id = it.def_id.expect_real();
+    let def_id = it.def_id.expect_def_id();
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
@@ -903,7 +912,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
             document(w, cx, field, Some(it));
         }
     }
-    let def_id = it.def_id.expect_real();
+    let def_id = it.def_id.expect_def_id();
     render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
     document_type_layout(w, cx, def_id);
 }
@@ -1041,7 +1050,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             }
         }
     }
-    let def_id = it.def_id.expect_real();
+    let def_id = it.def_id.expect_def_id();
     render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
     document_type_layout(w, cx, def_id);
 }
@@ -1093,7 +1102,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
 
 fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
     document(w, cx, it, None);
-    render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
@@ -1182,7 +1191,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
             }
         }
     }
-    let def_id = it.def_id.expect_real();
+    let def_id = it.def_id.expect_def_id();
     render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
     document_type_layout(w, cx, def_id);
 }
@@ -1213,7 +1222,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
 
     document(w, cx, it, None);
 
-    render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
 }
 
 fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
diff --git a/src/librustdoc/html/static/FiraSans-LICENSE.txt b/src/librustdoc/html/static/FiraSans-LICENSE.txt
deleted file mode 100644 (file)
index ff9afab..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
-with Reserved Font Name < Fira >,
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/FiraSans-Medium.woff b/src/librustdoc/html/static/FiraSans-Medium.woff
deleted file mode 100644 (file)
index 7d742c5..0000000
Binary files a/src/librustdoc/html/static/FiraSans-Medium.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/FiraSans-Medium.woff2 b/src/librustdoc/html/static/FiraSans-Medium.woff2
deleted file mode 100644 (file)
index 7a1e5fc..0000000
Binary files a/src/librustdoc/html/static/FiraSans-Medium.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/FiraSans-Regular.woff b/src/librustdoc/html/static/FiraSans-Regular.woff
deleted file mode 100644 (file)
index d8e0363..0000000
Binary files a/src/librustdoc/html/static/FiraSans-Regular.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/FiraSans-Regular.woff2 b/src/librustdoc/html/static/FiraSans-Regular.woff2
deleted file mode 100644 (file)
index e766e06..0000000
Binary files a/src/librustdoc/html/static/FiraSans-Regular.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceCodePro-It.ttf.woff b/src/librustdoc/html/static/SourceCodePro-It.ttf.woff
deleted file mode 100644 (file)
index 8d68f2f..0000000
Binary files a/src/librustdoc/html/static/SourceCodePro-It.ttf.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceCodePro-It.ttf.woff2 b/src/librustdoc/html/static/SourceCodePro-It.ttf.woff2
deleted file mode 100644 (file)
index 462c34e..0000000
Binary files a/src/librustdoc/html/static/SourceCodePro-It.ttf.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceCodePro-LICENSE.txt b/src/librustdoc/html/static/SourceCodePro-LICENSE.txt
deleted file mode 100644 (file)
index 0754257..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff b/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff
deleted file mode 100644 (file)
index 7be076e..0000000
Binary files a/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff2 b/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff2
deleted file mode 100644 (file)
index 10b558e..0000000
Binary files a/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff b/src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff
deleted file mode 100644 (file)
index 61bc67b..0000000
Binary files a/src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff2 b/src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff2
deleted file mode 100644 (file)
index 5ec64ee..0000000
Binary files a/src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff b/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff
deleted file mode 100644 (file)
index 8ad4188..0000000
Binary files a/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff2 b/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff2
deleted file mode 100644 (file)
index db57d21..0000000
Binary files a/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceSerif4-It.ttf.woff b/src/librustdoc/html/static/SourceSerif4-It.ttf.woff
deleted file mode 100644 (file)
index 2a34b5c..0000000
Binary files a/src/librustdoc/html/static/SourceSerif4-It.ttf.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceSerif4-It.ttf.woff2 b/src/librustdoc/html/static/SourceSerif4-It.ttf.woff2
deleted file mode 100644 (file)
index 1cbc021..0000000
Binary files a/src/librustdoc/html/static/SourceSerif4-It.ttf.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceSerif4-LICENSE.md b/src/librustdoc/html/static/SourceSerif4-LICENSE.md
deleted file mode 100644 (file)
index 68ea189..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff b/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff
deleted file mode 100644 (file)
index 45a5521..0000000
Binary files a/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff2 b/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff2
deleted file mode 100644 (file)
index 2db73fe..0000000
Binary files a/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff2 and /dev/null differ
diff --git a/src/librustdoc/html/static/brush.svg b/src/librustdoc/html/static/brush.svg
deleted file mode 100644 (file)
index ea266e8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/clipboard.svg b/src/librustdoc/html/static/clipboard.svg
deleted file mode 100644 (file)
index 8adbd99..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="24" height="25" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>
diff --git a/src/librustdoc/html/static/css/normalize.css b/src/librustdoc/html/static/css/normalize.css
new file mode 100644 (file)
index 0000000..fdb8a8c
--- /dev/null
@@ -0,0 +1,2 @@
+/* ignore-tidy-linelength */
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
new file mode 100644 (file)
index 0000000..0a196ed
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+This whole CSS file is used only in case rustdoc is rendered with javascript disabled. Since a lot
+of content is hidden by default (depending on the settings too), we have to overwrite some of the
+rules.
+*/
+
+#main .attributes {
+       /* Since there is no toggle (the "[-]") when JS is disabled, no need for this margin either. */
+       margin-left: 0 !important;
+}
+
+#copy-path {
+       /* It requires JS to work so no need to display it in this case. */
+       display: none;
+}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
new file mode 100644 (file)
index 0000000..66dfd2f
--- /dev/null
@@ -0,0 +1,1883 @@
+/* See FiraSans-LICENSE.txt for the Fira Sans license. */
+@font-face {
+       font-family: 'Fira Sans';
+       font-style: normal;
+       font-weight: 400;
+       src: local('Fira Sans'),
+               url("FiraSans-Regular.woff2") format("woff2"),
+               url("FiraSans-Regular.woff") format('woff');
+       font-display: swap;
+}
+@font-face {
+       font-family: 'Fira Sans';
+       font-style: normal;
+       font-weight: 500;
+       src: local('Fira Sans Medium'),
+               url("FiraSans-Medium.woff2") format("woff2"),
+               url("FiraSans-Medium.woff") format('woff');
+       font-display: swap;
+}
+
+/* See SourceSerif4-LICENSE.md for the Source Serif 4 license. */
+@font-face {
+       font-family: 'Source Serif 4';
+       font-style: normal;
+       font-weight: 400;
+       src: local('Source Serif 4'),
+               url("SourceSerif4-Regular.ttf.woff2") format("woff2"),
+               url("SourceSerif4-Regular.ttf.woff") format("woff");
+       font-display: swap;
+}
+@font-face {
+       font-family: 'Source Serif 4';
+       font-style: italic;
+       font-weight: 400;
+       src: local('Source Serif 4 Italic'),
+               url("SourceSerif4-It.ttf.woff2") format("woff2"),
+               url("SourceSerif4-It.ttf.woff") format("woff");
+       font-display: swap;
+}
+@font-face {
+       font-family: 'Source Serif 4';
+       font-style: normal;
+       font-weight: 700;
+       src: local('Source Serif 4 Bold'),
+               url("SourceSerif4-Bold.ttf.woff2") format("woff2"),
+               url("SourceSerif4-Bold.ttf.woff") format("woff");
+       font-display: swap;
+}
+
+/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */
+@font-face {
+       font-family: 'Source Code Pro';
+       font-style: normal;
+       font-weight: 400;
+       /* Avoid using locally installed font because bad versions are in circulation:
+        * see https://github.com/rust-lang/rust/issues/24355 */
+       src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"),
+               url("SourceCodePro-Regular.ttf.woff") format("woff");
+       font-display: swap;
+}
+@font-face {
+       font-family: 'Source Code Pro';
+       font-style: italic;
+       font-weight: 400;
+       src: url("SourceCodePro-It.ttf.woff2") format("woff2"),
+               url("SourceCodePro-It.ttf.woff") format("woff");
+       font-display: swap;
+}
+@font-face {
+       font-family: 'Source Code Pro';
+       font-style: normal;
+       font-weight: 600;
+       src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"),
+               url("SourceCodePro-Semibold.ttf.woff") format("woff");
+       font-display: swap;
+}
+
+/* Avoid using legacy CJK serif fonts in Windows like Batang */
+@font-face {
+       font-family: 'Noto Sans KR';
+       src: url("noto-sans-kr-v13-korean-regular.woff") format("woff");
+       font-display: swap;
+       unicode-range: U+A960-A97F, U+AC00-D7AF, U+D7B0-D7FF;
+}
+
+* {
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+}
+
+/* This part handles the "default" theme being used depending on the system one. */
+html {
+       content: "";
+}
+@media (prefers-color-scheme: light) {
+       html {
+               content: "light";
+       }
+}
+@media (prefers-color-scheme: dark) {
+       html {
+               content: "dark";
+       }
+}
+
+/* General structure and fonts */
+
+body {
+       font: 16px/1.4 "Source Serif 4", "Noto Sans KR", serif;
+       margin: 0;
+       position: relative;
+       padding: 10px 15px 20px 15px;
+
+       -webkit-font-feature-settings: "kern", "liga";
+       -moz-font-feature-settings: "kern", "liga";
+       font-feature-settings: "kern", "liga";
+}
+
+h1 {
+       font-size: 1.5em;
+}
+h2 {
+       font-size: 1.4em;
+}
+h3 {
+       font-size: 1.3em;
+}
+h1, h2, h3, h4 {
+       font-weight: 500;
+       margin: 20px 0 15px 0;
+       padding-bottom: 6px;
+}
+h1.fqn {
+       display: flex;
+       border-bottom: 1px dashed;
+       margin-top: 0;
+
+       /* workaround to keep flex from breaking below 700 px width due to the float: right on the nav
+          above the h1 */
+       padding-left: 1px;
+}
+h1.fqn > .in-band > a:hover {
+       text-decoration: underline;
+}
+h2, h3, h4 {
+       border-bottom: 1px solid;
+}
+.impl,
+.impl-items .method,
+.methods .method,
+.impl-items .type,
+.methods .type,
+.impl-items .associatedconstant,
+.methods .associatedconstant,
+.impl-items .associatedtype,
+.methods .associatedtype {
+       flex-basis: 100%;
+       font-weight: 600;
+       margin-top: 16px;
+       margin-bottom: 10px;
+       position: relative;
+}
+.impl, .method.trait-impl,
+.type.trait-impl,
+.associatedconstant.trait-impl,
+.associatedtype.trait-impl {
+       padding-left: 15px;
+}
+
+div.impl-items > div {
+       padding-left: 0;
+}
+
+h1, h2, h3, h4,
+.sidebar, a.source, .search-input, .search-results .result-name,
+.content table td:first-child > a,
+.item-left > a,
+div.item-list .out-of-band, span.since,
+#source-sidebar, #sidebar-toggle,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before,
+div.impl-items > div:not(.docblock):not(.item-info),
+.content ul.crate a.crate, a.srclink,
+/* This selector is for the items listed in the "all items" page. */
+#main > ul.docblock > li > a {
+       font-family: "Fira Sans", Arial, sans-serif;
+}
+
+.content ul.crate a.crate {
+       font-size: 16px/1.6;
+}
+
+ol, ul {
+       padding-left: 25px;
+}
+ul ul, ol ul, ul ol, ol ol {
+       margin-bottom: .6em;
+}
+
+p {
+       margin: 0 0 .6em 0;
+}
+
+summary {
+       outline: none;
+}
+
+/* Fix some style changes due to normalize.css 8 */
+
+td,
+th {
+       padding: 0;
+}
+
+table {
+       border-collapse: collapse;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+       color: inherit;
+       font: inherit;
+       margin: 0;
+}
+
+/* end tweaks for normalize.css 8 */
+
+details:not(.rustdoc-toggle) summary {
+       margin-bottom: .6em;
+}
+
+code, pre, a.test-arrow {
+       font-family: "Source Code Pro", monospace;
+}
+.docblock code, .docblock-short code {
+       border-radius: 3px;
+       padding: 0 0.1em;
+}
+.docblock pre code, .docblock-short pre code {
+       padding: 0;
+       padding-right: 1ex;
+}
+pre {
+       padding: 14px;
+}
+
+.source .content pre {
+       padding: 20px;
+}
+
+img {
+       max-width: 100%;
+}
+
+li {
+       position: relative;
+}
+
+.source .content {
+       margin-top: 50px;
+       max-width: none;
+       overflow: visible;
+       margin-left: 0px;
+}
+
+nav.sub {
+       font-size: 16px;
+       text-transform: uppercase;
+}
+
+.sidebar {
+       width: 200px;
+       position: fixed;
+       left: 0;
+       top: 0;
+       bottom: 0;
+       overflow: auto;
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+       scrollbar-width: initial;
+}
+.sidebar {
+       scrollbar-width: thin;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar {
+       width: 12px;
+}
+.sidebar::-webkit-scrollbar {
+       width: 8px;
+}
+::-webkit-scrollbar-track {
+       -webkit-box-shadow: inset 0;
+}
+
+.sidebar .block > ul > li {
+       margin-right: -10px;
+}
+
+.content, nav {
+       max-width: 960px;
+}
+
+/* Everything else */
+
+.hidden {
+       display: none !important;
+}
+
+.logo-container {
+       height: 100px;
+       width: 100px;
+       position: relative;
+       margin: 20px auto;
+       display: block;
+       margin-top: 10px;
+}
+
+.logo-container > img {
+       max-width: 100px;
+       max-height: 100px;
+       position: absolute;
+       left: 50%;
+       top: 50%;
+       transform: translate(-50%, -50%);
+       display: block;
+}
+
+.sidebar .location {
+       border: 1px solid;
+       font-size: 17px;
+       margin: 30px 10px 20px 10px;
+       text-align: center;
+       word-wrap: break-word;
+}
+
+.sidebar .version {
+       font-size: 15px;
+       text-align: center;
+       border-bottom: 1px solid;
+       overflow-wrap: break-word;
+       word-wrap: break-word; /* deprecated */
+       word-break: break-word; /* Chrome, non-standard */
+}
+
+.location:empty {
+       border: none;
+}
+
+.location a:first-of-type {
+       font-weight: 500;
+}
+.location a:hover {
+       text-decoration: underline;
+}
+
+.block {
+       padding: 0;
+       margin-bottom: 14px;
+}
+.block h2, .block h3 {
+       text-align: center;
+}
+.block ul, .block li {
+       margin: 0 10px;
+       padding: 0;
+       list-style: none;
+}
+
+.block a {
+       display: block;
+       text-overflow: ellipsis;
+       overflow: hidden;
+       line-height: 15px;
+       padding: 7px 5px;
+       font-size: 14px;
+       font-weight: 300;
+       transition: border 500ms ease-out;
+}
+
+.sidebar-title {
+       border-top: 1px solid;
+       border-bottom: 1px solid;
+       text-align: center;
+       font-size: 17px;
+       margin-bottom: 5px;
+}
+
+.sidebar-links {
+       margin-bottom: 15px;
+}
+
+.sidebar-links > a {
+       padding-left: 10px;
+       width: 100%;
+}
+
+.sidebar-menu {
+       display: none;
+}
+
+.content {
+       padding: 15px 0;
+}
+
+.source .content pre.rust {
+       white-space: pre;
+       overflow: auto;
+       padding-left: 0;
+}
+
+.rustdoc .example-wrap {
+       display: inline-flex;
+       margin-bottom: 10px;
+}
+
+.example-wrap {
+       position: relative;
+       width: 100%;
+}
+
+.example-wrap > pre.line-number {
+       overflow: initial;
+       border: 1px solid;
+       padding: 13px 8px;
+       text-align: right;
+       border-top-left-radius: 5px;
+       border-bottom-left-radius: 5px;
+}
+
+.rustdoc:not(.source) .example-wrap > pre.rust {
+       width: 100%;
+       overflow-x: auto;
+}
+
+.rustdoc .example-wrap > pre {
+       margin: 0;
+}
+
+#search {
+       margin-left: 230px;
+       position: relative;
+}
+
+#results > table {
+       width: 100%;
+       table-layout: fixed;
+}
+
+.content > .example-wrap pre.line-numbers {
+       position: relative;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+.line-numbers span {
+       cursor: pointer;
+}
+
+.docblock-short {
+       overflow-wrap: anywhere;
+}
+.docblock-short p {
+       display: inline;
+}
+
+.docblock-short p {
+       overflow: hidden;
+       text-overflow: ellipsis;
+       margin: 0;
+}
+/* Wrap non-pre code blocks (`text`) but not (```text```). */
+.docblock > :not(pre) > code,
+.docblock-short > :not(pre) > code {
+       white-space: pre-wrap;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+       border-bottom: 1px solid;
+}
+
+.top-doc .docblock h1 { font-size: 1.3em; }
+.top-doc .docblock h2 { font-size: 1.15em; }
+.top-doc .docblock h3,
+.top-doc .docblock h4,
+.top-doc .docblock h5 {
+       font-size: 1em;
+}
+
+.docblock h1 { font-size: 1em; }
+.docblock h2 { font-size: 0.95em; }
+.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
+
+.docblock {
+       margin-left: 24px;
+       position: relative;
+}
+
+.content .out-of-band {
+       flex-grow: 0;
+       text-align: right;
+       font-size: 23px;
+       margin: 0px;
+       padding: 0 0 0 12px;
+       font-weight: normal;
+}
+
+.method > code, .trait-impl > code, .invisible > code {
+       max-width: calc(100% - 41px);
+       display: block;
+}
+
+.invisible {
+       width: 100%;
+       display: inline-block;
+}
+
+.content .in-band {
+       flex-grow: 1;
+       margin: 0px;
+       padding: 0px;
+}
+
+.in-band > code {
+       display: inline-block;
+}
+
+#main {
+       position: relative;
+}
+#main > .since {
+       top: inherit;
+       font-family: "Fira Sans", Arial, sans-serif;
+}
+
+.content table:not(.table-display) {
+       border-spacing: 0 5px;
+}
+.content td { vertical-align: top; }
+.content td:first-child { padding-right: 20px; }
+.content td p:first-child { margin-top: 0; }
+.content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; }
+.content tr:first-child td { border-top: 0; }
+
+.docblock table {
+       margin: .5em 0;
+       width: calc(100% - 2px);
+       border: 1px dashed;
+}
+
+.docblock table td {
+       padding: .5em;
+       border: 1px dashed;
+}
+
+.docblock table th {
+       padding: .5em;
+       text-align: left;
+       border: 1px solid;
+}
+
+.fields + table {
+       margin-bottom: 1em;
+}
+
+.content .item-list {
+       list-style-type: none;
+       padding: 0;
+}
+
+.content .multi-column {
+       -moz-column-count: 5;
+       -moz-column-gap: 2.5em;
+       -webkit-column-count: 5;
+       -webkit-column-gap: 2.5em;
+       column-count: 5;
+       column-gap: 2.5em;
+}
+.content .multi-column li { width: 100%; display: inline-block; }
+
+.content > .methods > .method {
+       font-size: 1em;
+       position: relative;
+}
+/* Shift "where ..." part of method or fn definition down a line */
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+       display: block;
+       font-size: 0.8em;
+}
+
+.content .methods > div:not(.notable-traits):not(.method) {
+       margin-left: 40px;
+       margin-bottom: 15px;
+}
+
+.content .docblock > .impl-items {
+       margin-left: 20px;
+       margin-top: -34px;
+}
+.content .docblock >.impl-items .table-display {
+       margin: 0;
+}
+.content .docblock >.impl-items table td {
+       padding: 0;
+}
+.content .docblock > .impl-items .table-display, .impl-items table td {
+       border: none;
+}
+
+.content .item-info code {
+       font-size: 90%;
+}
+
+.content .item-info {
+       position: relative;
+       margin-left: 33px;
+}
+
+.sub-variant > div > .item-info {
+       margin-top: initial;
+}
+
+.content .item-info::before {
+       content: '⬑';
+       font-size: 25px;
+       position: absolute;
+       top: -6px;
+       left: -19px;
+}
+
+.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant,
+.impl-items > .associatedtype, .content .impl-items details > summary > .type,
+.impl-items details > summary > .associatedconstant,
+.impl-items details > summary > .associatedtype {
+       margin-left: 20px;
+}
+
+.content .impl-items .docblock, .content .impl-items .item-info {
+       margin-bottom: .6em;
+}
+
+.content .impl-items > .item-info {
+       margin-left: 40px;
+}
+
+.methods > .item-info, .content .impl-items > .item-info {
+       margin-top: -8px;
+}
+
+.impl-items {
+       flex-basis: 100%;
+}
+
+#main > .item-info {
+       margin-top: 0;
+}
+
+nav:not(.sidebar) {
+       border-bottom: 1px solid;
+       padding-bottom: 10px;
+       margin-bottom: 10px;
+}
+nav.main {
+       padding: 20px 0;
+       text-align: center;
+}
+nav.main .current {
+       border-top: 1px solid;
+       border-bottom: 1px solid;
+}
+nav.main .separator {
+       border: 1px solid;
+       display: inline-block;
+       height: 23px;
+       margin: 0 20px;
+}
+nav.sum { text-align: right; }
+nav.sub form { display: inline; }
+
+nav.sub, .content {
+       margin-left: 230px;
+}
+
+a {
+       text-decoration: none;
+       background: transparent;
+}
+
+.small-section-header {
+       display: flex;
+       justify-content: space-between;
+       position: relative;
+}
+
+.small-section-header:hover > .anchor {
+       display: initial;
+}
+
+.in-band:hover > .anchor, .impl:hover > .anchor, .method.trait-impl:hover > .anchor,
+.type.trait-impl:hover > .anchor, .associatedconstant.trait-impl:hover > .anchor,
+.associatedtype.trait-impl:hover > .anchor {
+       display: inline-block;
+       position: absolute;
+}
+.anchor {
+       display: none;
+       position: absolute;
+       left: -7px;
+}
+.anchor.field {
+       left: -5px;
+}
+.small-section-header > .anchor {
+       left: -28px;
+       padding-right: 10px; /* avoid gap that causes hover to disappear */
+}
+.anchor:before {
+       content: '\2002\00a7\2002';
+}
+
+.docblock a:not(.srclink):not(.test-arrow):hover,
+.docblock-short a:not(.srclink):not(.test-arrow):hover, .item-info a {
+       text-decoration: underline;
+}
+
+.invisible > .srclink,
+.method > code + .srclink {
+       position: absolute;
+       top: 0;
+       right: 0;
+       font-size: 17px;
+       font-weight: normal;
+}
+
+.block a.current.crate { font-weight: 500; }
+
+.item-table {
+       display: grid;
+       column-gap: 1.2rem;
+       row-gap: 0.0rem;
+       grid-template-columns: auto 1fr;
+       /* align content left */
+       justify-items: start;
+}
+
+.item-left, .item-right {
+       display: block;
+}
+.item-left {
+       grid-column: 1;
+}
+.item-right {
+       grid-column: 2;
+}
+
+.search-container {
+       position: relative;
+}
+.search-container > div {
+       display: inline-flex;
+       width: calc(100% - 63px);
+}
+#crate-search {
+       min-width: 115px;
+       margin-top: 5px;
+       padding: 6px;
+       padding-right: 19px;
+       flex: none;
+       border: 0;
+       border-right: 0;
+       border-radius: 4px 0 0 4px;
+       outline: none;
+       cursor: pointer;
+       border-right: 1px solid;
+       -moz-appearance: none;
+       -webkit-appearance: none;
+       /* Removes default arrow from firefox */
+       text-indent: 0.01px;
+       text-overflow: "";
+       background-repeat: no-repeat;
+       background-color: transparent;
+       background-size: 20px;
+       background-position: calc(100% - 1px) 56%;
+}
+.search-container > .top-button {
+       position: absolute;
+       right: 0;
+       top: 10px;
+}
+.search-input {
+       /* Override Normalize.css: we have margins and do
+        not want to overflow - the `moz` attribute is necessary
+        until Firefox 29, too early to drop at this point */
+       -moz-box-sizing: border-box !important;
+       box-sizing: border-box !important;
+       outline: none;
+       border: none;
+       border-radius: 1px;
+       margin-top: 5px;
+       padding: 10px 16px;
+       font-size: 17px;
+       transition: border-color 300ms ease;
+       transition: border-radius 300ms ease-in-out;
+       transition: box-shadow 300ms ease-in-out;
+       width: 100%;
+}
+
+#crate-search + .search-input {
+       border-radius: 0 1px 1px 0;
+       width: calc(100% - 32px);
+}
+
+.search-input:focus {
+       border-radius: 2px;
+       border: 0;
+       outline: 0;
+}
+
+.search-results {
+       display: none;
+       padding-bottom: 2em;
+}
+
+.search-results.active {
+       display: block;
+       /* prevent overhanging tabs from moving the first result */
+       clear: both;
+}
+
+.search-results .desc > span {
+       white-space: nowrap;
+       text-overflow: ellipsis;
+       overflow: hidden;
+       display: block;
+}
+
+.search-results > a {
+       display: block;
+       width: 100%;
+       /* A little margin ensures the browser's outlining of focused links has room to display. */
+       margin-left: 2px;
+       margin-right: 2px;
+       border-bottom: 1px solid #aaa3;
+}
+
+.search-results > a > div {
+       display: flex;
+       flex-flow: row wrap;
+}
+
+.search-results .result-name, .search-results div.desc, .search-results .result-description {
+       width: 50%;
+}
+.search-results .result-name {
+       padding-right: 1em;
+}
+
+.search-results .result-name > span {
+       display: inline-block;
+       margin: 0;
+       font-weight: normal;
+}
+
+body.blur > :not(#help) {
+       filter: blur(8px);
+       -webkit-filter: blur(8px);
+       opacity: .7;
+}
+
+#help {
+       width: 100%;
+       height: 100vh;
+       position: fixed;
+       top: 0;
+       left: 0;
+       display: flex;
+       justify-content: center;
+       align-items: center;
+}
+#help > div {
+       flex: 0 0 auto;
+       box-shadow: 0 0 6px rgba(0,0,0,.2);
+       width: 550px;
+       height: auto;
+       border: 1px solid;
+}
+#help dt {
+       float: left;
+       clear: left;
+       display: block;
+       margin-right: 0.5rem;
+}
+#help > div > span {
+       text-align: center;
+       display: block;
+       margin: 10px 0;
+       font-size: 18px;
+       border-bottom: 1px solid #ccc;
+       padding-bottom: 4px;
+       margin-bottom: 6px;
+}
+#help dd { margin: 5px 35px; }
+#help .infos { padding-left: 0; }
+#help h1, #help h2 { margin-top: 0; }
+#help > div div {
+       width: 50%;
+       float: left;
+       padding: 0 20px 20px 17px;;
+}
+
+.stab {
+       border-width: 1px;
+       border-style: solid;
+       padding: 3px;
+       margin-bottom: 5px;
+       font-size: 90%;
+       font-weight: normal;
+}
+.stab p {
+       display: inline;
+}
+
+.stab .emoji {
+       font-size: 1.5em;
+}
+
+/* Black one-pixel outline around emoji shapes */
+.emoji {
+       text-shadow:
+               1px 0 0 black,
+               -1px 0 0 black,
+               0  1px 0 black,
+               0 -1px 0 black;
+}
+
+.module-item .stab,
+.import-item .stab {
+       border-radius: 3px;
+       display: inline-block;
+       font-size: 80%;
+       line-height: 1.2;
+       margin-bottom: 0;
+       margin-left: .3em;
+       padding: 2px;
+       vertical-align: text-bottom;
+}
+
+.module-item.unstable,
+.import-item.unstable {
+       opacity: 0.65;
+}
+
+.since {
+       font-weight: normal;
+       font-size: initial;
+}
+
+.impl-items .since, .impl .since, .methods .since {
+       padding-left: 12px;
+       padding-right: 2px;
+       position: initial;
+}
+
+.impl-items .srclink, .impl .srclink, .methods .srclink {
+       /* Override header settings otherwise it's too bold */
+       font-size: 17px;
+       font-weight: normal;
+}
+
+.rightside {
+       float: right;
+}
+
+.has-srclink {
+       font-size: 16px;
+       margin-bottom: 12px;
+       /* Push the src link out to the right edge consistently */
+       justify-content: space-between;
+}
+
+.variants_table {
+       width: 100%;
+}
+
+.variants_table tbody tr td:first-child {
+       width: 1%; /* make the variant name as small as possible */
+}
+
+td.summary-column {
+       width: 100%;
+}
+
+.summary {
+       padding-right: 0px;
+}
+
+pre.rust .question-mark {
+       font-weight: bold;
+}
+
+a.test-arrow {
+       display: inline-block;
+       position: absolute;
+       padding: 5px 10px 5px 10px;
+       border-radius: 5px;
+       font-size: 130%;
+       top: 5px;
+       right: 5px;
+       z-index: 1;
+}
+a.test-arrow:hover{
+       text-decoration: none;
+}
+
+.section-header:hover a:before {
+       position: absolute;
+       left: -25px;
+       padding-right: 10px; /* avoid gap that causes hover to disappear */
+       content: '\2002\00a7\2002';
+}
+
+.section-header:hover a {
+       text-decoration: none;
+}
+
+.section-header a {
+       color: inherit;
+}
+
+.code-attribute {
+       font-weight: 300;
+}
+
+.since + .srclink {
+       padding-left: 10px;
+}
+
+.item-spacer {
+       width: 100%;
+       height: 12px;
+}
+
+.out-of-band > span.since {
+       position: initial;
+       font-size: 20px;
+       margin-right: 5px;
+}
+
+.sub-variant, .sub-variant > h3 {
+       margin-top: 0px !important;
+       padding-top: 1px;
+}
+
+#main > details > .sub-variant > h3 {
+       font-size: 15px;
+       margin-left: 25px;
+       margin-bottom: 5px;
+}
+
+.sub-variant > div {
+       margin-left: 20px;
+       margin-bottom: 10px;
+}
+
+.sub-variant > div > span {
+       display: block;
+       position: relative;
+}
+
+.toggle-label {
+       display: inline-block;
+       margin-left: 4px;
+       margin-top: 3px;
+}
+
+.docblock > .section-header:first-child {
+       margin-left: 15px;
+       margin-top: 0;
+}
+
+.docblock > .section-header:first-child:hover > a:before {
+       left: -10px;
+}
+
+:target > code {
+       opacity: 1;
+}
+
+:target {
+       padding-right: 3px;
+}
+
+.information {
+       position: absolute;
+       left: -25px;
+       margin-top: 7px;
+       z-index: 1;
+}
+
+.tooltip {
+       position: relative;
+       display: inline-block;
+       cursor: pointer;
+}
+
+.tooltip::after {
+       display: none;
+       text-align: center;
+       padding: 5px 3px 3px 3px;
+       border-radius: 6px;
+       margin-left: 5px;
+       font-size: 16px;
+}
+
+.tooltip.ignore::after {
+       content: "This example is not tested";
+}
+.tooltip.compile_fail::after {
+       content: "This example deliberately fails to compile";
+}
+.tooltip.should_panic::after {
+       content: "This example panics";
+}
+.tooltip.edition::after {
+       content: "This code runs with edition " attr(data-edition);
+}
+
+.tooltip::before {
+       content: " ";
+       position: absolute;
+       top: 50%;
+       left: 16px;
+       margin-top: -5px;
+       border-width: 5px;
+       border-style: solid;
+       display: none;
+}
+
+.tooltip:hover::before, .tooltip:hover::after {
+       display: inline;
+}
+
+.tooltip.compile_fail, .tooltip.should_panic, .tooltip.ignore {
+       font-weight: bold;
+       font-size: 20px;
+}
+
+.notable-traits-tooltip {
+       display: inline-block;
+       cursor: pointer;
+}
+
+.notable-traits:hover .notable-traits-tooltiptext,
+.notable-traits .notable-traits-tooltiptext.force-tooltip {
+       display: inline-block;
+}
+
+.notable-traits .notable-traits-tooltiptext {
+       display: none;
+       padding: 5px 3px 3px 3px;
+       border-radius: 6px;
+       margin-left: 5px;
+       z-index: 10;
+       font-size: 16px;
+       cursor: default;
+       position: absolute;
+       border: 1px solid;
+}
+
+.notable-traits-tooltip::after {
+       /* The margin on the tooltip does not capture hover events,
+          this extends the area of hover enough so that mouse hover is not
+          lost when moving the mouse to the tooltip */
+       content: "\00a0\00a0\00a0";
+}
+
+.notable-traits .notable, .notable-traits .docblock {
+       margin: 0;
+}
+
+.notable-traits .notable {
+       margin: 0;
+       margin-bottom: 13px;
+       font-size: 19px;
+       font-weight: 600;
+}
+
+.notable-traits .docblock code.content{
+       margin: 0;
+       padding: 0;
+       font-size: 20px;
+}
+
+/* Example code has the "Run" button that needs to be positioned relative to the pre */
+pre.rust.rust-example-rendered {
+       position: relative;
+}
+
+pre.rust {
+       tab-size: 4;
+       -moz-tab-size: 4;
+}
+
+.search-failed {
+       text-align: center;
+       margin-top: 20px;
+       display: none;
+}
+
+.search-failed.active {
+       display: block;
+}
+
+.search-failed > ul {
+       text-align: left;
+       max-width: 570px;
+       margin-left: auto;
+       margin-right: auto;
+}
+
+#titles {
+       height: 35px;
+}
+
+#titles > button {
+       float: left;
+       width: 33.3%;
+       text-align: center;
+       font-size: 18px;
+       cursor: pointer;
+       border: 0;
+       border-top: 2px solid;
+}
+
+#titles > button:not(:last-child) {
+       margin-right: 1px;
+       width: calc(33.3% - 1px);
+}
+
+#titles > button > div.count {
+       display: inline-block;
+       font-size: 16px;
+}
+
+.notable-traits {
+       cursor: pointer;
+       z-index: 2;
+       margin-left: 5px;
+}
+
+#all-types {
+       text-align: center;
+       border: 1px solid;
+       margin: 0 10px;
+       margin-bottom: 10px;
+       display: block;
+       border-radius: 7px;
+}
+#all-types > p {
+       margin: 5px 0;
+}
+
+#sidebar-toggle {
+       position: fixed;
+       top: 30px;
+       left: 300px;
+       z-index: 10;
+       padding: 3px;
+       border-top-right-radius: 3px;
+       border-bottom-right-radius: 3px;
+       cursor: pointer;
+       font-weight: bold;
+       transition: left .5s;
+       font-size: 1.2em;
+       border: 1px solid;
+       border-left: 0;
+}
+#source-sidebar {
+       position: fixed;
+       top: 0;
+       bottom: 0;
+       left: 0;
+       width: 300px;
+       z-index: 1;
+       overflow: auto;
+       transition: left .5s;
+       border-right: 1px solid;
+}
+#source-sidebar > .title {
+       font-size: 1.5em;
+       text-align: center;
+       border-bottom: 1px solid;
+       margin-bottom: 6px;
+}
+
+.theme-picker {
+       position: absolute;
+       left: 211px;
+       top: 19px;
+}
+
+.theme-picker button {
+       outline: none;
+}
+
+#settings-menu, #help-button {
+       position: absolute;
+       top: 10px;
+}
+
+#settings-menu {
+       right: 0;
+       outline: none;
+}
+
+#theme-picker, #settings-menu, #help-button, #copy-path {
+       padding: 4px;
+       width: 27px;
+       height: 29px;
+       border: 1px solid;
+       border-radius: 3px;
+       cursor: pointer;
+}
+
+#help-button {
+       right: 30px;
+       font-family: "Fira Sans", Arial, sans-serif;
+       text-align: center;
+       font-size: 17px;
+       padding-top: 2px;
+}
+
+#copy-path {
+       background: initial;
+       margin-left: 10px;
+       padding: 0;
+       padding-left: 2px;
+       border: 0;
+}
+
+#theme-choices {
+       display: none;
+       position: absolute;
+       left: 0;
+       top: 28px;
+       border: 1px solid;
+       border-radius: 3px;
+       z-index: 1;
+       cursor: pointer;
+}
+
+#theme-choices > button {
+       border: none;
+       width: 100%;
+       padding: 4px 8px;
+       text-align: center;
+       background: rgba(0,0,0,0);
+}
+
+#theme-choices > button:not(:first-child) {
+       border-top: 1px solid;
+}
+
+kbd {
+       display: inline-block;
+       padding: 3px 5px;
+       font: 15px monospace;
+       line-height: 10px;
+       vertical-align: middle;
+       border: solid 1px;
+       border-radius: 3px;
+       box-shadow: inset 0 -1px 0;
+       cursor: default;
+}
+
+.hidden-by-impl-hider,
+.hidden-by-usual-hider {
+       /* important because of conflicting rule for small screens */
+       display: none !important;
+}
+
+#implementations-list > h3 > span.in-band {
+       width: 100%;
+}
+
+.table-display {
+       width: 100%;
+       border: 0;
+       border-collapse: collapse;
+       border-spacing: 0;
+       font-size: 16px;
+}
+
+.table-display tr td:first-child {
+       padding-right: 0;
+}
+
+.table-display tr td:last-child {
+       float: right;
+}
+.table-display .out-of-band {
+       position: relative;
+       font-size: 19px;
+       display: block;
+}
+#implementors-list > .impl-items .table-display .out-of-band {
+       font-size: 17px;
+}
+
+.table-display td:hover .anchor {
+       display: block;
+       top: 2px;
+       left: -5px;
+}
+
+#main > ul {
+       padding-left: 10px;
+}
+#main > ul > li {
+       list-style: none;
+}
+
+.non-exhaustive {
+       margin-bottom: 1em;
+}
+
+div.children {
+       padding-left: 27px;
+       display: none;
+}
+div.name {
+       cursor: pointer;
+       position: relative;
+       margin-left: 16px;
+}
+div.files > a {
+       display: block;
+       padding: 0 3px;
+}
+div.files > a:hover, div.name:hover {
+       background-color: #a14b4b;
+}
+div.name.expand + .children {
+       display: block;
+}
+div.name::before {
+       content: "\25B6";
+       padding-left: 4px;
+       font-size: 0.7em;
+       position: absolute;
+       left: -16px;
+       top: 4px;
+}
+div.name.expand::before {
+       transform: rotate(90deg);
+       left: -15px;
+       top: 2px;
+}
+
+/* The hideme class is used on summary tags that contain a span with
+       placeholder text shown only when the toggle is closed. For instance,
+       "Expand description" or "Show methods". */
+details.rustdoc-toggle > summary.hideme {
+       cursor: pointer;
+}
+
+details.rustdoc-toggle > summary, details.undocumented > summary {
+       list-style: none;
+}
+details.rustdoc-toggle > summary::-webkit-details-marker,
+details.rustdoc-toggle > summary::marker,
+details.undocumented > summary::-webkit-details-marker,
+details.undocumented > summary::marker {
+       display: none;
+}
+
+details.rustdoc-toggle > summary.hideme > span {
+       margin-left: 9px;
+}
+
+details.rustdoc-toggle > summary::before {
+       content: "[+]";
+       font-weight: 300;
+       font-size: 0.8em;
+       letter-spacing: 1px;
+       cursor: pointer;
+}
+
+details.rustdoc-toggle.top-doc > summary,
+details.rustdoc-toggle.top-doc > summary::before,
+details.rustdoc-toggle.non-exhaustive > summary,
+details.rustdoc-toggle.non-exhaustive > summary::before {
+       font-family: 'Fira Sans';
+       font-size: 16px;
+}
+
+details.non-exhaustive {
+       margin-bottom: 8px;
+}
+
+details.rustdoc-toggle > summary.hideme::before {
+       position: relative;
+}
+
+details.rustdoc-toggle > summary:not(.hideme)::before {
+       position: absolute;
+       left: -23px;
+       top: 3px;
+}
+
+.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before,
+.undocumented > details.rustdoc-toggle > summary:not(.hideme)::before {
+       position: absolute;
+       left: -2px;
+}
+
+/* When a "hideme" summary is open and the "Expand description" or "Show
+       methods" text is hidden, we want the [-] toggle that remains to not
+       affect the layout of the items to its right. To do that, we use
+       absolute positioning. Note that we also set position: relative
+       on the parent <details> to make this work properly. */
+details.rustdoc-toggle[open] > summary.hideme {
+       position: absolute;
+}
+
+details.rustdoc-toggle, details.undocumented {
+       position: relative;
+}
+
+details.rustdoc-toggle[open] > summary.hideme > span {
+       display: none;
+}
+
+details.rustdoc-toggle[open] > summary::before {
+       content: "[−]";
+       display: inline;
+}
+
+details.undocumented > summary::before {
+       content: "[+] Show hidden undocumented items";
+       cursor: pointer;
+       font-size: 16px;
+       font-weight: 300;
+}
+
+details.undocumented[open] > summary::before {
+       content: "[−] Hide undocumented items";
+}
+
+/* Media Queries */
+
+@media (min-width: 701px) {
+       /* In case there is no documentation before a code block, we need to add some margin at the top
+       to prevent an overlay between the "collapse toggle" and the information tooltip.
+       However, it's not needed with smaller screen width because the doc/code block is always put
+       "one line" below. */
+       .docblock > .information:first-child > .tooltip {
+               margin-top: 16px;
+       }
+}
+
+@media (max-width: 700px) {
+       body {
+               padding-top: 0px;
+       }
+
+       .rustdoc > .sidebar {
+               height: 45px;
+               min-height: 40px;
+               margin: 0;
+               margin-left: -15px;
+               padding: 0 15px;
+               position: static;
+               z-index: 11;
+       }
+
+       .sidebar > .location {
+               float: right;
+               margin: 0px;
+               margin-top: 2px;
+               padding: 3px 10px 1px 10px;
+               min-height: 39px;
+               background: inherit;
+               text-align: left;
+               font-size: 24px;
+       }
+
+       .sidebar .location:empty {
+               padding: 0;
+       }
+
+       .sidebar .logo-container {
+               width: 35px;
+               height: 35px;
+               margin-top: 5px;
+               margin-bottom: 5px;
+               float: left;
+               margin-left: 50px;
+       }
+
+       .sidebar .logo-container > img {
+               max-width: 35px;
+               max-height: 35px;
+       }
+
+       .sidebar-menu {
+               position: fixed;
+               z-index: 10;
+               font-size: 2rem;
+               cursor: pointer;
+               width: 45px;
+               left: 0;
+               text-align: center;
+               display: block;
+               border-bottom: 1px solid;
+               border-right: 1px solid;
+               height: 45px;
+       }
+
+       .rustdoc.source > .sidebar > .sidebar-menu {
+               display: none;
+       }
+
+       .sidebar-elems {
+               position: fixed;
+               z-index: 1;
+               left: 0;
+               top: 45px;
+               bottom: 0;
+               overflow-y: auto;
+               border-right: 1px solid;
+               display: none;
+       }
+
+       .sidebar > .block.version {
+               overflow: hidden;
+               border-bottom: none;
+               margin-bottom: 0;
+               height: 100%;
+               padding-left: 12px;
+       }
+       .sidebar > .block.version > div.narrow-helper {
+               float: left;
+               width: 1px;
+               height: 100%;
+       }
+       .sidebar > .block.version > p {
+               /* hide Version text if too narrow */
+               margin: 0;
+               min-width: 55px;
+               /* vertically center */
+               display: flex;
+               align-items: center;
+               height: 100%;
+       }
+
+       nav.sub {
+               width: calc(100% - 32px);
+               float: right;
+       }
+
+       .content {
+               margin-left: 0px;
+       }
+
+       #main, #search {
+               margin-top: 45px;
+               padding: 0;
+       }
+
+       #search {
+               margin-left: 0;
+       }
+
+       .anchor {
+               display: none !important;
+       }
+
+       .theme-picker {
+               left: 10px;
+               top: 54px;
+               z-index: 1;
+       }
+
+       .notable-traits {
+               position: absolute;
+               left: -22px;
+               top: 24px;
+       }
+
+       #titles > button > div.count {
+               float: left;
+               width: 100%;
+       }
+
+       #titles {
+               height: 50px;
+       }
+
+       .sidebar.mobile {
+               position: fixed;
+               width: 100%;
+               margin-left: 0;
+               background-color: rgba(0,0,0,0);
+               height: 100%;
+       }
+       /*
+       This allows to prevent the version text to overflow the sidebar title on mobile mode when the
+       sidebar is displayed (after clicking on the "hamburger" button).
+       */
+       .sidebar.mobile > div.version {
+               overflow: hidden;
+               max-height: 33px;
+       }
+       .sidebar {
+               width: calc(100% + 30px);
+       }
+
+       .show-it {
+               display: block;
+               width: 246px;
+       }
+
+       .show-it > .block.items {
+               margin: 8px 0;
+       }
+
+       .show-it > .block.items > ul {
+               margin: 0;
+       }
+
+       .show-it > .block.items > ul > li {
+               text-align: center;
+               margin: 2px 0;
+       }
+
+       .show-it > .block.items > ul > li > a {
+               font-size: 21px;
+       }
+
+       /* Because of ios, we need to actually have a full height sidebar title so the
+        * actual sidebar can show up. But then we need to make it transparent so we don't
+        * hide content. The filler just allows to create the background for the sidebar
+        * title. But because of the absolute position, I had to lower the z-index.
+        */
+       #sidebar-filler {
+               position: fixed;
+               left: 45px;
+               width: calc(100% - 45px);
+               top: 0;
+               height: 45px;
+               z-index: -1;
+               border-bottom: 1px solid;
+       }
+
+       #main > details.rustdoc-toggle > summary::before,
+       #main > div > details.rustdoc-toggle > summary::before {
+               left: -11px;
+       }
+
+       #all-types {
+               margin: 10px;
+       }
+
+       #sidebar-toggle {
+               top: 100px;
+               width: 30px;
+               font-size: 1.5rem;
+               text-align: center;
+               padding: 0;
+       }
+
+       #source-sidebar {
+               z-index: 11;
+       }
+
+       #main > .line-numbers {
+               margin-top: 0;
+       }
+
+       .notable-traits .notable-traits-tooltiptext {
+               left: 0;
+               top: 100%;
+       }
+
+       /* We don't display the help button on mobile devices. */
+       #help-button {
+               display: none;
+       }
+
+       /* Display an alternating layout on tablets and phones */
+       .item-table {
+               display: flex;
+               flex-flow: column wrap;
+       }
+       .item-left, .item-right {
+               width: 100%;
+       }
+
+       .search-container > div {
+               width: calc(100% - 32px);
+       }
+
+       /* Display an alternating layout on tablets and phones */
+       .search-results > a {
+               border-bottom: 1px solid #aaa9;
+               padding: 5px 0px;
+       }
+       .search-results .result-name, .search-results div.desc, .search-results .result-description {
+               width: 100%;
+       }
+       .search-results div.desc, .search-results .result-description, .item-right {
+               padding-left: 2em;
+       }
+}
+
+@media print {
+       nav.sub, .content .out-of-band {
+               display: none;
+       }
+}
+
+@media (max-width: 464px) {
+       #titles, #titles > button {
+               height: 73px;
+       }
+
+       /* This is to prevent the search bar from being underneath the <section>
+        * element following it.
+        */
+       #main, #search {
+               margin-top: 100px;
+       }
+
+       #main > table:not(.table-display) td {
+               word-break: break-word;
+               width: 50%;
+       }
+
+       .search-container > div {
+               display: block;
+               width: calc(100% - 37px);
+       }
+
+       #crate-search {
+               width: 100%;
+               border-radius: 4px;
+               border: 0;
+       }
+
+       #crate-search + .search-input {
+               width: calc(100% + 71px);
+               margin-left: -36px;
+       }
+
+       #theme-picker, #settings-menu {
+               padding: 5px;
+               width: 31px;
+               height: 31px;
+       }
+
+       #theme-picker {
+               margin-top: -2px;
+       }
+
+       #settings-menu {
+               top: 7px;
+       }
+
+       .docblock {
+               margin-left: 12px;
+       }
+}
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
new file mode 100644 (file)
index 0000000..fb8990b
--- /dev/null
@@ -0,0 +1,107 @@
+.setting-line {
+       padding: 5px;
+       position: relative;
+}
+
+.setting-line > div {
+       display: inline-block;
+       vertical-align: top;
+       font-size: 17px;
+       padding-top: 2px;
+}
+
+.setting-line > .title {
+       font-size: 19px;
+       width: 100%;
+       max-width: none;
+       border-bottom: 1px solid;
+}
+
+.toggle {
+       position: relative;
+       display: inline-block;
+       width: 45px;
+       height: 27px;
+       margin-right: 20px;
+}
+
+.toggle input {
+       opacity: 0;
+       position: absolute;
+}
+
+.select-wrapper {
+       float: right;
+       position: relative;
+       height: 27px;
+       min-width: 25%;
+}
+
+.select-wrapper select {
+       appearance: none;
+       -moz-appearance: none;
+       -webkit-appearance: none;
+       background: none;
+       border: 2px solid #ccc;
+       padding-right: 28px;
+       width: 100%;
+}
+
+.select-wrapper img {
+       pointer-events: none;
+       position: absolute;
+       right: 0;
+       bottom: 0;
+       background: #ccc;
+       height: 100%;
+       width: 28px;
+       padding: 0px 4px;
+}
+
+.select-wrapper select option {
+       color: initial;
+}
+
+.slider {
+       position: absolute;
+       cursor: pointer;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+       background-color: #ccc;
+       -webkit-transition: .3s;
+       transition: .3s;
+}
+
+.slider:before {
+       position: absolute;
+       content: "";
+       height: 19px;
+       width: 19px;
+       left: 4px;
+       bottom: 4px;
+       background-color: white;
+       -webkit-transition: .3s;
+       transition: .3s;
+}
+
+input:checked + .slider {
+       background-color: #2196F3;
+}
+
+input:focus + .slider {
+       box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
+}
+
+input:checked + .slider:before {
+       -webkit-transform: translateX(19px);
+       -ms-transform: translateX(19px);
+       transform: translateX(19px);
+}
+
+.setting-line > .sub-settings {
+       padding-left: 42px;
+       width: 100%;
+       display: block;
+}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
new file mode 100644 (file)
index 0000000..171d06c
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+Based off of the Ayu theme
+Original by Dempfi (https://github.com/dempfi/ayu)
+*/
+
+/* General structure and fonts */
+
+body {
+       background-color: #0f1419;
+       color: #c5c5c5;
+}
+
+h1, h2, h3, h4 {
+       color: white;
+}
+h1.fqn {
+       border-bottom-color: #5c6773;
+}
+h1.fqn  a {
+       color: #fff;
+}
+h2, h3, h4 {
+       border-bottom-color: #5c6773;
+}
+h4 {
+       border: none;
+}
+
+.in-band {
+       background-color: #0f1419;
+}
+
+.invisible {
+       background: rgba(0, 0, 0, 0);
+}
+
+code {
+       color: #ffb454;
+}
+h3 > code, h4 > code, h5 > code {
+       color: #e6e1cf;
+}
+pre > code {
+       color: #e6e1cf;
+}
+span code {
+       color: #e6e1cf;
+}
+.docblock a > code {
+       color: #39AFD7 !important;
+}
+.docblock code, .docblock-short code {
+       background-color: #191f26;
+}
+pre, .rustdoc.source .example-wrap {
+       color: #e6e1cf;
+       background-color: #191f26;
+}
+
+.sidebar {
+       background-color: #14191f;
+}
+
+.logo-container.rust-logo > img {
+       filter: drop-shadow(1px 0 0px #fff)
+               drop-shadow(0 1px 0 #fff)
+               drop-shadow(-1px 0 0 #fff)
+               drop-shadow(0 -1px 0 #fff);
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+       scrollbar-color: #5c6773 transparent;
+}
+
+.sidebar {
+       scrollbar-color: #5c6773 transparent;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+       background-color: transparent;
+}
+::-webkit-scrollbar-thumb {
+       background-color: #5c6773;
+}
+.sidebar::-webkit-scrollbar-track {
+       background-color: transparent;
+}
+.sidebar::-webkit-scrollbar-thumb {
+       background-color: #5c6773;
+}
+
+.sidebar .current {
+       background-color: transparent;
+       color: #ffb44c;
+}
+
+.source .sidebar {
+       background-color: #0f1419;
+}
+
+.sidebar .location {
+       border-color: #000;
+       background-color: #0f1419;
+       color: #fff;
+}
+
+.sidebar-elems .location {
+       color: #ff7733;
+}
+
+.sidebar-elems .location a {
+       color: #fff;
+}
+
+.sidebar .version {
+       border-bottom-color: #424c57;
+}
+
+.sidebar-title {
+       border-top-color: #5c6773;
+       border-bottom-color: #5c6773;
+}
+
+.block a:hover {
+       background: transparent;
+       color: #ffb44c;
+}
+
+.line-numbers span { color: #5c6773; }
+.line-numbers .line-highlighted {
+       color: #708090;
+       background-color: rgba(255, 236, 164, 0.06);
+       padding-right: 4px;
+       border-right: 1px solid #ffb44c;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+       border-bottom-color: #5c6773;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+       border-color: #5c6773;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+       color: #c5c5c5;
+}
+
+.search-results a:hover {
+       background-color: #777;
+}
+
+.search-results a:focus {
+       color: #000 !important;
+       background-color: #c6afb3;
+}
+.search-results a {
+       color: #0096cf;
+}
+.search-results a span.desc {
+       color: #c5c5c5;
+}
+
+.content .item-info::before { color: #ccc; }
+
+.content span.foreigntype, .content a.foreigntype { color: #ef57ff; }
+.content span.union, .content a.union { color: #98a01c; }
+.content span.constant, .content a.constant,
+.content span.static, .content a.static { color: #6380a0; }
+.content span.primitive, .content a.primitive { color: #32889b; }
+.content span.traitalias, .content a.traitalias { color: #57d399; }
+.content span.keyword, .content a.keyword { color: #de5249; }
+
+.content span.externcrate, .content span.mod, .content a.mod {
+       color: #acccf9;
+}
+.content span.struct, .content a.struct {
+       color: #ffa0a5;
+}
+.content span.enum, .content a.enum {
+       color: #99e0c9;
+}
+.content span.trait, .content a.trait {
+       color: #39AFD7;
+}
+.content span.type, .content a.type {
+       color: #cfbcf5;
+}
+.content span.fn, .content a.fn, .content span.method,
+.content a.method, .content span.tymethod,
+.content a.tymethod, .content .fnname {
+       color: #fdd687;
+}
+.content span.attr, .content a.attr, .content span.derive,
+.content a.derive, .content span.macro, .content a.macro {
+       color: #a37acc;
+}
+
+pre.rust .comment { color: #788797; }
+pre.rust .doccomment { color: #a1ac88; }
+
+nav:not(.sidebar) {
+       border-bottom-color: #424c57;
+}
+nav.main .current {
+       border-top-color: #5c6773;
+       border-bottom-color: #5c6773;
+}
+nav.main .separator {
+       border: 1px solid #5c6773;
+}
+a {
+       color: #c5c5c5;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
+#help a {
+       color: #39AFD7;
+}
+
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+       color: #999;
+}
+
+#crate-search {
+       color: #c5c5c5;
+       background-color: #141920;
+       box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
+       border-color: #424c57;
+}
+
+.search-input {
+       color: #ffffff;
+       background-color: #141920;
+       box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
+       transition: box-shadow 150ms ease-in-out;
+}
+
+#crate-search+.search-input:focus {
+       box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
+}
+
+.search-input:disabled {
+       background-color: #3e3e3e;
+}
+
+.module-item .stab,
+.import-item .stab {
+       color: #000;
+}
+
+.stab.unstable,
+.stab.deprecated,
+.stab.portability {
+       color: #c5c5c5;
+       background: #314559 !important;
+       border-style: none !important;
+       border-radius: 4px;
+       padding: 3px 6px 3px 6px;
+}
+
+.stab.portability > code {
+       color: #e6e1cf;
+       background: none;
+}
+
+#help > div {
+       background: #14191f;
+       box-shadow: 0px 6px 20px 0px black;
+       border: none;
+       border-radius: 4px;
+}
+
+#help > div > span {
+       border-bottom-color: #5c6773;
+}
+
+.since {
+       color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+       color: #788797;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .number, pre.rust .string { color: #b8cc52; }
+pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty,
+pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .op, pre.rust .lifetime { color: #ff7733; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; }
+pre.rust .question-mark {
+       color: #ff9011;
+}
+pre.rust .self {
+       color: #36a3d9;
+       font-style: italic;
+}
+pre.rust .attribute {
+       color: #e6e1cf;
+}
+pre.rust .attribute .ident, pre.rust .attribute .op {
+       color: #e6e1cf;
+}
+
+.example-wrap > pre.line-number {
+       color: #5c67736e;
+       border: none;
+}
+
+a.test-arrow {
+       font-size: 100%;
+       color: #788797;
+       border-radius: 4px;
+       background-color: rgba(57, 175, 215, 0.09);
+}
+
+a.test-arrow:hover {
+       background-color: rgba(57, 175, 215, 0.368);
+       color: #c5c5c5;
+}
+
+.toggle-label,
+.code-attribute {
+       color: #999;
+}
+
+:target, :target * {
+       background: rgba(255, 236, 164, 0.06);
+}
+
+:target {
+       border-right: 3px solid rgba(255, 180, 76, 0.85);
+}
+
+pre.compile_fail {
+       border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+       border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+       border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+       border-left: 2px solid #f00;
+}
+
+pre.ignore {
+       border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+       border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+       color: rgba(255,0,0,.5);
+}
+
+.information > .compile_fail:hover {
+       color: #f00;
+}
+
+.tooltip.should_panic {
+       color: rgba(255,0,0,.5);
+}
+
+.information > .should_panic:hover {
+       color: #f00;
+}
+
+.tooltip.ignore {
+       color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+       color: #ff9200;
+}
+
+.search-failed a {
+       color: #39AFD7;
+}
+
+.tooltip::after {
+       background-color: #314559;
+       color: #c5c5c5;
+       border: 1px solid #5c6773;
+}
+
+.tooltip::before {
+       border-color: transparent #314559 transparent transparent;
+}
+
+.notable-traits-tooltiptext {
+       background-color: #314559;
+       border-color: #5c6773;
+}
+
+.notable-traits-tooltiptext .notable {
+       border-bottom-color: #5c6773;
+}
+
+#titles > button.selected {
+       background-color: #141920 !important;
+       border-bottom: 1px solid #ffb44c !important;
+       border-top: none;
+}
+
+#titles > button:not(.selected) {
+       background-color: transparent !important;
+       border: none;
+}
+
+#titles > button:hover {
+       border-bottom: 1px solid rgba(242, 151, 24, 0.3);
+}
+
+#titles > button > div.count {
+       color: #888;
+}
+
+/* rules that this theme does not need to set, here to satisfy the rule checker */
+/* note that a lot of these are partially set in some way (meaning they are set
+individually rather than as a group) */
+/* FIXME: these rules should be at the bottom of the file but currently must be
+above the `@media (max-width: 700px)` rules due to a bug in the css checker */
+/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
+.search-input:focus {}
+.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
+.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
+.content span.struct,.content a.struct,.block a.current.struct {}
+#titles>button:hover,#titles>button.selected {}
+.content span.type,.content a.type,.block a.current.type {}
+.content span.union,.content a.union,.block a.current.union {}
+pre.rust .lifetime {}
+.stab.unstable {}
+h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod) {}
+.content span.enum,.content a.enum,.block a.current.enum {}
+.content span.constant,.content a.constant,.block a.current.constant,.content span.static,
+.content a.static, .block a.current.static {}
+.content span.keyword,.content a.keyword,.block a.current.keyword {}
+pre.rust .comment {}
+.content span.traitalias,.content a.traitalias,.block a.current.traitalias {}
+.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,
+.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,
+.content .fnname {}
+pre.rust .kw {}
+pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,
+pre.rust .attribute .ident {}
+.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype {}
+pre.rust .doccomment {}
+.stab.deprecated {}
+.content a.attr,.content a.derive,.content a.macro {}
+.stab.portability {}
+.content span.primitive,.content a.primitive,.block a.current.primitive {}
+.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod {}
+pre.rust .kw-2,pre.rust .prelude-ty {}
+.content span.trait,.content a.trait,.block a.current.trait {}
+
+.search-results a:focus span {}
+a.result-trait:focus {}
+a.result-traitalias:focus {}
+a.result-mod:focus,
+a.result-externcrate:focus {}
+a.result-mod:focus {}
+a.result-externcrate:focus {}
+a.result-enum:focus {}
+a.result-struct:focus {}
+a.result-union:focus {}
+a.result-fn:focus,
+a.result-method:focus,
+a.result-tymethod:focus {}
+a.result-type:focus {}
+a.result-foreigntype:focus {}
+a.result-attr:focus,
+a.result-derive:focus,
+a.result-macro:focus {}
+a.result-constant:focus,
+a.result-static:focus {}
+a.result-primitive:focus {}
+a.result-keyword:focus {}
+
+@media (max-width: 700px) {
+       .sidebar-menu {
+               background-color: #14191f;
+               border-bottom-color: #5c6773;
+               border-right-color: #5c6773;
+       }
+
+       .sidebar-elems {
+               background-color: #14191f;
+               border-right-color: #5c6773;
+       }
+
+       #sidebar-filler {
+               background-color: #14191f;
+               border-bottom-color: #5c6773;
+       }
+}
+
+kbd {
+       color: #c5c5c5;
+       background-color: #314559;
+       border-color: #5c6773;
+       border-bottom-color: #5c6773;
+       box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu, #help-button {
+       border-color: #5c6773;
+       background-color: #0f1419;
+       color: #fff;
+}
+
+#theme-picker > img, #settings-menu > img {
+       filter: invert(100);
+}
+
+#copy-path {
+       color: #fff;
+}
+#copy-path > img {
+       filter: invert(70%);
+}
+#copy-path:hover > img {
+       filter: invert(100%);
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus,
+#help-button:hover, #help-button:focus {
+       border-color: #e0e0e0;
+}
+
+#theme-choices {
+       border-color: #5c6773;
+       background-color: #0f1419;
+}
+
+#theme-choices > button:not(:first-child) {
+       border-top-color: #5c6773;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+       background-color: rgba(110, 110, 110, 0.33);
+}
+
+@media (max-width: 700px) {
+       #theme-picker {
+               background: #0f1419;
+       }
+}
+
+#all-types {
+       background-color: #14191f;
+}
+#all-types:hover {
+       background-color: rgba(70, 70, 70, 0.33);
+}
+
+.search-results .result-name span.alias {
+       color: #c5c5c5;
+}
+.search-results .result-name span.grey {
+       color: #999;
+}
+
+#sidebar-toggle {
+       background-color: #14191f;
+}
+#sidebar-toggle:hover {
+       background-color: rgba(70, 70, 70, 0.33);
+}
+#source-sidebar {
+       background-color: #14191f;
+}
+#source-sidebar > .title {
+       color: #fff;
+       border-bottom-color: #5c6773;
+}
+div.files > a:hover, div.name:hover {
+       background-color: #14191f;
+       color: #ffb44c;
+}
+div.files > .selected {
+       background-color: #14191f;
+       color: #ffb44c;
+}
+.setting-line > .title {
+       border-bottom-color: #5c6773;
+}
+input:checked + .slider {
+       background-color: #ffb454 !important;
+}
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
new file mode 100644 (file)
index 0000000..d9ea280
--- /dev/null
@@ -0,0 +1,479 @@
+body {
+       background-color: #353535;
+       color: #ddd;
+}
+
+h1, h2, h3, h4 {
+       color: #ddd;
+}
+h1.fqn {
+       border-bottom-color: #d2d2d2;
+}
+h2, h3, h4 {
+       border-bottom-color: #d2d2d2;
+}
+
+.in-band {
+       background-color: #353535;
+}
+
+.invisible {
+       background: rgba(0, 0, 0, 0);
+}
+
+.docblock code, .docblock-short code {
+       background-color: #2A2A2A;
+}
+pre, .rustdoc.source .example-wrap {
+       background-color: #2A2A2A;
+}
+
+.sidebar {
+       background-color: #505050;
+}
+
+.logo-container.rust-logo > img {
+       filter: drop-shadow(1px 0 0px #fff)
+               drop-shadow(0 1px 0 #fff)
+               drop-shadow(-1px 0 0 #fff)
+               drop-shadow(0 -1px 0 #fff)
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+       scrollbar-color: rgb(64, 65, 67) #717171;
+}
+.sidebar {
+       scrollbar-color: rgba(32,34,37,.6) transparent;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+       background-color: #717171;
+}
+::-webkit-scrollbar-thumb {
+       background-color: rgba(32, 34, 37, .6);
+}
+.sidebar::-webkit-scrollbar-track {
+       background-color: #717171;
+}
+.sidebar::-webkit-scrollbar-thumb {
+       background-color: rgba(32, 34, 37, .6);
+}
+
+.sidebar .current {
+       background-color: #333;
+}
+
+.source .sidebar {
+       background-color: #353535;
+}
+
+.sidebar .location {
+       border-color: #fff;
+       background: #575757;
+       color: #DDD;
+}
+
+.sidebar .version {
+       border-bottom-color: #DDD;
+}
+
+.sidebar-title {
+       border-top-color: #777;
+       border-bottom-color: #777;
+}
+
+.block a:hover {
+       background: #444;
+}
+
+.line-numbers span { color: #3B91E2; }
+.line-numbers .line-highlighted {
+       background-color: #0a042f !important;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+       border-bottom-color: #DDD;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+       border-color: #ddd;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+       color: #ddd;
+}
+
+.search-results a:hover {
+       background-color: #777;
+}
+
+.search-results a:focus {
+       color: #eee !important;
+       background-color: #616161;
+}
+.search-results a:focus span { color: #eee !important; }
+a.result-trait:focus { background-color: #013191; }
+a.result-traitalias:focus { background-color: #013191; }
+a.result-mod:focus,
+a.result-externcrate:focus { background-color: #afc6e4; }
+a.result-mod:focus { background-color: #803a1b; }
+a.result-externcrate:focus { background-color: #396bac; }
+a.result-enum:focus { background-color: #5b4e68; }
+a.result-struct:focus { background-color: #194e9f; }
+a.result-union:focus { background-color: #b7bd49; }
+a.result-fn:focus,
+a.result-method:focus,
+a.result-tymethod:focus { background-color: #4950ed; }
+a.result-type:focus { background-color: #38902c; }
+a.result-foreigntype:focus { background-color: #b200d6; }
+a.result-attr:focus,
+a.result-derive:focus,
+a.result-macro:focus { background-color: #217d1c; }
+a.result-constant:focus,
+a.result-static:focus { background-color: #0063cc; }
+a.result-primitive:focus { background-color: #00708a; }
+a.result-keyword:focus { background-color: #884719; }
+
+.content .item-info::before { color: #ccc; }
+
+.content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
+.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
+.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
+.content span.attr, .content a.attr, .block a.current.attr,
+.content span.derive, .content a.derive, .block a.current.derive,
+.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
+.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
+.content span.constant, .content a.constant, .block a.current.constant,
+.content span.static, .content a.static, .block a.current.static { color: #82a5c9; }
+.content span.primitive, .content a.primitive, .block a.current.primitive { color: #43aec7; }
+.content span.externcrate,
+.content span.mod, .content a.mod, .block a.current.mod { color: #bda000; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #b78cf2; }
+.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #b397da; }
+.content span.fn, .content a.fn, .block a.current.fn,
+.content span.method, .content a.method, .block a.current.method,
+.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
+.content .fnname{ color: #2BAB63; }
+.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
+
+pre.rust .comment { color: #8d8d8b; }
+pre.rust .doccomment { color: #8ca375; }
+
+nav:not(.sidebar) {
+       border-bottom-color: #4e4e4e;
+}
+nav.main .current {
+       border-top-color: #eee;
+       border-bottom-color: #eee;
+}
+nav.main .separator {
+       border-color: #eee;
+}
+a {
+       color: #ddd;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
+#help a {
+       color: #D2991D;
+}
+
+a.test-arrow {
+       color: #dedede;
+}
+
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+       color: #999;
+}
+
+#crate-search {
+       color: #111;
+       background-color: #f0f0f0;
+       border-color: #000;
+       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
+}
+
+.search-input {
+       color: #111;
+       background-color: #f0f0f0;
+       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
+}
+
+.search-input:focus {
+       border-color: #008dfd;
+}
+
+.search-input:disabled {
+       background-color: #c5c4c4;
+}
+
+#crate-search + .search-input:focus {
+       box-shadow: 0 0 8px 4px #078dd8;
+}
+
+.module-item .stab,
+.import-item .stab {
+       color: #ddd;
+}
+
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
+.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
+.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
+.stab.portability > code { background: none; }
+
+#help > div {
+       background: #4d4d4d;
+       border-color: #bfbfbf;
+}
+
+#help > div > span {
+       border-bottom-color: #bfbfbf;
+}
+
+#help dt {
+       border-color: #bfbfbf;
+       background: rgba(0,0,0,0);
+}
+
+.since {
+       color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+       color: #ddd;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .kw { color: #ab8ac1; }
+pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; }
+pre.rust .number, pre.rust .string { color: #83a300; }
+pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .attribute, pre.rust .attribute .ident { color: #ee6868; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
+pre.rust .lifetime { color: #d97f26; }
+pre.rust .question-mark {
+       color: #ff9011;
+}
+
+.example-wrap > pre.line-number {
+       border-color: #4a4949;
+}
+
+a.test-arrow {
+       background-color: rgba(78, 139, 202, 0.2);
+}
+
+a.test-arrow:hover{
+       background-color: #4e8bca;
+}
+
+.toggle-label,
+.code-attribute {
+       color: #999;
+}
+
+:target, :target * {
+       background-color: #494a3d;
+}
+
+:target {
+       border-right: 3px solid #bb7410;
+}
+
+pre.compile_fail {
+       border-left: 2px solid rgba(255,0,0,.8);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+       border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+       border-left: 2px solid rgba(255,0,0,.8);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+       border-left: 2px solid #f00;
+}
+
+pre.ignore {
+       border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+       border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+       color: rgba(255,0,0,.8);
+}
+
+.information > .compile_fail:hover {
+       color: #f00;
+}
+
+.tooltip.should_panic {
+       color: rgba(255,0,0,.8);
+}
+
+.information > .should_panic:hover {
+       color: #f00;
+}
+
+.tooltip.ignore {
+       color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+       color: #ff9200;
+}
+
+.search-failed a {
+       color: #0089ff;
+}
+
+.tooltip::after {
+       background-color: #000;
+       color: #fff;
+       border-color: #000;
+}
+
+.tooltip::before {
+       border-color: transparent black transparent transparent;
+}
+
+.notable-traits-tooltiptext {
+       background-color: #111;
+       border-color: #777;
+}
+
+.notable-traits-tooltiptext .notable {
+       border-bottom-color: #d2d2d2;
+}
+
+#titles > button:not(.selected) {
+       background-color: #252525;
+       border-top-color: #252525;
+}
+
+#titles > button:hover, #titles > button.selected {
+       border-top-color: #0089ff;
+       background-color: #353535;
+}
+
+#titles > button > div.count {
+       color: #888;
+}
+
+@media (max-width: 700px) {
+       .sidebar-menu {
+               background-color: #505050;
+               border-bottom-color: #e0e0e0;
+               border-right-color: #e0e0e0;
+       }
+
+       .sidebar-elems {
+               background-color: #505050;
+               border-right-color: #000;
+       }
+
+       #sidebar-filler {
+               background-color: #505050;
+               border-bottom-color: #e0e0e0;
+       }
+}
+
+kbd {
+       color: #000;
+       background-color: #fafbfc;
+       border-color: #d1d5da;
+       border-bottom-color: #c6cbd1;
+       box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu, #help-button {
+       border-color: #e0e0e0;
+       background: #f0f0f0;
+       color: #000;
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus,
+#help-button:hover, #help-button:focus {
+       border-color: #ffb900;
+}
+
+#copy-path {
+       color: #999;
+}
+#copy-path > img {
+       filter: invert(50%);
+}
+#copy-path:hover > img {
+       filter: invert(65%);
+}
+
+#theme-choices {
+       border-color: #e0e0e0;
+       background-color: #353535;
+}
+
+#theme-choices > button:not(:first-child) {
+       border-top-color: #e0e0e0;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+       background-color: #4e4e4e;
+}
+
+@media (max-width: 700px) {
+       #theme-picker {
+               background: #f0f0f0;
+       }
+}
+
+#all-types {
+       background-color: #505050;
+}
+#all-types:hover {
+       background-color: #606060;
+}
+
+.search-results .result-name span.alias {
+       color: #fff;
+}
+.search-results .result-name span.grey {
+       color: #ccc;
+}
+
+#sidebar-toggle {
+       background-color: #565656;
+}
+#sidebar-toggle:hover {
+       background-color: #676767;
+}
+#source-sidebar {
+       background-color: #565656;
+}
+#source-sidebar > .title {
+       border-bottom-color: #ccc;
+}
+div.files > a:hover, div.name:hover {
+       background-color: #444;
+}
+div.files > .selected {
+       background-color: #333;
+}
+.setting-line > .title {
+       border-bottom-color: #ddd;
+}
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
new file mode 100644 (file)
index 0000000..6785b79
--- /dev/null
@@ -0,0 +1,469 @@
+/* General structure and fonts */
+
+body {
+       background-color: white;
+       color: black;
+}
+
+h1, h2, h3, h4 {
+       color: black;
+}
+h1.fqn {
+       border-bottom-color: #D5D5D5;
+}
+h2, h3, h4 {
+       border-bottom-color: #DDDDDD;
+}
+
+.in-band {
+       background-color: white;
+}
+
+.invisible {
+       background: rgba(0, 0, 0, 0);
+}
+
+.docblock code, .docblock-short code {
+       background-color: #F5F5F5;
+}
+pre, .rustdoc.source .example-wrap {
+       background-color: #F5F5F5;
+}
+
+.sidebar {
+       background-color: #F1F1F1;
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+       scrollbar-color: rgba(36, 37, 39, 0.6) #e6e6e6;
+}
+
+.sidebar {
+       scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9;
+}
+
+.logo-container.rust-logo > img {
+       /* No need for a border in here! */
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+       background-color: #ecebeb;
+}
+::-webkit-scrollbar-thumb {
+       background-color: rgba(36, 37, 39, 0.6);
+}
+.sidebar::-webkit-scrollbar-track {
+       background-color: #dcdcdc;
+}
+.sidebar::-webkit-scrollbar-thumb {
+       background-color: rgba(36, 37, 39, 0.6);
+}
+
+.sidebar .current {
+       background-color: #fff;
+}
+
+.source .sidebar {
+       background-color: #fff;
+}
+
+.sidebar .location {
+       border-color: #000;
+       background-color: #fff;
+       color: #333;
+}
+
+.sidebar .version {
+       border-bottom-color: #DDD;
+}
+
+.sidebar-title {
+       border-top-color: #777;
+       border-bottom-color: #777;
+}
+
+.block a:hover {
+       background: #F5F5F5;
+}
+
+.line-numbers span { color: #c67e2d; }
+.line-numbers .line-highlighted {
+       background-color: #f6fdb0 !important;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+       border-bottom-color: #ddd;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+       border-color: #ddd;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+       color: #4E4C4C;
+}
+
+.search-results a:hover {
+       background-color: #ddd;
+}
+
+.search-results a:focus {
+       color: #000 !important;
+       background-color: #ccc;
+}
+.search-results a:focus span { color: #000 !important; }
+a.result-trait:focus { background-color: #c7b6ff; }
+a.result-traitalias:focus { background-color: #c7b6ff; }
+a.result-mod:focus,
+a.result-externcrate:focus { background-color: #afc6e4; }
+a.result-enum:focus { background-color: #b4d1b9; }
+a.result-struct:focus { background-color: #e7b1a0; }
+a.result-union:focus { background-color: #b7bd49; }
+a.result-fn:focus,
+a.result-method:focus,
+a.result-tymethod:focus { background-color: #c6afb3; }
+a.result-type:focus { background-color: #ffc891; }
+a.result-foreigntype:focus { background-color: #f5c4ff; }
+a.result-attr:focus,
+a.result-derive:focus,
+a.result-macro:focus { background-color: #8ce488; }
+a.result-constant:focus,
+a.result-static:focus { background-color: #c3e0ff; }
+a.result-primitive:focus { background-color: #9aecff; }
+a.result-keyword:focus { background-color: #f99650; }
+
+.content .item-info::before { color: #ccc; }
+
+.content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
+.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
+.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
+.content span.attr, .content a.attr, .block a.current.attr,
+.content span.derive, .content a.derive, .block a.current.derive,
+.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
+.content span.union, .content a.union, .block a.current.union { color: #767b27; }
+.content span.constant, .content a.constant, .block a.current.constant,
+.content span.static, .content a.static, .block a.current.static { color: #546e8a; }
+.content span.primitive, .content a.primitive, .block a.current.primitive { color: #2c8093; }
+.content span.externcrate,
+.content span.mod, .content a.mod, .block a.current.mod { color: #4d76ae; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
+.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #6841f1; }
+.content span.fn, .content a.fn, .block a.current.fn,
+.content span.method, .content a.method, .block a.current.method,
+.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
+.content .fnname { color: #9a6e31; }
+.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
+
+nav:not(.sidebar) {
+       border-bottom-color: #e0e0e0;
+}
+nav.main .current {
+       border-top-color: #000;
+       border-bottom-color: #000;
+}
+nav.main .separator {
+       border: 1px solid #000;
+}
+a {
+       color: #000;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
+#help a {
+       color: #3873AD;
+}
+
+a.test-arrow {
+       color: #f5f5f5;
+}
+
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+       color: #999;
+}
+
+#crate-search {
+       color: #555;
+       background-color: white;
+       border-color: #e0e0e0;
+       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+}
+
+.search-input {
+       color: #555;
+       background-color: white;
+       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+}
+
+.search-input:focus {
+       border-color: #66afe9;
+}
+
+.search-input:disabled {
+       background-color: #e6e6e6;
+}
+
+#crate-search + .search-input:focus {
+       box-shadow: 0 0 8px #078dd8;
+}
+
+.module-item .stab,
+.import-item .stab {
+       color: #000;
+}
+
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
+.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
+.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
+.stab.portability > code { background: none; }
+
+#help > div {
+       background: #e9e9e9;
+       border-color: #bfbfbf;
+}
+
+#help > div > span {
+       border-bottom-color: #bfbfbf;
+}
+
+.since {
+       color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+       color: black;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .kw { color: #8959A8; }
+pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
+pre.rust .number, pre.rust .string { color: #718C00; }
+pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
+pre.rust .comment { color: #8E908C; }
+pre.rust .doccomment { color: #4D4D4C; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
+pre.rust .lifetime { color: #B76514; }
+pre.rust .question-mark {
+       color: #ff9011;
+}
+
+.example-wrap > pre.line-number {
+       border-color: #c7c7c7;
+}
+
+a.test-arrow {
+       background-color: rgba(78, 139, 202, 0.2);
+}
+
+a.test-arrow:hover{
+       background-color: #4e8bca;
+}
+
+.toggle-label,
+.code-attribute {
+       color: #999;
+}
+
+:target, :target * {
+       background: #FDFFD3;
+}
+
+:target {
+       border-right: 3px solid #ffb44c;
+}
+
+pre.compile_fail {
+       border-left: 2px solid rgba(255,0,0,.5);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+       border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+       border-left: 2px solid rgba(255,0,0,.5);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+       border-left: 2px solid #f00;
+}
+
+pre.ignore {
+       border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+       border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+       color: rgba(255,0,0,.5);
+}
+
+.information > .compile_fail:hover {
+       color: #f00;
+}
+
+.tooltip.should_panic {
+       color: rgba(255,0,0,.5);
+}
+
+.information > .should_panic:hover {
+       color: #f00;
+}
+
+.tooltip.ignore {
+       color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+       color: #ff9200;
+}
+
+.search-failed a {
+       color: #0089ff;
+}
+
+.tooltip::after {
+       background-color: #000;
+       color: #fff;
+}
+
+.tooltip::before {
+       border-color: transparent black transparent transparent;
+}
+
+.notable-traits-tooltiptext {
+       background-color: #eee;
+       border-color: #999;
+}
+
+.notable-traits-tooltiptext .notable {
+       border-bottom-color: #DDDDDD;
+}
+
+#titles > button:not(.selected) {
+       background-color: #e6e6e6;
+       border-top-color: #e6e6e6;
+}
+
+#titles > button:hover, #titles > button.selected {
+       background-color: #ffffff;
+       border-top-color: #0089ff;
+}
+
+#titles > button > div.count {
+       color: #888;
+}
+
+@media (max-width: 700px) {
+       .sidebar-menu {
+               background-color: #F1F1F1;
+               border-bottom-color: #e0e0e0;
+               border-right-color: #e0e0e0;
+       }
+
+       .sidebar-elems {
+               background-color: #F1F1F1;
+               border-right-color: #000;
+       }
+
+       #sidebar-filler {
+               background-color: #F1F1F1;
+               border-bottom-color: #e0e0e0;
+       }
+}
+
+kbd {
+       color: #000;
+       background-color: #fafbfc;
+       border-color: #d1d5da;
+       border-bottom-color: #c6cbd1;
+       box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu, #help-button {
+       border-color: #e0e0e0;
+       background-color: #fff;
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus,
+#help-button:hover, #help-button:focus {
+       border-color: #717171;
+}
+
+#copy-path {
+       color: #999;
+}
+#copy-path > img {
+       filter: invert(50%);
+}
+#copy-path:hover > img {
+       filter: invert(35%);
+}
+
+#theme-choices {
+       border-color: #ccc;
+       background-color: #fff;
+}
+
+#theme-choices > button:not(:first-child) {
+       border-top-color: #e0e0e0;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+       background-color: #eee;
+}
+
+@media (max-width: 700px) {
+       #theme-picker {
+               background: #fff;
+       }
+}
+
+#all-types {
+       background-color: #fff;
+}
+#all-types:hover {
+       background-color: #f9f9f9;
+}
+
+.search-results .result-name span.alias {
+       color: #000;
+}
+.search-results .result-name span.grey {
+       color: #999;
+}
+
+#sidebar-toggle {
+       background-color: #F1F1F1;
+}
+#sidebar-toggle:hover {
+       background-color: #E0E0E0;
+}
+#source-sidebar {
+       background-color: #F1F1F1;
+}
+#source-sidebar > .title {
+       border-bottom-color: #ccc;
+}
+div.files > a:hover, div.name:hover {
+       background-color: #E0E0E0;
+}
+div.files > .selected {
+       background-color: #fff;
+}
+.setting-line > .title {
+       border-bottom-color: #D5D5D5;
+}
diff --git a/src/librustdoc/html/static/down-arrow.svg b/src/librustdoc/html/static/down-arrow.svg
deleted file mode 100644 (file)
index 35437e7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/favicon-16x16.png b/src/librustdoc/html/static/favicon-16x16.png
deleted file mode 100644 (file)
index 7cfe6c1..0000000
Binary files a/src/librustdoc/html/static/favicon-16x16.png and /dev/null differ
diff --git a/src/librustdoc/html/static/favicon-32x32.png b/src/librustdoc/html/static/favicon-32x32.png
deleted file mode 100644 (file)
index 5109c1d..0000000
Binary files a/src/librustdoc/html/static/favicon-32x32.png and /dev/null differ
diff --git a/src/librustdoc/html/static/favicon.svg b/src/librustdoc/html/static/favicon.svg
deleted file mode 100644 (file)
index 8b34b51..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;">
-<defs>
-  <style type="text/css"><![CDATA[
-    #logo {
-      fill-rule: nonzero;
-    }
-    #logo-teeth {
-      stroke: #000000;
-      stroke-width: 0.92px;
-    }
-    @media (prefers-color-scheme: dark) {
-      #logo {
-        fill: #FFFFFF;
-        fill-rule: nonzero;
-      }
-      #logo-teeth {
-        fill: #FFFFFF;
-        stroke: #FFFFFF;
-        stroke-width: 0.92px;
-      }
-    }
-  ]]></style>
-</defs>
-<path id="logo" d="M15.993,1.54c-7.972,0 -14.461,6.492 -14.461,14.462c0,7.969 6.492,14.461 14.461,14.461c7.97,0 14.462,-6.492 14.462,-14.461c0,-7.97 -6.492,-14.462 -14.462,-14.462Zm-0.021,1.285c0.511,0.013 0.924,0.439 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0.001 0.028,0.001Zm2.178,1.566c3.379,0.633 6.313,2.723 8.016,5.709l-1.123,2.533c-0.193,0.438 0.006,0.952 0.44,1.147l2.16,0.958c0.067,0.675 0.076,1.355 0.025,2.031l-1.202,0c-0.12,0 -0.169,0.08 -0.169,0.196l0,0.551c0,1.297 -0.731,1.582 -1.373,1.652c-0.612,0.07 -1.288,-0.257 -1.374,-0.63c-0.361,-2.029 -0.961,-2.46 -1.909,-3.21c1.178,-0.746 2.401,-1.85 2.401,-3.325c0,-1.594 -1.092,-2.597 -1.835,-3.09c-1.046,-0.688 -2.203,-0.826 -2.515,-0.826l-12.421,0c1.717,-1.918 4.02,-3.218 6.55,-3.696l1.466,1.536c0.33,0.346 0.878,0.361 1.223,0.028l1.64,-1.564Zm-13.522,7.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.951 0.951,-0.951c0.009,0 0.019,0 0.028,0Zm22.685,0.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0 0.028,0.001Zm-20.892,0.153l1.658,0l0,7.477l-3.347,0c-0.414,-1.452 -0.542,-2.97 -0.38,-4.47l2.05,-0.912c0.438,-0.195 0.637,-0.706 0.441,-1.144l-0.422,-0.951Zm6.92,0.079l3.949,0c0.205,0 1.441,0.236 1.441,1.163c0,0.768 -0.948,1.043 -1.728,1.043l-3.665,0l0.003,-2.206Zm0,5.373l3.026,0c0.275,0 1.477,0.079 1.86,1.615c0.119,0.471 0.385,2.007 0.566,2.499c0.18,0.551 0.911,1.652 1.691,1.652l4.938,0c-0.331,0.444 -0.693,0.863 -1.083,1.255l-2.01,-0.432c-0.468,-0.101 -0.93,0.199 -1.031,0.667l-0.477,2.228c-3.104,1.406 -6.672,1.389 -9.762,-0.046l-0.478,-2.228c-0.101,-0.468 -0.56,-0.767 -1.028,-0.667l-1.967,0.423c-0.365,-0.377 -0.704,-0.778 -1.016,-1.2l9.567,0c0.107,0 0.181,-0.018 0.181,-0.119l0,-3.384c0,-0.097 -0.074,-0.119 -0.181,-0.119l-2.799,0l0.003,-2.144Zm-4.415,7.749c0.512,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.952,-0.43 -0.952,-0.952c0,0 0,0 0,0c0,-0.522 0.43,-0.952 0.952,-0.952c0.009,0 0.018,0.001 0.027,0.001Zm14.089,0.043c0.511,0.015 0.924,0.439 0.923,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.009,0 0.018,0 0.028,0.001Z"/><path id="logo-teeth" d="M29.647,16.002c0,7.49 -6.163,13.653 -13.654,13.653c-7.49,0 -13.654,-6.163 -13.654,-13.653c0,-7.491 6.164,-13.654 13.654,-13.654c7.491,0 13.654,6.163 13.654,13.654Zm-0.257,-1.319l2.13,1.319l-2.13,1.318l1.83,1.71l-2.344,0.878l1.463,2.035l-2.475,0.404l1.04,2.282l-2.506,-0.089l0.575,2.442l-2.441,-0.576l0.089,2.506l-2.283,-1.04l-0.403,2.475l-2.035,-1.462l-0.878,2.343l-1.71,-1.829l-1.319,2.129l-1.318,-2.129l-1.71,1.829l-0.878,-2.343l-2.035,1.462l-0.404,-2.475l-2.282,1.04l0.089,-2.506l-2.442,0.576l0.575,-2.442l-2.505,0.089l1.04,-2.282l-2.475,-0.404l1.462,-2.035l-2.343,-0.878l1.829,-1.71l-2.129,-1.318l2.129,-1.319l-1.829,-1.71l2.343,-0.878l-1.462,-2.035l2.475,-0.404l-1.04,-2.282l2.505,0.089l-0.575,-2.441l2.442,0.575l-0.089,-2.506l2.282,1.04l0.404,-2.475l2.035,1.463l0.878,-2.344l1.71,1.83l1.318,-2.13l1.319,2.13l1.71,-1.83l0.878,2.344l2.035,-1.463l0.403,2.475l2.283,-1.04l-0.089,2.506l2.441,-0.575l-0.575,2.441l2.506,-0.089l-1.04,2.282l2.475,0.404l-1.463,2.035l2.344,0.878l-1.83,1.71Z"/></svg>
diff --git a/src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt b/src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt
new file mode 100644 (file)
index 0000000..ff9afab
--- /dev/null
@@ -0,0 +1,94 @@
+Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
+with Reserved Font Name < Fira >,
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/fonts/FiraSans-Medium.woff b/src/librustdoc/html/static/fonts/FiraSans-Medium.woff
new file mode 100644 (file)
index 0000000..7d742c5
Binary files /dev/null and b/src/librustdoc/html/static/fonts/FiraSans-Medium.woff differ
diff --git a/src/librustdoc/html/static/fonts/FiraSans-Medium.woff2 b/src/librustdoc/html/static/fonts/FiraSans-Medium.woff2
new file mode 100644 (file)
index 0000000..7a1e5fc
Binary files /dev/null and b/src/librustdoc/html/static/fonts/FiraSans-Medium.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/FiraSans-Regular.woff b/src/librustdoc/html/static/fonts/FiraSans-Regular.woff
new file mode 100644 (file)
index 0000000..d8e0363
Binary files /dev/null and b/src/librustdoc/html/static/fonts/FiraSans-Regular.woff differ
diff --git a/src/librustdoc/html/static/fonts/FiraSans-Regular.woff2 b/src/librustdoc/html/static/fonts/FiraSans-Regular.woff2
new file mode 100644 (file)
index 0000000..e766e06
Binary files /dev/null and b/src/librustdoc/html/static/fonts/FiraSans-Regular.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff b/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff
new file mode 100644 (file)
index 0000000..8d68f2f
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2
new file mode 100644 (file)
index 0000000..462c34e
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-LICENSE.txt b/src/librustdoc/html/static/fonts/SourceCodePro-LICENSE.txt
new file mode 100644 (file)
index 0000000..0754257
--- /dev/null
@@ -0,0 +1,93 @@
+Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff b/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff
new file mode 100644 (file)
index 0000000..7be076e
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2
new file mode 100644 (file)
index 0000000..10b558e
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff b/src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff
new file mode 100644 (file)
index 0000000..61bc67b
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff2
new file mode 100644 (file)
index 0000000..5ec64ee
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff
new file mode 100644 (file)
index 0000000..8ad4188
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2
new file mode 100644 (file)
index 0000000..db57d21
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff
new file mode 100644 (file)
index 0000000..2a34b5c
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2
new file mode 100644 (file)
index 0000000..1cbc021
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md b/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md
new file mode 100644 (file)
index 0000000..68ea189
--- /dev/null
@@ -0,0 +1,93 @@
+Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff
new file mode 100644 (file)
index 0000000..45a5521
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2
new file mode 100644 (file)
index 0000000..2db73fe
Binary files /dev/null and b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 differ
diff --git a/src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt b/src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt
new file mode 100644 (file)
index 0000000..922d5fd
--- /dev/null
@@ -0,0 +1,93 @@
+Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular.woff b/src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular.woff
new file mode 100644 (file)
index 0000000..01d6b6b
Binary files /dev/null and b/src/librustdoc/html/static/fonts/noto-sans-kr-v13-korean-regular.woff differ
diff --git a/src/librustdoc/html/static/images/brush.svg b/src/librustdoc/html/static/images/brush.svg
new file mode 100644 (file)
index 0000000..ea266e8
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/images/clipboard.svg b/src/librustdoc/html/static/images/clipboard.svg
new file mode 100644 (file)
index 0000000..8adbd99
--- /dev/null
@@ -0,0 +1 @@
+<svg width="24" height="25" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>
diff --git a/src/librustdoc/html/static/images/down-arrow.svg b/src/librustdoc/html/static/images/down-arrow.svg
new file mode 100644 (file)
index 0000000..35437e7
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/images/favicon-16x16.png b/src/librustdoc/html/static/images/favicon-16x16.png
new file mode 100644 (file)
index 0000000..7cfe6c1
Binary files /dev/null and b/src/librustdoc/html/static/images/favicon-16x16.png differ
diff --git a/src/librustdoc/html/static/images/favicon-32x32.png b/src/librustdoc/html/static/images/favicon-32x32.png
new file mode 100644 (file)
index 0000000..5109c1d
Binary files /dev/null and b/src/librustdoc/html/static/images/favicon-32x32.png differ
diff --git a/src/librustdoc/html/static/images/favicon.svg b/src/librustdoc/html/static/images/favicon.svg
new file mode 100644 (file)
index 0000000..8b34b51
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;">
+<defs>
+  <style type="text/css"><![CDATA[
+    #logo {
+      fill-rule: nonzero;
+    }
+    #logo-teeth {
+      stroke: #000000;
+      stroke-width: 0.92px;
+    }
+    @media (prefers-color-scheme: dark) {
+      #logo {
+        fill: #FFFFFF;
+        fill-rule: nonzero;
+      }
+      #logo-teeth {
+        fill: #FFFFFF;
+        stroke: #FFFFFF;
+        stroke-width: 0.92px;
+      }
+    }
+  ]]></style>
+</defs>
+<path id="logo" d="M15.993,1.54c-7.972,0 -14.461,6.492 -14.461,14.462c0,7.969 6.492,14.461 14.461,14.461c7.97,0 14.462,-6.492 14.462,-14.461c0,-7.97 -6.492,-14.462 -14.462,-14.462Zm-0.021,1.285c0.511,0.013 0.924,0.439 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0.001 0.028,0.001Zm2.178,1.566c3.379,0.633 6.313,2.723 8.016,5.709l-1.123,2.533c-0.193,0.438 0.006,0.952 0.44,1.147l2.16,0.958c0.067,0.675 0.076,1.355 0.025,2.031l-1.202,0c-0.12,0 -0.169,0.08 -0.169,0.196l0,0.551c0,1.297 -0.731,1.582 -1.373,1.652c-0.612,0.07 -1.288,-0.257 -1.374,-0.63c-0.361,-2.029 -0.961,-2.46 -1.909,-3.21c1.178,-0.746 2.401,-1.85 2.401,-3.325c0,-1.594 -1.092,-2.597 -1.835,-3.09c-1.046,-0.688 -2.203,-0.826 -2.515,-0.826l-12.421,0c1.717,-1.918 4.02,-3.218 6.55,-3.696l1.466,1.536c0.33,0.346 0.878,0.361 1.223,0.028l1.64,-1.564Zm-13.522,7.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.951 0.951,-0.951c0.009,0 0.019,0 0.028,0Zm22.685,0.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0 0.028,0.001Zm-20.892,0.153l1.658,0l0,7.477l-3.347,0c-0.414,-1.452 -0.542,-2.97 -0.38,-4.47l2.05,-0.912c0.438,-0.195 0.637,-0.706 0.441,-1.144l-0.422,-0.951Zm6.92,0.079l3.949,0c0.205,0 1.441,0.236 1.441,1.163c0,0.768 -0.948,1.043 -1.728,1.043l-3.665,0l0.003,-2.206Zm0,5.373l3.026,0c0.275,0 1.477,0.079 1.86,1.615c0.119,0.471 0.385,2.007 0.566,2.499c0.18,0.551 0.911,1.652 1.691,1.652l4.938,0c-0.331,0.444 -0.693,0.863 -1.083,1.255l-2.01,-0.432c-0.468,-0.101 -0.93,0.199 -1.031,0.667l-0.477,2.228c-3.104,1.406 -6.672,1.389 -9.762,-0.046l-0.478,-2.228c-0.101,-0.468 -0.56,-0.767 -1.028,-0.667l-1.967,0.423c-0.365,-0.377 -0.704,-0.778 -1.016,-1.2l9.567,0c0.107,0 0.181,-0.018 0.181,-0.119l0,-3.384c0,-0.097 -0.074,-0.119 -0.181,-0.119l-2.799,0l0.003,-2.144Zm-4.415,7.749c0.512,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.952,-0.43 -0.952,-0.952c0,0 0,0 0,0c0,-0.522 0.43,-0.952 0.952,-0.952c0.009,0 0.018,0.001 0.027,0.001Zm14.089,0.043c0.511,0.015 0.924,0.439 0.923,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.009,0 0.018,0 0.028,0.001Z"/><path id="logo-teeth" d="M29.647,16.002c0,7.49 -6.163,13.653 -13.654,13.653c-7.49,0 -13.654,-6.163 -13.654,-13.653c0,-7.491 6.164,-13.654 13.654,-13.654c7.491,0 13.654,6.163 13.654,13.654Zm-0.257,-1.319l2.13,1.319l-2.13,1.318l1.83,1.71l-2.344,0.878l1.463,2.035l-2.475,0.404l1.04,2.282l-2.506,-0.089l0.575,2.442l-2.441,-0.576l0.089,2.506l-2.283,-1.04l-0.403,2.475l-2.035,-1.462l-0.878,2.343l-1.71,-1.829l-1.319,2.129l-1.318,-2.129l-1.71,1.829l-0.878,-2.343l-2.035,1.462l-0.404,-2.475l-2.282,1.04l0.089,-2.506l-2.442,0.576l0.575,-2.442l-2.505,0.089l1.04,-2.282l-2.475,-0.404l1.462,-2.035l-2.343,-0.878l1.829,-1.71l-2.129,-1.318l2.129,-1.319l-1.829,-1.71l2.343,-0.878l-1.462,-2.035l2.475,-0.404l-1.04,-2.282l2.505,0.089l-0.575,-2.441l2.442,0.575l-0.089,-2.506l2.282,1.04l0.404,-2.475l2.035,1.463l0.878,-2.344l1.71,1.83l1.318,-2.13l1.319,2.13l1.71,-1.83l0.878,2.344l2.035,-1.463l0.403,2.475l2.283,-1.04l-0.089,2.506l2.441,-0.575l-0.575,2.441l2.506,-0.089l-1.04,2.282l2.475,0.404l-1.463,2.035l2.344,0.878l-1.83,1.71Z"/></svg>
diff --git a/src/librustdoc/html/static/images/rust-logo.png b/src/librustdoc/html/static/images/rust-logo.png
new file mode 100644 (file)
index 0000000..74b4bd6
Binary files /dev/null and b/src/librustdoc/html/static/images/rust-logo.png differ
diff --git a/src/librustdoc/html/static/images/wheel.svg b/src/librustdoc/html/static/images/wheel.svg
new file mode 100644 (file)
index 0000000..01da3b2
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" version="1.1" viewBox="0 0 27.434 29.5" xml:space="preserve"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
new file mode 100644 (file)
index 0000000..9812887
--- /dev/null
@@ -0,0 +1,1018 @@
+// Local js definitions:
+/* global addClass, getSettingValue, hasClass, searchState */
+/* global onEach, onEachLazy, removeClass */
+/* global switchTheme, useSystemTheme */
+
+if (!String.prototype.startsWith) {
+    String.prototype.startsWith = function(searchString, position) {
+        position = position || 0;
+        return this.indexOf(searchString, position) === position;
+    };
+}
+if (!String.prototype.endsWith) {
+    String.prototype.endsWith = function(suffix, length) {
+        var l = length || this.length;
+        return this.indexOf(suffix, l - suffix.length) !== -1;
+    };
+}
+
+if (!DOMTokenList.prototype.add) {
+    DOMTokenList.prototype.add = function(className) {
+        if (className && !hasClass(this, className)) {
+            if (this.className && this.className.length > 0) {
+                this.className += " " + className;
+            } else {
+                this.className = className;
+            }
+        }
+    };
+}
+
+if (!DOMTokenList.prototype.remove) {
+    DOMTokenList.prototype.remove = function(className) {
+        if (className && this.className) {
+            this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
+                                                         .trim();
+        }
+    };
+}
+
+(function () {
+    var rustdocVars = document.getElementById("rustdoc-vars");
+    if (rustdocVars) {
+        window.rootPath = rustdocVars.attributes["data-root-path"].value;
+        window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
+        window.searchJS = rustdocVars.attributes["data-search-js"].value;
+        window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
+    }
+    var sidebarVars = document.getElementById("sidebar-vars");
+    if (sidebarVars) {
+        window.sidebarCurrent = {
+            name: sidebarVars.attributes["data-name"].value,
+            ty: sidebarVars.attributes["data-ty"].value,
+            relpath: sidebarVars.attributes["data-relpath"].value,
+        };
+    }
+}());
+
+// Gets the human-readable string for the virtual-key code of the
+// given KeyboardEvent, ev.
+//
+// This function is meant as a polyfill for KeyboardEvent#key,
+// since it is not supported in IE 11 or Chrome for Android. We also test for
+// KeyboardEvent#keyCode because the handleShortcut handler is
+// also registered for the keydown event, because Blink doesn't fire
+// keypress on hitting the Escape key.
+//
+// So I guess you could say things are getting pretty interoperable.
+function getVirtualKey(ev) {
+    if ("key" in ev && typeof ev.key != "undefined") {
+        return ev.key;
+    }
+
+    var c = ev.charCode || ev.keyCode;
+    if (c == 27) {
+        return "Escape";
+    }
+    return String.fromCharCode(c);
+}
+
+var THEME_PICKER_ELEMENT_ID = "theme-picker";
+var THEMES_ELEMENT_ID = "theme-choices";
+
+function getThemesElement() {
+    return document.getElementById(THEMES_ELEMENT_ID);
+}
+
+function getThemePickerElement() {
+    return document.getElementById(THEME_PICKER_ELEMENT_ID);
+}
+
+// Returns the current URL without any query parameter or hash.
+function getNakedUrl() {
+    return window.location.href.split("?")[0].split("#")[0];
+}
+
+function showThemeButtonState() {
+    var themePicker = getThemePickerElement();
+    var themeChoices = getThemesElement();
+
+    themeChoices.style.display = "block";
+    themePicker.style.borderBottomRightRadius = "0";
+    themePicker.style.borderBottomLeftRadius = "0";
+}
+
+function hideThemeButtonState() {
+    var themePicker = getThemePickerElement();
+    var themeChoices = getThemesElement();
+
+    themeChoices.style.display = "none";
+    themePicker.style.borderBottomRightRadius = "3px";
+    themePicker.style.borderBottomLeftRadius = "3px";
+}
+
+// Set up the theme picker list.
+(function () {
+    var themeChoices = getThemesElement();
+    var themePicker = getThemePickerElement();
+    var availableThemes/* INSERT THEMES HERE */;
+
+    function switchThemeButtonState() {
+        if (themeChoices.style.display === "block") {
+            hideThemeButtonState();
+        } else {
+            showThemeButtonState();
+        }
+    }
+
+    function handleThemeButtonsBlur(e) {
+        var active = document.activeElement;
+        var related = e.relatedTarget;
+
+        if (active.id !== THEME_PICKER_ELEMENT_ID &&
+            (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
+            (!related ||
+             (related.id !== THEME_PICKER_ELEMENT_ID &&
+              (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
+            hideThemeButtonState();
+        }
+    }
+
+    themePicker.onclick = switchThemeButtonState;
+    themePicker.onblur = handleThemeButtonsBlur;
+    availableThemes.forEach(function(item) {
+        var but = document.createElement("button");
+        but.textContent = item;
+        but.onclick = function() {
+            switchTheme(window.currentTheme, window.mainTheme, item, true);
+            useSystemTheme(false);
+        };
+        but.onblur = handleThemeButtonsBlur;
+        themeChoices.appendChild(but);
+    });
+}());
+
+(function() {
+    "use strict";
+
+    window.searchState = {
+        loadingText: "Loading search results...",
+        input: document.getElementsByClassName("search-input")[0],
+        outputElement: function() {
+            return document.getElementById("search");
+        },
+        title: document.title,
+        titleBeforeSearch: document.title,
+        timeout: null,
+        // On the search screen, so you remain on the last tab you opened.
+        //
+        // 0 for "In Names"
+        // 1 for "In Parameters"
+        // 2 for "In Return Types"
+        currentTab: 0,
+        // tab and back preserves the element that was focused.
+        focusedByTab: [null, null, null],
+        clearInputTimeout: function() {
+            if (searchState.timeout !== null) {
+                clearTimeout(searchState.timeout);
+                searchState.timeout = null;
+            }
+        },
+        // Sets the focus on the search bar at the top of the page
+        focus: function() {
+            searchState.input.focus();
+        },
+        // Removes the focus from the search bar.
+        defocus: function() {
+            searchState.input.blur();
+        },
+        showResults: function(search) {
+            if (search === null || typeof search === 'undefined') {
+                search = searchState.outputElement();
+            }
+            addClass(main, "hidden");
+            removeClass(search, "hidden");
+            searchState.mouseMovedAfterSearch = false;
+            document.title = searchState.title;
+        },
+        hideResults: function(search) {
+            if (search === null || typeof search === 'undefined') {
+                search = searchState.outputElement();
+            }
+            addClass(search, "hidden");
+            removeClass(main, "hidden");
+            document.title = searchState.titleBeforeSearch;
+            // We also remove the query parameter from the URL.
+            if (searchState.browserSupportsHistoryApi()) {
+                history.replaceState("", window.currentCrate + " - Rust",
+                    getNakedUrl() + window.location.hash);
+            }
+        },
+        getQueryStringParams: function() {
+            var params = {};
+            window.location.search.substring(1).split("&").
+                map(function(s) {
+                    var pair = s.split("=");
+                    params[decodeURIComponent(pair[0])] =
+                        typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
+                });
+            return params;
+        },
+        putBackSearch: function(search_input) {
+            var search = searchState.outputElement();
+            if (search_input.value !== "" && hasClass(search, "hidden")) {
+                searchState.showResults(search);
+                if (searchState.browserSupportsHistoryApi()) {
+                    var extra = "?search=" + encodeURIComponent(search_input.value);
+                    history.replaceState(search_input.value, "",
+                        getNakedUrl() + extra + window.location.hash);
+                }
+                document.title = searchState.title;
+            }
+        },
+        browserSupportsHistoryApi: function() {
+            return window.history && typeof window.history.pushState === "function";
+        },
+        setup: function() {
+            var search_input = searchState.input;
+            if (!searchState.input) {
+                return;
+            }
+            function loadScript(url) {
+                var script = document.createElement('script');
+                script.src = url;
+                document.head.append(script);
+            }
+
+            var searchLoaded = false;
+            function loadSearch() {
+                if (!searchLoaded) {
+                    searchLoaded = true;
+                    loadScript(window.searchJS);
+                    loadScript(window.searchIndexJS);
+                }
+            }
+
+            search_input.addEventListener("focus", function() {
+                searchState.putBackSearch(this);
+                search_input.origPlaceholder = searchState.input.placeholder;
+                search_input.placeholder = "Type your search here.";
+                loadSearch();
+            });
+            search_input.addEventListener("blur", function() {
+                search_input.placeholder = searchState.input.origPlaceholder;
+            });
+
+            search_input.removeAttribute('disabled');
+
+            // `crates{version}.js` should always be loaded before this script, so we can use it
+            // safely.
+            searchState.addCrateDropdown(window.ALL_CRATES);
+            var params = searchState.getQueryStringParams();
+            if (params.search !== undefined) {
+                var search = searchState.outputElement();
+                search.innerHTML = "<h3 style=\"text-align: center;\">" +
+                   searchState.loadingText + "</h3>";
+                searchState.showResults(search);
+                loadSearch();
+            }
+        },
+        addCrateDropdown: function(crates) {
+            var elem = document.getElementById("crate-search");
+
+            if (!elem) {
+                return;
+            }
+            var savedCrate = getSettingValue("saved-filter-crate");
+            for (var i = 0, len = crates.length; i < len; ++i) {
+                var option = document.createElement("option");
+                option.value = crates[i];
+                option.innerText = crates[i];
+                elem.appendChild(option);
+                // Set the crate filter from saved storage, if the current page has the saved crate
+                // filter.
+                //
+                // If not, ignore the crate filter -- we want to support filtering for crates on
+                // sites like doc.rust-lang.org where the crates may differ from page to page while
+                // on the
+                // same domain.
+                if (crates[i] === savedCrate) {
+                    elem.value = savedCrate;
+                }
+            }
+        },
+    };
+
+    function getPageId() {
+        if (window.location.hash) {
+            var tmp = window.location.hash.replace(/^#/, "");
+            if (tmp.length > 0) {
+                return tmp;
+            }
+        }
+        return null;
+    }
+
+    function showSidebar() {
+        var elems = document.getElementsByClassName("sidebar-elems")[0];
+        if (elems) {
+            addClass(elems, "show-it");
+        }
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        if (sidebar) {
+            addClass(sidebar, "mobile");
+            var filler = document.getElementById("sidebar-filler");
+            if (!filler) {
+                var div = document.createElement("div");
+                div.id = "sidebar-filler";
+                sidebar.appendChild(div);
+            }
+        }
+    }
+
+    function hideSidebar() {
+        var elems = document.getElementsByClassName("sidebar-elems")[0];
+        if (elems) {
+            removeClass(elems, "show-it");
+        }
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        removeClass(sidebar, "mobile");
+        var filler = document.getElementById("sidebar-filler");
+        if (filler) {
+            filler.remove();
+        }
+        document.getElementsByTagName("body")[0].style.marginTop = "";
+    }
+
+    var toggleAllDocsId = "toggle-all-docs";
+    var main = document.getElementById("main");
+    var savedHash = "";
+
+    function handleHashes(ev) {
+        var elem;
+        var search = searchState.outputElement();
+        if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
+            // This block occurs when clicking on an element in the navbar while
+            // in a search.
+            searchState.hideResults(search);
+            var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
+            if (searchState.browserSupportsHistoryApi()) {
+                // `window.location.search`` contains all the query parameters, not just `search`.
+                history.replaceState(hash, "",
+                    getNakedUrl() + window.location.search + "#" + hash);
+            }
+            elem = document.getElementById(hash);
+            if (elem) {
+                elem.scrollIntoView();
+            }
+        }
+        // This part is used in case an element is not visible.
+        if (savedHash !== window.location.hash) {
+            savedHash = window.location.hash;
+            if (savedHash.length === 0) {
+                return;
+            }
+            expandSection(savedHash.slice(1)); // we remove the '#'
+        }
+    }
+
+    function onHashChange(ev) {
+        // If we're in mobile mode, we should hide the sidebar in any case.
+        hideSidebar();
+        handleHashes(ev);
+    }
+
+    function openParentDetails(elem) {
+        while (elem) {
+            if (elem.tagName === "DETAILS") {
+                elem.open = true;
+            }
+            elem = elem.parentNode;
+        }
+    }
+
+    function expandSection(id) {
+        openParentDetails(document.getElementById(id));
+    }
+
+    function getHelpElement(build) {
+        if (build) {
+            buildHelperPopup();
+        }
+        return document.getElementById("help");
+    }
+
+    function displayHelp(display, ev, help) {
+        if (display) {
+            help = help ? help : getHelpElement(true);
+            if (hasClass(help, "hidden")) {
+                ev.preventDefault();
+                removeClass(help, "hidden");
+                addClass(document.body, "blur");
+            }
+        } else {
+            // No need to build the help popup if we want to hide it in case it hasn't been
+            // built yet...
+            help = help ? help : getHelpElement(false);
+            if (help && !hasClass(help, "hidden")) {
+                ev.preventDefault();
+                addClass(help, "hidden");
+                removeClass(document.body, "blur");
+            }
+        }
+    }
+
+    function handleEscape(ev) {
+        var help = getHelpElement(false);
+        var search = searchState.outputElement();
+        if (help && !hasClass(help, "hidden")) {
+            displayHelp(false, ev, help);
+        } else if (search && !hasClass(search, "hidden")) {
+            searchState.clearInputTimeout();
+            ev.preventDefault();
+            searchState.hideResults(search);
+        }
+        searchState.defocus();
+        hideThemeButtonState();
+    }
+
+    var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
+    function handleShortcut(ev) {
+        // Don't interfere with browser shortcuts
+        if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
+            return;
+        }
+
+        if (document.activeElement.tagName === "INPUT") {
+            switch (getVirtualKey(ev)) {
+            case "Escape":
+                handleEscape(ev);
+                break;
+            }
+        } else {
+            switch (getVirtualKey(ev)) {
+            case "Escape":
+                handleEscape(ev);
+                break;
+
+            case "s":
+            case "S":
+                displayHelp(false, ev);
+                ev.preventDefault();
+                searchState.focus();
+                break;
+
+            case "+":
+            case "-":
+                ev.preventDefault();
+                toggleAllDocs();
+                break;
+
+            case "?":
+                displayHelp(true, ev);
+                break;
+
+            case "t":
+            case "T":
+                displayHelp(false, ev);
+                ev.preventDefault();
+                var themePicker = getThemePickerElement();
+                themePicker.click();
+                themePicker.focus();
+                break;
+
+            default:
+                if (getThemePickerElement().parentNode.contains(ev.target)) {
+                    handleThemeKeyDown(ev);
+                }
+            }
+        }
+    }
+
+    function handleThemeKeyDown(ev) {
+        var active = document.activeElement;
+        var themes = getThemesElement();
+        switch (getVirtualKey(ev)) {
+        case "ArrowUp":
+            ev.preventDefault();
+            if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
+                active.previousElementSibling.focus();
+            } else {
+                showThemeButtonState();
+                themes.lastElementChild.focus();
+            }
+            break;
+        case "ArrowDown":
+            ev.preventDefault();
+            if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
+                active.nextElementSibling.focus();
+            } else {
+                showThemeButtonState();
+                themes.firstElementChild.focus();
+            }
+            break;
+        case "Enter":
+        case "Return":
+        case "Space":
+            if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
+                ev.preventDefault();
+                showThemeButtonState();
+                themes.firstElementChild.focus();
+            }
+            break;
+        case "Home":
+            ev.preventDefault();
+            themes.firstElementChild.focus();
+            break;
+        case "End":
+            ev.preventDefault();
+            themes.lastElementChild.focus();
+            break;
+        // The escape key is handled in handleEscape, not here,
+        // so that pressing escape will close the menu even if it isn't focused
+        }
+    }
+
+    document.addEventListener("keypress", handleShortcut);
+    document.addEventListener("keydown", handleShortcut);
+
+    (function() {
+        var x = document.getElementsByClassName("version-selector");
+        if (x.length > 0) {
+            x[0].onchange = function() {
+                var i, match,
+                    url = document.location.href,
+                    stripped = "",
+                    len = window.rootPath.match(/\.\.\//g).length + 1;
+
+                for (i = 0; i < len; ++i) {
+                    match = url.match(/\/[^/]*$/);
+                    if (i < len - 1) {
+                        stripped = match[0] + stripped;
+                    }
+                    url = url.substring(0, url.length - match[0].length);
+                }
+
+                var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
+                url += "/" + selectedVersion + stripped;
+
+                document.location.href = url;
+            };
+        }
+    }());
+
+    // delayed sidebar rendering.
+    window.initSidebarItems = function(items) {
+        var sidebar = document.getElementsByClassName("sidebar-elems")[0];
+        var current = window.sidebarCurrent;
+
+        function addSidebarCrates(crates) {
+            if (!hasClass(document.body, "crate")) {
+                // We only want to list crates on the crate page.
+                return;
+            }
+            // Draw a convenient sidebar of known crates if we have a listing
+            var div = document.createElement("div");
+            div.className = "block crate";
+            div.innerHTML = "<h3>Crates</h3>";
+            var ul = document.createElement("ul");
+            div.appendChild(ul);
+
+            for (var i = 0; i < crates.length; ++i) {
+                var klass = "crate";
+                if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
+                    klass += " current";
+                }
+                var link = document.createElement("a");
+                link.href = window.rootPath + crates[i] + "/index.html";
+                link.className = klass;
+                link.textContent = crates[i];
+
+                var li = document.createElement("li");
+                li.appendChild(link);
+                ul.appendChild(li);
+            }
+            sidebar.appendChild(div);
+        }
+
+        function block(shortty, longty) {
+            var filtered = items[shortty];
+            if (!filtered) {
+                return;
+            }
+
+            var div = document.createElement("div");
+            div.className = "block " + shortty;
+            var h3 = document.createElement("h3");
+            h3.textContent = longty;
+            div.appendChild(h3);
+            var ul = document.createElement("ul");
+
+            for (var i = 0, len = filtered.length; i < len; ++i) {
+                var item = filtered[i];
+                var name = item[0];
+                var desc = item[1]; // can be null
+
+                var klass = shortty;
+                if (name === current.name && shortty === current.ty) {
+                    klass += " current";
+                }
+                var path;
+                if (shortty === "mod") {
+                    path = name + "/index.html";
+                } else {
+                    path = shortty + "." + name + ".html";
+                }
+                var link = document.createElement("a");
+                link.href = current.relpath + path;
+                link.title = desc;
+                link.className = klass;
+                link.textContent = name;
+                var li = document.createElement("li");
+                li.appendChild(link);
+                ul.appendChild(li);
+            }
+            div.appendChild(ul);
+            sidebar.appendChild(div);
+        }
+
+        if (sidebar) {
+            var isModule = hasClass(document.body, "mod");
+            if (!isModule) {
+                block("primitive", "Primitive Types");
+                block("mod", "Modules");
+                block("macro", "Macros");
+                block("struct", "Structs");
+                block("enum", "Enums");
+                block("union", "Unions");
+                block("constant", "Constants");
+                block("static", "Statics");
+                block("trait", "Traits");
+                block("fn", "Functions");
+                block("type", "Type Definitions");
+                block("foreigntype", "Foreign Types");
+                block("keyword", "Keywords");
+                block("traitalias", "Trait Aliases");
+            }
+
+            // `crates{version}.js` should always be loaded before this script, so we can use
+            // it safely.
+            addSidebarCrates(window.ALL_CRATES);
+        }
+    };
+
+    window.register_implementors = function(imp) {
+        var implementors = document.getElementById("implementors-list");
+        var synthetic_implementors = document.getElementById("synthetic-implementors-list");
+
+        if (synthetic_implementors) {
+            // This `inlined_types` variable is used to avoid having the same implementation
+            // showing up twice. For example "String" in the "Sync" doc page.
+            //
+            // By the way, this is only used by and useful for traits implemented automatically
+            // (like "Send" and "Sync").
+            var inlined_types = new Set();
+            onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
+                var aliases = el.getAttribute("data-aliases");
+                if (!aliases) {
+                    return;
+                }
+                aliases.split(",").forEach(function(alias) {
+                    inlined_types.add(alias);
+                });
+            });
+        }
+
+        var libs = Object.getOwnPropertyNames(imp);
+        for (var i = 0, llength = libs.length; i < llength; ++i) {
+            if (libs[i] === window.currentCrate) { continue; }
+            var structs = imp[libs[i]];
+
+            struct_loop:
+            for (var j = 0, slength = structs.length; j < slength; ++j) {
+                var struct = structs[j];
+
+                var list = struct.synthetic ? synthetic_implementors : implementors;
+
+                if (struct.synthetic) {
+                    for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
+                        if (inlined_types.has(struct.types[k])) {
+                            continue struct_loop;
+                        }
+                        inlined_types.add(struct.types[k]);
+                    }
+                }
+
+                var code = document.createElement("code");
+                code.innerHTML = struct.text;
+
+                onEachLazy(code.getElementsByTagName("a"), function(elem) {
+                    var href = elem.getAttribute("href");
+
+                    if (href && href.indexOf("http") !== 0) {
+                        elem.setAttribute("href", window.rootPath + href);
+                    }
+                });
+
+                var display = document.createElement("h3");
+                addClass(display, "impl");
+                display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
+                    "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
+                    "</tbody></table></span>";
+                list.appendChild(display);
+            }
+        }
+    };
+    if (window.pending_implementors) {
+        window.register_implementors(window.pending_implementors);
+    }
+
+    function labelForToggleButton(sectionIsCollapsed) {
+        if (sectionIsCollapsed) {
+            // button will expand the section
+            return "+";
+        }
+        // button will collapse the section
+        // note that this text is also set in the HTML template in ../render/mod.rs
+        return "\u2212"; // "\u2212" is "−" minus sign
+    }
+
+    function toggleAllDocs() {
+        var innerToggle = document.getElementById(toggleAllDocsId);
+        if (!innerToggle) {
+            return;
+        }
+        var sectionIsCollapsed = false;
+        if (hasClass(innerToggle, "will-expand")) {
+            removeClass(innerToggle, "will-expand");
+            onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
+                if (!hasClass(e, "type-contents-toggle")) {
+                    e.open = true;
+                }
+            });
+            innerToggle.title = "collapse all docs";
+        } else {
+            addClass(innerToggle, "will-expand");
+            onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
+                if (e.parentNode.id !== "main" ||
+                    (!hasClass(e, "implementors-toggle") &&
+                     !hasClass(e, "type-contents-toggle")))
+                {
+                    e.open = false;
+                }
+            });
+            sectionIsCollapsed = true;
+            innerToggle.title = "expand all docs";
+        }
+        innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
+    }
+
+    function insertAfter(newNode, referenceNode) {
+        referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+    }
+
+    (function() {
+        var toggles = document.getElementById(toggleAllDocsId);
+        if (toggles) {
+            toggles.onclick = toggleAllDocs;
+        }
+
+        var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
+        var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
+        var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
+
+        function setImplementorsTogglesOpen(id, open) {
+            var list = document.getElementById(id);
+            if (list !== null) {
+                onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
+                    e.open = open;
+                });
+            }
+        }
+
+        if (hideImplementations) {
+            setImplementorsTogglesOpen("trait-implementations-list", false);
+            setImplementorsTogglesOpen("blanket-implementations-list", false);
+        }
+
+        onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
+            if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
+                e.open = true;
+            }
+            if (hideMethodDocs && hasClass(e, "method-toggle")) {
+                e.open = false;
+            }
+
+        });
+
+        var pageId = getPageId();
+        if (pageId !== null) {
+            expandSection(pageId);
+        }
+    }());
+
+    (function() {
+        // To avoid checking on "rustdoc-line-numbers" value on every loop...
+        var lineNumbersFunc = function() {};
+        if (getSettingValue("line-numbers") === "true") {
+            lineNumbersFunc = function(x) {
+                var count = x.textContent.split("\n").length;
+                var elems = [];
+                for (var i = 0; i < count; ++i) {
+                    elems.push(i + 1);
+                }
+                var node = document.createElement("pre");
+                addClass(node, "line-number");
+                node.innerHTML = elems.join("\n");
+                x.parentNode.insertBefore(node, x);
+            };
+        }
+        onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
+            if (hasClass(e, "compile_fail")) {
+                e.addEventListener("mouseover", function() {
+                    this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
+                });
+                e.addEventListener("mouseout", function() {
+                    this.parentElement.previousElementSibling.childNodes[0].style.color = "";
+                });
+            } else if (hasClass(e, "ignore")) {
+                e.addEventListener("mouseover", function() {
+                    this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
+                });
+                e.addEventListener("mouseout", function() {
+                    this.parentElement.previousElementSibling.childNodes[0].style.color = "";
+                });
+            }
+            lineNumbersFunc(e);
+        });
+    }());
+
+    function handleClick(id, f) {
+        var elem = document.getElementById(id);
+        if (elem) {
+            elem.addEventListener("click", f);
+        }
+    }
+    handleClick("help-button", function(ev) {
+        displayHelp(true, ev);
+    });
+
+    onEachLazy(document.getElementsByTagName("a"), function(el) {
+        // For clicks on internal links (<A> tags with a hash property), we expand the section we're
+        // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
+        // the height of the document so we wind up scrolled to the wrong place.
+        if (el.hash) {
+            el.addEventListener("click", function() {
+                expandSection(el.hash.slice(1));
+            });
+        }
+    });
+
+    onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
+        e.onclick = function() {
+            this.getElementsByClassName('notable-traits-tooltiptext')[0]
+                .classList.toggle("force-tooltip");
+        };
+    });
+
+    var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
+    if (sidebar_menu) {
+        sidebar_menu.onclick = function() {
+            var sidebar = document.getElementsByClassName("sidebar")[0];
+            if (hasClass(sidebar, "mobile")) {
+                hideSidebar();
+            } else {
+                showSidebar();
+            }
+        };
+    }
+
+    var buildHelperPopup = function() {
+        var popup = document.createElement("aside");
+        addClass(popup, "hidden");
+        popup.id = "help";
+
+        popup.addEventListener("click", function(ev) {
+            if (ev.target === popup) {
+                // Clicked the blurred zone outside the help popup; dismiss help.
+                displayHelp(false, ev);
+            }
+        });
+
+        var book_info = document.createElement("span");
+        book_info.innerHTML = "You can find more information in \
+            <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
+
+        var container = document.createElement("div");
+        var shortcuts = [
+            ["?", "Show this help dialog"],
+            ["S", "Focus the search field"],
+            ["T", "Focus the theme picker menu"],
+            ["↑", "Move up in search results"],
+            ["↓", "Move down in search results"],
+            ["← / →", "Switch result tab (when results focused)"],
+            ["&#9166;", "Go to active search result"],
+            ["+", "Expand all sections"],
+            ["-", "Collapse all sections"],
+        ].map(function(x) {
+            return "<dt>" +
+                x[0].split(" ")
+                    .map(function(y, index) {
+                        return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
+                    })
+                    .join("") + "</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 item kind.",
+            "Accepted kinds 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 -&gt; usize</code> or \
+             <code>* -&gt; 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(function(x) {
+            return "<p>" + x + "</p>";
+        }).join("");
+        var div_infos = document.createElement("div");
+        addClass(div_infos, "infos");
+        div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
+
+        container.appendChild(book_info);
+        container.appendChild(div_shortcuts);
+        container.appendChild(div_infos);
+
+        popup.appendChild(container);
+        insertAfter(popup, searchState.outputElement());
+        // So that it's only built once and then it'll do nothing when called!
+        buildHelperPopup = function() {};
+    };
+
+    onHashChange(null);
+    window.addEventListener("hashchange", onHashChange);
+    searchState.setup();
+}());
+
+(function () {
+    var reset_button_timeout = null;
+
+    window.copy_path = function(but) {
+        var parent = but.parentElement;
+        var path = [];
+
+        onEach(parent.childNodes, function(child) {
+            if (child.tagName === 'A') {
+                path.push(child.textContent);
+            }
+        });
+
+        var el = document.createElement('textarea');
+        el.value = 'use ' + path.join('::') + ';';
+        el.setAttribute('readonly', '');
+        // To not make it appear on the screen.
+        el.style.position = 'absolute';
+        el.style.left = '-9999px';
+
+        document.body.appendChild(el);
+        el.select();
+        document.execCommand('copy');
+        document.body.removeChild(el);
+
+        // There is always one children, but multiple childNodes.
+        but.children[0].style.display = 'none';
+
+        var tmp;
+        if (but.childNodes.length < 2) {
+            tmp = document.createTextNode('✓');
+            but.appendChild(tmp);
+        } else {
+            onEachLazy(but.childNodes, function(e) {
+                if (e.nodeType === Node.TEXT_NODE) {
+                    tmp = e;
+                    return true;
+                }
+            });
+            tmp.textContent = '✓';
+        }
+
+        if (reset_button_timeout !== null) {
+            window.clearTimeout(reset_button_timeout);
+        }
+
+        function reset_button() {
+            tmp.textContent = '';
+            reset_button_timeout = null;
+            but.children[0].style.display = "";
+        }
+
+        reset_button_timeout = window.setTimeout(reset_button, 1000);
+    };
+}());
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
new file mode 100644 (file)
index 0000000..76e7295
--- /dev/null
@@ -0,0 +1,1554 @@
+/* global addClass, getNakedUrl, getSettingValue, hasOwnPropertyRustdoc, initSearch, onEach */
+/* global onEachLazy, removeClass, searchState, updateLocalStorage */
+
+(function() {
+// This mapping table should match the discriminants of
+// `rustdoc::html::item_type::ItemType` type in Rust.
+var itemTypes = ["mod",
+                    "externcrate",
+                    "import",
+                    "struct",
+                    "enum",
+                    "fn",
+                    "type",
+                    "static",
+                    "trait",
+                    "impl",
+                    "tymethod",
+                    "method",
+                    "structfield",
+                    "variant",
+                    "macro",
+                    "primitive",
+                    "associatedtype",
+                    "constant",
+                    "associatedconstant",
+                    "union",
+                    "foreigntype",
+                    "keyword",
+                    "existential",
+                    "attr",
+                    "derive",
+                    "traitalias"];
+
+// used for special search precedence
+var TY_PRIMITIVE = itemTypes.indexOf("primitive");
+var TY_KEYWORD = itemTypes.indexOf("keyword");
+
+// In the search display, allows to switch between tabs.
+function printTab(nb) {
+    if (nb === 0 || nb === 1 || nb === 2) {
+        searchState.currentTab = nb;
+    }
+    var nb_copy = nb;
+    onEachLazy(document.getElementById("titles").childNodes, function(elem) {
+        if (nb_copy === 0) {
+            addClass(elem, "selected");
+        } else {
+            removeClass(elem, "selected");
+        }
+        nb_copy -= 1;
+    });
+    onEachLazy(document.getElementById("results").childNodes, function(elem) {
+        if (nb === 0) {
+            addClass(elem, "active");
+        } else {
+            removeClass(elem, "active");
+        }
+        nb -= 1;
+    });
+}
+
+function removeEmptyStringsFromArray(x) {
+    for (var i = 0, len = x.length; i < len; ++i) {
+        if (x[i] === "") {
+            x.splice(i, 1);
+            i -= 1;
+        }
+    }
+}
+
+/**
+ * A function to compute the Levenshtein distance between two strings
+ * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
+ * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
+ * This code is an unmodified version of the code written by Marco de Wit
+ * and was found at https://stackoverflow.com/a/18514751/745719
+ */
+var levenshtein_row2 = [];
+function levenshtein(s1, s2) {
+    if (s1 === s2) {
+        return 0;
+    }
+    var s1_len = s1.length, s2_len = s2.length;
+    if (s1_len && s2_len) {
+        var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
+        while (i1 < s1_len) {
+            row[i1] = ++i1;
+        }
+        while (i2 < s2_len) {
+            c2 = s2.charCodeAt(i2);
+            a = i2;
+            ++i2;
+            b = i2;
+            for (i1 = 0; i1 < s1_len; ++i1) {
+                c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+                a = row[i1];
+                b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+                row[i1] = b;
+            }
+        }
+        return b;
+    }
+    return s1_len + s2_len;
+}
+
+window.initSearch = function(rawSearchIndex) {
+    var MAX_LEV_DISTANCE = 3;
+    var MAX_RESULTS = 200;
+    var GENERICS_DATA = 2;
+    var NAME = 0;
+    var INPUTS_DATA = 0;
+    var OUTPUT_DATA = 1;
+    var NO_TYPE_FILTER = -1;
+    var currentResults, index, searchIndex;
+    var ALIASES = {};
+    var params = searchState.getQueryStringParams();
+
+    // Populate search bar with query string search term when provided,
+    // but only if the input bar is empty. This avoid the obnoxious issue
+    // where you start trying to do a search, and the index loads, and
+    // suddenly your search is gone!
+    if (searchState.input.value === "") {
+        searchState.input.value = params.search || "";
+    }
+
+    /**
+     * Executes the query and builds an index of results
+     * @param  {[Object]} query      [The user query]
+     * @param  {[type]} searchWords  [The list of search words to query
+     *                                against]
+     * @param  {[type]} filterCrates [Crate to search in if defined]
+     * @return {[type]}              [A search index of results]
+     */
+    function execQuery(query, searchWords, filterCrates) {
+        function itemTypeFromName(typename) {
+            for (var i = 0, len = itemTypes.length; i < len; ++i) {
+                if (itemTypes[i] === typename) {
+                    return i;
+                }
+            }
+            return NO_TYPE_FILTER;
+        }
+
+        var valLower = query.query.toLowerCase(),
+            val = valLower,
+            typeFilter = itemTypeFromName(query.type),
+            results = {}, results_in_args = {}, results_returned = {},
+            split = valLower.split("::");
+
+        removeEmptyStringsFromArray(split);
+
+        function transformResults(results) {
+            var out = [];
+            for (var i = 0, len = results.length; i < len; ++i) {
+                if (results[i].id > -1) {
+                    var obj = searchIndex[results[i].id];
+                    obj.lev = results[i].lev;
+                    var res = buildHrefAndPath(obj);
+                    obj.displayPath = pathSplitter(res[0]);
+                    obj.fullPath = obj.displayPath + obj.name;
+                    // To be sure than it some items aren't considered as duplicate.
+                    obj.fullPath += "|" + obj.ty;
+                    obj.href = res[1];
+                    out.push(obj);
+                    if (out.length >= MAX_RESULTS) {
+                        break;
+                    }
+                }
+            }
+            return out;
+        }
+
+        function sortResults(results, isType) {
+            var ar = [];
+            for (var entry in results) {
+                if (hasOwnPropertyRustdoc(results, entry)) {
+                    ar.push(results[entry]);
+                }
+            }
+            results = ar;
+            var i, len, result;
+            for (i = 0, len = results.length; i < len; ++i) {
+                result = results[i];
+                result.word = searchWords[result.id];
+                result.item = searchIndex[result.id] || {};
+            }
+            // if there are no results then return to default and fail
+            if (results.length === 0) {
+                return [];
+            }
+
+            results.sort(function(aaa, bbb) {
+                var a, b;
+
+                // sort by exact match with regard to the last word (mismatch goes later)
+                a = (aaa.word !== val);
+                b = (bbb.word !== val);
+                if (a !== b) { return a - b; }
+
+                // Sort by non levenshtein results and then levenshtein results by the distance
+                // (less changes required to match means higher rankings)
+                a = (aaa.lev);
+                b = (bbb.lev);
+                if (a !== b) { return a - b; }
+
+                // sort by crate (non-current crate goes later)
+                a = (aaa.item.crate !== window.currentCrate);
+                b = (bbb.item.crate !== window.currentCrate);
+                if (a !== b) { return a - b; }
+
+                // sort by item name length (longer goes later)
+                a = aaa.word.length;
+                b = bbb.word.length;
+                if (a !== b) { return a - b; }
+
+                // sort by item name (lexicographically larger goes later)
+                a = aaa.word;
+                b = bbb.word;
+                if (a !== b) { return (a > b ? +1 : -1); }
+
+                // sort by index of keyword in item name (no literal occurrence goes later)
+                a = (aaa.index < 0);
+                b = (bbb.index < 0);
+                if (a !== b) { return a - b; }
+                // (later literal occurrence, if any, goes later)
+                a = aaa.index;
+                b = bbb.index;
+                if (a !== b) { return a - b; }
+
+                // special precedence for primitive and keyword pages
+                if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
+                    (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
+                    return -1;
+                }
+                if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
+                    (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
+                    return 1;
+                }
+
+                // sort by description (no description goes later)
+                a = (aaa.item.desc === "");
+                b = (bbb.item.desc === "");
+                if (a !== b) { return a - b; }
+
+                // sort by type (later occurrence in `itemTypes` goes later)
+                a = aaa.item.ty;
+                b = bbb.item.ty;
+                if (a !== b) { return a - b; }
+
+                // sort by path (lexicographically larger goes later)
+                a = aaa.item.path;
+                b = bbb.item.path;
+                if (a !== b) { return (a > b ? +1 : -1); }
+
+                // que sera, sera
+                return 0;
+            });
+
+            for (i = 0, len = results.length; i < len; ++i) {
+                result = results[i];
+
+                // this validation does not make sense when searching by types
+                if (result.dontValidate) {
+                    continue;
+                }
+                var name = result.item.name.toLowerCase(),
+                    path = result.item.path.toLowerCase(),
+                    parent = result.item.parent;
+
+                if (!isType && !validateResult(name, path, split, parent)) {
+                    result.id = -1;
+                }
+            }
+            return transformResults(results);
+        }
+
+        function extractGenerics(val) {
+            val = val.toLowerCase();
+            if (val.indexOf("<") !== -1) {
+                var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
+                return {
+                    name: val.substring(0, val.indexOf("<")),
+                    generics: values.split(/\s*,\s*/),
+                };
+            }
+            return {
+                name: val,
+                generics: [],
+            };
+        }
+
+        function checkGenerics(obj, val) {
+            // The names match, but we need to be sure that all generics kinda
+            // match as well.
+            var tmp_lev, elem_name;
+            if (val.generics.length > 0) {
+                if (obj.length > GENERICS_DATA &&
+                      obj[GENERICS_DATA].length >= val.generics.length) {
+                    var elems = Object.create(null);
+                    var elength = obj[GENERICS_DATA].length;
+                    for (var x = 0; x < elength; ++x) {
+                        if (!elems[obj[GENERICS_DATA][x]]) {
+                            elems[obj[GENERICS_DATA][x]] = 0;
+                        }
+                        elems[obj[GENERICS_DATA][x]] += 1;
+                    }
+                    var total = 0;
+                    var done = 0;
+                    // We need to find the type that matches the most to remove it in order
+                    // to move forward.
+                    var vlength = val.generics.length;
+                    for (x = 0; x < vlength; ++x) {
+                        var lev = MAX_LEV_DISTANCE + 1;
+                        var firstGeneric = val.generics[x];
+                        var match = null;
+                        if (elems[firstGeneric]) {
+                            match = firstGeneric;
+                            lev = 0;
+                        } else {
+                            for (elem_name in elems) {
+                                tmp_lev = levenshtein(elem_name, firstGeneric);
+                                if (tmp_lev < lev) {
+                                    lev = tmp_lev;
+                                    match = elem_name;
+                                }
+                            }
+                        }
+                        if (match !== null) {
+                            elems[match] -= 1;
+                            if (elems[match] == 0) {
+                                delete elems[match];
+                            }
+                            total += lev;
+                            done += 1;
+                        } else {
+                            return MAX_LEV_DISTANCE + 1;
+                        }
+                    }
+                    return Math.ceil(total / done);
+                }
+            }
+            return MAX_LEV_DISTANCE + 1;
+        }
+
+        // Check for type name and type generics (if any).
+        function checkType(obj, val, literalSearch) {
+            var lev_distance = MAX_LEV_DISTANCE + 1;
+            var len, x, firstGeneric;
+            if (obj[NAME] === val.name) {
+                if (literalSearch) {
+                    if (val.generics && val.generics.length !== 0) {
+                        if (obj.length > GENERICS_DATA &&
+                             obj[GENERICS_DATA].length > 0) {
+                            var elems = Object.create(null);
+                            len = obj[GENERICS_DATA].length;
+                            for (x = 0; x < len; ++x) {
+                                if (!elems[obj[GENERICS_DATA][x]]) {
+                                    elems[obj[GENERICS_DATA][x]] = 0;
+                                }
+                                elems[obj[GENERICS_DATA][x]] += 1;
+                            }
+
+                            var allFound = true;
+                            len = val.generics.length;
+                            for (x = 0; x < len; ++x) {
+                                firstGeneric = val.generics[x];
+                                if (elems[firstGeneric]) {
+                                    elems[firstGeneric] -= 1;
+                                } else {
+                                    allFound = false;
+                                    break;
+                                }
+                            }
+                            if (allFound) {
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+                    return true;
+                } else {
+                    // If the type has generics but don't match, then it won't return at this point.
+                    // Otherwise, `checkGenerics` will return 0 and it'll return.
+                    if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
+                        var tmp_lev = checkGenerics(obj, val);
+                        if (tmp_lev <= MAX_LEV_DISTANCE) {
+                            return tmp_lev;
+                        }
+                    }
+                }
+            } else if (literalSearch) {
+                if ((!val.generics || val.generics.length === 0) &&
+                      obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+                    return obj[GENERICS_DATA].some(
+                        function(name) {
+                            return name === val.name;
+                        });
+                }
+                return false;
+            }
+            lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
+            if (lev_distance <= MAX_LEV_DISTANCE) {
+                // The generics didn't match but the name kinda did so we give it
+                // a levenshtein distance value that isn't *this* good so it goes
+                // into the search results but not too high.
+                lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
+            } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+                // We can check if the type we're looking for is inside the generics!
+                var olength = obj[GENERICS_DATA].length;
+                for (x = 0; x < olength; ++x) {
+                    lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
+                                            lev_distance);
+                }
+            }
+            // Now whatever happens, the returned distance is "less good" so we should mark it
+            // as such, and so we add 1 to the distance to make it "less good".
+            return lev_distance + 1;
+        }
+
+        function findArg(obj, val, literalSearch, typeFilter) {
+            var lev_distance = MAX_LEV_DISTANCE + 1;
+
+            if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
+                var length = obj.type[INPUTS_DATA].length;
+                for (var i = 0; i < length; i++) {
+                    var tmp = obj.type[INPUTS_DATA][i];
+                    if (!typePassesFilter(typeFilter, tmp[1])) {
+                        continue;
+                    }
+                    tmp = checkType(tmp, val, literalSearch);
+                    if (literalSearch) {
+                        if (tmp) {
+                            return true;
+                        }
+                        continue;
+                    }
+                    lev_distance = Math.min(tmp, lev_distance);
+                    if (lev_distance === 0) {
+                        return 0;
+                    }
+                }
+            }
+            return literalSearch ? false : lev_distance;
+        }
+
+        function checkReturned(obj, val, literalSearch, typeFilter) {
+            var lev_distance = MAX_LEV_DISTANCE + 1;
+
+            if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
+                var ret = obj.type[OUTPUT_DATA];
+                if (typeof ret[0] === "string") {
+                    ret = [ret];
+                }
+                for (var x = 0, len = ret.length; x < len; ++x) {
+                    var tmp = ret[x];
+                    if (!typePassesFilter(typeFilter, tmp[1])) {
+                        continue;
+                    }
+                    tmp = checkType(tmp, val, literalSearch);
+                    if (literalSearch) {
+                        if (tmp) {
+                            return true;
+                        }
+                        continue;
+                    }
+                    lev_distance = Math.min(tmp, lev_distance);
+                    if (lev_distance === 0) {
+                        return 0;
+                    }
+                }
+            }
+            return literalSearch ? false : lev_distance;
+        }
+
+        function checkPath(contains, lastElem, ty) {
+            if (contains.length === 0) {
+                return 0;
+            }
+            var ret_lev = MAX_LEV_DISTANCE + 1;
+            var path = ty.path.split("::");
+
+            if (ty.parent && ty.parent.name) {
+                path.push(ty.parent.name.toLowerCase());
+            }
+
+            var length = path.length;
+            var clength = contains.length;
+            if (clength > length) {
+                return MAX_LEV_DISTANCE + 1;
+            }
+            for (var i = 0; i < length; ++i) {
+                if (i + clength > length) {
+                    break;
+                }
+                var lev_total = 0;
+                var aborted = false;
+                for (var x = 0; x < clength; ++x) {
+                    var lev = levenshtein(path[i + x], contains[x]);
+                    if (lev > MAX_LEV_DISTANCE) {
+                        aborted = true;
+                        break;
+                    }
+                    lev_total += lev;
+                }
+                if (!aborted) {
+                    ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
+                }
+            }
+            return ret_lev;
+        }
+
+        function typePassesFilter(filter, type) {
+            // No filter
+            if (filter <= NO_TYPE_FILTER) return true;
+
+            // Exact match
+            if (filter === type) return true;
+
+            // Match related items
+            var name = itemTypes[type];
+            switch (itemTypes[filter]) {
+                case "constant":
+                    return name === "associatedconstant";
+                case "fn":
+                    return name === "method" || name === "tymethod";
+                case "type":
+                    return name === "primitive" || name === "associatedtype";
+                case "trait":
+                    return name === "traitalias";
+            }
+
+            // No match
+            return false;
+        }
+
+        function createAliasFromItem(item) {
+            return {
+                crate: item.crate,
+                name: item.name,
+                path: item.path,
+                desc: item.desc,
+                ty: item.ty,
+                parent: item.parent,
+                type: item.type,
+                is_alias: true,
+            };
+        }
+
+        function handleAliases(ret, query, filterCrates) {
+            // We separate aliases and crate aliases because we want to have current crate
+            // aliases to be before the others in the displayed results.
+            var aliases = [];
+            var crateAliases = [];
+            if (filterCrates !== undefined) {
+                if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
+                    var query_aliases = ALIASES[filterCrates][query.search];
+                    var len = query_aliases.length;
+                    for (var i = 0; i < len; ++i) {
+                        aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
+                    }
+                }
+            } else {
+                Object.keys(ALIASES).forEach(function(crate) {
+                    if (ALIASES[crate][query.search]) {
+                        var pushTo = crate === window.currentCrate ? crateAliases : aliases;
+                        var query_aliases = ALIASES[crate][query.search];
+                        var len = query_aliases.length;
+                        for (var i = 0; i < len; ++i) {
+                            pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
+                        }
+                    }
+                });
+            }
+
+            var sortFunc = function(aaa, bbb) {
+                if (aaa.path < bbb.path) {
+                    return 1;
+                } else if (aaa.path === bbb.path) {
+                    return 0;
+                }
+                return -1;
+            };
+            crateAliases.sort(sortFunc);
+            aliases.sort(sortFunc);
+
+            var pushFunc = function(alias) {
+                alias.alias = query.raw;
+                var res = buildHrefAndPath(alias);
+                alias.displayPath = pathSplitter(res[0]);
+                alias.fullPath = alias.displayPath + alias.name;
+                alias.href = res[1];
+
+                ret.others.unshift(alias);
+                if (ret.others.length > MAX_RESULTS) {
+                    ret.others.pop();
+                }
+            };
+            onEach(aliases, pushFunc);
+            onEach(crateAliases, pushFunc);
+        }
+
+        // quoted values mean literal search
+        var nSearchWords = searchWords.length;
+        var i, it;
+        var ty;
+        var fullId;
+        var returned;
+        var in_args;
+        var len;
+        if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
+            val.charAt(val.length - 1) === val.charAt(0))
+        {
+            val = extractGenerics(val.substr(1, val.length - 2));
+            for (i = 0; i < nSearchWords; ++i) {
+                if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+                    continue;
+                }
+                in_args = findArg(searchIndex[i], val, true, typeFilter);
+                returned = checkReturned(searchIndex[i], val, true, typeFilter);
+                ty = searchIndex[i];
+                fullId = ty.id;
+
+                if (searchWords[i] === val.name
+                    && typePassesFilter(typeFilter, searchIndex[i].ty)
+                    && results[fullId] === undefined) {
+                    results[fullId] = {
+                        id: i,
+                        index: -1,
+                        dontValidate: true,
+                    };
+                }
+                if (in_args && results_in_args[fullId] === undefined) {
+                    results_in_args[fullId] = {
+                        id: i,
+                        index: -1,
+                        dontValidate: true,
+                    };
+                }
+                if (returned && results_returned[fullId] === undefined) {
+                    results_returned[fullId] = {
+                        id: i,
+                        index: -1,
+                        dontValidate: true,
+                    };
+                }
+            }
+            query.inputs = [val];
+            query.output = val;
+            query.search = val;
+        // searching by type
+        } else if (val.search("->") > -1) {
+            var trimmer = function(s) { return s.trim(); };
+            var parts = val.split("->").map(trimmer);
+            var input = parts[0];
+            // sort inputs so that order does not matter
+            var inputs = input.split(",").map(trimmer).sort();
+            for (i = 0, len = inputs.length; i < len; ++i) {
+                inputs[i] = extractGenerics(inputs[i]);
+            }
+            var output = extractGenerics(parts[1]);
+
+            for (i = 0; i < nSearchWords; ++i) {
+                if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+                    continue;
+                }
+                var type = searchIndex[i].type;
+                ty = searchIndex[i];
+                if (!type) {
+                    continue;
+                }
+                fullId = ty.id;
+
+                returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
+                if (output.name === "*" || returned) {
+                    in_args = false;
+                    var is_module = false;
+
+                    if (input === "*") {
+                        is_module = true;
+                    } else {
+                        var allFound = true;
+                        for (it = 0, len = inputs.length; allFound && it < len; it++) {
+                            allFound = checkType(type, inputs[it], true);
+                        }
+                        in_args = allFound;
+                    }
+                    if (in_args) {
+                        results_in_args[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                    if (returned) {
+                        results_returned[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                    if (is_module) {
+                        results[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                }
+            }
+            query.inputs = inputs.map(function(input) {
+                return input.name;
+            });
+            query.output = output.name;
+        } else {
+            query.inputs = [val];
+            query.output = val;
+            query.search = val;
+            // gather matching search results up to a certain maximum
+            val = val.replace(/_/g, "");
+
+            var valGenerics = extractGenerics(val);
+
+            var paths = valLower.split("::");
+            removeEmptyStringsFromArray(paths);
+            val = paths[paths.length - 1];
+            var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
+
+            var lev, j;
+            for (j = 0; j < nSearchWords; ++j) {
+                ty = searchIndex[j];
+                if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
+                    continue;
+                }
+                var lev_add = 0;
+                if (paths.length > 1) {
+                    lev = checkPath(contains, paths[paths.length - 1], ty);
+                    if (lev > MAX_LEV_DISTANCE) {
+                        continue;
+                    } else if (lev > 0) {
+                        lev_add = lev / 10;
+                    }
+                }
+
+                returned = MAX_LEV_DISTANCE + 1;
+                in_args = MAX_LEV_DISTANCE + 1;
+                var index = -1;
+                // we want lev results to go lower than others
+                lev = MAX_LEV_DISTANCE + 1;
+                fullId = ty.id;
+
+                if (searchWords[j].indexOf(split[i]) > -1 ||
+                    searchWords[j].indexOf(val) > -1 ||
+                    ty.normalizedName.indexOf(val) > -1)
+                {
+                    // filter type: ... queries
+                    if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
+                        index = ty.normalizedName.indexOf(val);
+                    }
+                }
+                if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
+                    if (typePassesFilter(typeFilter, ty.ty)) {
+                        lev += 1;
+                    } else {
+                        lev = MAX_LEV_DISTANCE + 1;
+                    }
+                }
+                in_args = findArg(ty, valGenerics, false, typeFilter);
+                returned = checkReturned(ty, valGenerics, false, typeFilter);
+
+                lev += lev_add;
+                if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
+                    if (val.length < 6) {
+                        lev -= 1;
+                    } else {
+                        lev = 0;
+                    }
+                }
+                if (in_args <= MAX_LEV_DISTANCE) {
+                    if (results_in_args[fullId] === undefined) {
+                        results_in_args[fullId] = {
+                            id: j,
+                            index: index,
+                            lev: in_args,
+                        };
+                    }
+                    results_in_args[fullId].lev =
+                        Math.min(results_in_args[fullId].lev, in_args);
+                }
+                if (returned <= MAX_LEV_DISTANCE) {
+                    if (results_returned[fullId] === undefined) {
+                        results_returned[fullId] = {
+                            id: j,
+                            index: index,
+                            lev: returned,
+                        };
+                    }
+                    results_returned[fullId].lev =
+                        Math.min(results_returned[fullId].lev, returned);
+                }
+                if (typePassesFilter(typeFilter, ty.ty) &&
+                        (index !== -1 || lev <= MAX_LEV_DISTANCE)) {
+                    if (index !== -1 && paths.length < 2) {
+                        lev = 0;
+                    }
+                    if (results[fullId] === undefined) {
+                        results[fullId] = {
+                            id: j,
+                            index: index,
+                            lev: lev,
+                        };
+                    }
+                    results[fullId].lev = Math.min(results[fullId].lev, lev);
+                }
+            }
+        }
+
+        var ret = {
+            "in_args": sortResults(results_in_args, true),
+            "returned": sortResults(results_returned, true),
+            "others": sortResults(results, false),
+        };
+        handleAliases(ret, query, filterCrates);
+        return ret;
+    }
+
+    /**
+     * Validate performs the following boolean logic. For example:
+     * "File::open" will give IF A PARENT EXISTS => ("file" && "open")
+     * exists in (name || path || parent) OR => ("file" && "open") exists in
+     * (name || path )
+     *
+     * This could be written functionally, but I wanted to minimise
+     * functions on stack.
+     *
+     * @param  {[string]} name   [The name of the result]
+     * @param  {[string]} path   [The path of the result]
+     * @param  {[string]} keys   [The keys to be used (["file", "open"])]
+     * @param  {[object]} parent [The parent of the result]
+     * @return {boolean}       [Whether the result is valid or not]
+     */
+    function validateResult(name, path, keys, parent) {
+        for (var i = 0, len = keys.length; i < len; ++i) {
+            // each check is for validation so we negate the conditions and invalidate
+            if (!(
+                // check for an exact name match
+                name.indexOf(keys[i]) > -1 ||
+                // then an exact path match
+                path.indexOf(keys[i]) > -1 ||
+                // next if there is a parent, check for exact parent match
+                (parent !== undefined && parent.name !== undefined &&
+                    parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
+                // lastly check to see if the name was a levenshtein match
+                levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    function getQuery(raw) {
+        var matches, type, query;
+        query = raw;
+
+        matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
+        if (matches) {
+            type = matches[1].replace(/^const$/, "constant");
+            query = query.substring(matches[0].length);
+        }
+
+        return {
+            raw: raw,
+            query: query,
+            type: type,
+            id: query + type
+        };
+    }
+
+    function nextTab(direction) {
+        var next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length;
+        searchState.focusedByTab[searchState.currentTab] = document.activeElement;
+        printTab(next);
+        focusSearchResult();
+    }
+
+    // Focus the first search result on the active tab, or the result that
+    // was focused last time this tab was active.
+    function focusSearchResult() {
+        var target = searchState.focusedByTab[searchState.currentTab] ||
+            document.querySelectorAll(".search-results.active a").item(0) ||
+            document.querySelectorAll("#titles > button").item(searchState.currentTab);
+        if (target) {
+            target.focus();
+        }
+    }
+
+    function buildHrefAndPath(item) {
+        var displayPath;
+        var href;
+        var type = itemTypes[item.ty];
+        var name = item.name;
+        var path = item.path;
+
+        if (type === "mod") {
+            displayPath = path + "::";
+            href = window.rootPath + path.replace(/::/g, "/") + "/" +
+                   name + "/index.html";
+        } else if (type === "primitive" || type === "keyword") {
+            displayPath = "";
+            href = window.rootPath + path.replace(/::/g, "/") +
+                   "/" + type + "." + name + ".html";
+        } else if (type === "externcrate") {
+            displayPath = "";
+            href = window.rootPath + name + "/index.html";
+        } else if (item.parent !== undefined) {
+            var myparent = item.parent;
+            var anchor = "#" + type + "." + name;
+            var parentType = itemTypes[myparent.ty];
+            var pageType = parentType;
+            var pageName = myparent.name;
+
+            if (parentType === "primitive") {
+                displayPath = myparent.name + "::";
+            } else if (type === "structfield" && parentType === "variant") {
+                // Structfields belonging to variants are special: the
+                // final path element is the enum name.
+                var enumNameIdx = item.path.lastIndexOf("::");
+                var enumName = item.path.substr(enumNameIdx + 2);
+                path = item.path.substr(0, enumNameIdx);
+                displayPath = path + "::" + enumName + "::" + myparent.name + "::";
+                anchor = "#variant." + myparent.name + ".field." + name;
+                pageType = "enum";
+                pageName = enumName;
+            } else {
+                displayPath = path + "::" + myparent.name + "::";
+            }
+            href = window.rootPath + path.replace(/::/g, "/") +
+                   "/" + pageType +
+                   "." + pageName +
+                   ".html" + anchor;
+        } else {
+            displayPath = item.path + "::";
+            href = window.rootPath + item.path.replace(/::/g, "/") +
+                   "/" + type + "." + name + ".html";
+        }
+        return [displayPath, href];
+    }
+
+    function escape(content) {
+        var h1 = document.createElement("h1");
+        h1.textContent = content;
+        return h1.innerHTML;
+    }
+
+    function pathSplitter(path) {
+        var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
+        if (tmp.endsWith("<span>")) {
+            return tmp.slice(0, tmp.length - 6);
+        }
+        return tmp;
+    }
+
+    function addTab(array, query, display) {
+        var extraClass = "";
+        if (display === true) {
+            extraClass = " active";
+        }
+
+        var output = document.createElement("div");
+        var duplicates = {};
+        var length = 0;
+        if (array.length > 0) {
+            output.className = "search-results " + extraClass;
+
+            array.forEach(function(item) {
+                if (item.is_alias !== true) {
+                    if (duplicates[item.fullPath]) {
+                        return;
+                    }
+                    duplicates[item.fullPath] = true;
+                }
+
+                var name = item.name;
+                var type = itemTypes[item.ty];
+
+                length += 1;
+
+                var extra = "";
+                if (type === "primitive") {
+                    extra = " <i>(primitive type)</i>";
+                } else if (type === "keyword") {
+                    extra = " <i>(keyword)</i>";
+                }
+
+                var link = document.createElement("a");
+                link.className = "result-" + type;
+                link.href = item.href;
+
+                var wrapper = document.createElement("div");
+                var resultName = document.createElement("div");
+                resultName.className = "result-name";
+
+                if (item.is_alias) {
+                    var alias = document.createElement("span");
+                    alias.className = "alias";
+
+                    var bold = document.createElement("b");
+                    bold.innerText = item.alias;
+                    alias.appendChild(bold);
+
+                    alias.insertAdjacentHTML(
+                        "beforeend",
+                        "<span class=\"grey\"><i>&nbsp;- see&nbsp;</i></span>");
+
+                    resultName.appendChild(alias);
+                }
+                resultName.insertAdjacentHTML(
+                    "beforeend",
+                    item.displayPath + "<span class=\"" + type + "\">" + name + extra + "</span>");
+                wrapper.appendChild(resultName);
+
+                var description = document.createElement("div");
+                description.className = "desc";
+                var spanDesc = document.createElement("span");
+                spanDesc.insertAdjacentHTML("beforeend", item.desc);
+
+                description.appendChild(spanDesc);
+                wrapper.appendChild(description);
+                link.appendChild(wrapper);
+                output.appendChild(link);
+            });
+        } else {
+            output.className = "search-failed" + extraClass;
+            output.innerHTML = "No results :(<br/>" +
+                "Try on <a href=\"https://duckduckgo.com/?q=" +
+                encodeURIComponent("rust " + query.query) +
+                "\">DuckDuckGo</a>?<br/><br/>" +
+                "Or try looking in one of these:<ul><li>The <a " +
+                "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
+                " for technical details about the language.</li><li><a " +
+                "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
+                "Example</a> for expository code examples.</a></li><li>The <a " +
+                "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
+                "introductions to language features and the language itself.</li><li><a " +
+                "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
+                " <a href=\"https://crates.io/\">crates.io</a>.</li></ul>";
+        }
+        return [output, length];
+    }
+
+    function makeTabHeader(tabNb, text, nbElems) {
+        if (searchState.currentTab === tabNb) {
+            return "<button class=\"selected\">" + text +
+                   " <div class=\"count\">(" + nbElems + ")</div></button>";
+        }
+        return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
+    }
+
+    function showResults(results, go_to_first) {
+        var search = searchState.outputElement();
+        if (go_to_first || (results.others.length === 1
+            && getSettingValue("go-to-only-result") === "true"
+            // By default, the search DOM element is "empty" (meaning it has no children not
+            // text content). Once a search has been run, it won't be empty, even if you press
+            // ESC or empty the search input (which also "cancels" the search).
+            && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)))
+        {
+            var elem = document.createElement("a");
+            elem.href = results.others[0].href;
+            removeClass(elem, "active");
+            // For firefox, we need the element to be in the DOM so it can be clicked.
+            document.body.appendChild(elem);
+            elem.click();
+            return;
+        }
+        var query = getQuery(searchState.input.value);
+
+        currentResults = query.id;
+
+        var ret_others = addTab(results.others, query);
+        var ret_in_args = addTab(results.in_args, query, false);
+        var ret_returned = addTab(results.returned, query, false);
+
+        // Navigate to the relevant tab if the current tab is empty, like in case users search
+        // for "-> String". If they had selected another tab previously, they have to click on
+        // it again.
+        var currentTab = searchState.currentTab;
+        if ((currentTab === 0 && ret_others[1] === 0) ||
+                (currentTab === 1 && ret_in_args[1] === 0) ||
+                (currentTab === 2 && ret_returned[1] === 0)) {
+            if (ret_others[1] !== 0) {
+                currentTab = 0;
+            } else if (ret_in_args[1] !== 0) {
+                currentTab = 1;
+            } else if (ret_returned[1] !== 0) {
+                currentTab = 2;
+            }
+        }
+
+        var output = "<h1>Results for " + escape(query.query) +
+            (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
+            "<div id=\"titles\">" +
+            makeTabHeader(0, "In Names", ret_others[1]) +
+            makeTabHeader(1, "In Parameters", ret_in_args[1]) +
+            makeTabHeader(2, "In Return Types", ret_returned[1]) +
+            "</div>";
+
+        var resultsElem = document.createElement("div");
+        resultsElem.id = "results";
+        resultsElem.appendChild(ret_others[0]);
+        resultsElem.appendChild(ret_in_args[0]);
+        resultsElem.appendChild(ret_returned[0]);
+
+        search.innerHTML = output;
+        search.appendChild(resultsElem);
+        // Reset focused elements.
+        searchState.focusedByTab = [null, null, null];
+        searchState.showResults(search);
+        var elems = document.getElementById("titles").childNodes;
+        elems[0].onclick = function() { printTab(0); };
+        elems[1].onclick = function() { printTab(1); };
+        elems[2].onclick = function() { printTab(2); };
+        printTab(currentTab);
+    }
+
+    function execSearch(query, searchWords, filterCrates) {
+        function getSmallest(arrays, positions, notDuplicates) {
+            var start = null;
+
+            for (var it = 0, len = positions.length; it < len; ++it) {
+                if (arrays[it].length > positions[it] &&
+                    (start === null || start > arrays[it][positions[it]].lev) &&
+                    !notDuplicates[arrays[it][positions[it]].fullPath]) {
+                    start = arrays[it][positions[it]].lev;
+                }
+            }
+            return start;
+        }
+
+        function mergeArrays(arrays) {
+            var ret = [];
+            var positions = [];
+            var notDuplicates = {};
+
+            for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
+                positions.push(0);
+            }
+            while (ret.length < MAX_RESULTS) {
+                var smallest = getSmallest(arrays, positions, notDuplicates);
+
+                if (smallest === null) {
+                    break;
+                }
+                for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
+                    if (arrays[x].length > positions[x] &&
+                            arrays[x][positions[x]].lev === smallest &&
+                            !notDuplicates[arrays[x][positions[x]].fullPath]) {
+                        ret.push(arrays[x][positions[x]]);
+                        notDuplicates[arrays[x][positions[x]].fullPath] = true;
+                        positions[x] += 1;
+                    }
+                }
+            }
+            return ret;
+        }
+
+        // Split search query by ",", while respecting angle bracket nesting.
+        // Since "<" is an alias for the Ord family of traits, it also uses
+        // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket.
+        //
+        // tokenizeQuery("A<B, C>, D") == ["A<B, C>", "D"]
+        // tokenizeQuery("A<B, C, D") == ["A<B", "C", "D"]
+        function tokenizeQuery(raw) {
+            var i, matched;
+            var l = raw.length;
+            var depth = 0;
+            var nextAngle = /(<|>)/g;
+            var ret = [];
+            var start = 0;
+            for (i = 0; i < l; ++i) {
+                switch (raw[i]) {
+                    case "<":
+                        nextAngle.lastIndex = i + 1;
+                        matched = nextAngle.exec(raw);
+                        if (matched && matched[1] === '>') {
+                            depth += 1;
+                        }
+                        break;
+                    case ">":
+                        if (depth > 0) {
+                            depth -= 1;
+                        }
+                        break;
+                    case ",":
+                        if (depth === 0) {
+                            ret.push(raw.substring(start, i));
+                            start = i + 1;
+                        }
+                        break;
+                }
+            }
+            if (start !== i) {
+                ret.push(raw.substring(start, i));
+            }
+            return ret;
+        }
+
+        var queries = tokenizeQuery(query.raw);
+        var results = {
+            "in_args": [],
+            "returned": [],
+            "others": [],
+        };
+
+        for (var i = 0, len = queries.length; i < len; ++i) {
+            query = queries[i].trim();
+            if (query.length !== 0) {
+                var tmp = execQuery(getQuery(query), searchWords, filterCrates);
+
+                results.in_args.push(tmp.in_args);
+                results.returned.push(tmp.returned);
+                results.others.push(tmp.others);
+            }
+        }
+        if (queries.length > 1) {
+            return {
+                "in_args": mergeArrays(results.in_args),
+                "returned": mergeArrays(results.returned),
+                "others": mergeArrays(results.others),
+            };
+        }
+        return {
+            "in_args": results.in_args[0],
+            "returned": results.returned[0],
+            "others": results.others[0],
+        };
+    }
+
+    function getFilterCrates() {
+        var elem = document.getElementById("crate-search");
+
+        if (elem && elem.value !== "All crates" &&
+            hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
+        {
+            return elem.value;
+        }
+        return undefined;
+    }
+
+    function search(e, forced) {
+        var params = searchState.getQueryStringParams();
+        var query = getQuery(searchState.input.value.trim());
+
+        if (e) {
+            e.preventDefault();
+        }
+
+        if (query.query.length === 0) {
+            return;
+        }
+        if (!forced && query.id === currentResults) {
+            if (query.query.length > 0) {
+                searchState.putBackSearch(searchState.input);
+            }
+            return;
+        }
+
+        // Update document title to maintain a meaningful browser history
+        searchState.title = "Results for " + query.query + " - Rust";
+
+        // Because searching is incremental by character, only the most
+        // recent search query is added to the browser history.
+        if (searchState.browserSupportsHistoryApi()) {
+            var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
+                window.location.hash;
+            if (!history.state && !params.search) {
+                history.pushState(query, "", newURL);
+            } else {
+                history.replaceState(query, "", newURL);
+            }
+        }
+
+        var filterCrates = getFilterCrates();
+        showResults(execSearch(query, index, filterCrates), params.go_to_first);
+    }
+
+    function buildIndex(rawSearchIndex) {
+        searchIndex = [];
+        var searchWords = [];
+        var i, word;
+        var currentIndex = 0;
+        var id = 0;
+
+        for (var crate in rawSearchIndex) {
+            if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
+                continue;
+            }
+
+            var crateSize = 0;
+
+            searchWords.push(crate);
+            // This object should have exactly the same set of fields as the "row"
+            // object defined below. Your JavaScript runtime will thank you.
+            // https://mathiasbynens.be/notes/shapes-ics
+            var crateRow = {
+                crate: crate,
+                ty: 1, // == ExternCrate
+                name: crate,
+                path: "",
+                desc: rawSearchIndex[crate].doc,
+                parent: undefined,
+                type: null,
+                id: id,
+                normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
+            };
+            id += 1;
+            searchIndex.push(crateRow);
+            currentIndex += 1;
+
+            // an array of (Number) item types
+            var itemTypes = rawSearchIndex[crate].t;
+            // an array of (String) item names
+            var itemNames = rawSearchIndex[crate].n;
+            // an array of (String) full paths (or empty string for previous path)
+            var itemPaths = rawSearchIndex[crate].q;
+            // an array of (String) descriptions
+            var itemDescs = rawSearchIndex[crate].d;
+            // an array of (Number) the parent path index + 1 to `paths`, or 0 if none
+            var itemParentIdxs = rawSearchIndex[crate].i;
+            // an array of (Object | null) the type of the function, if any
+            var itemFunctionSearchTypes = rawSearchIndex[crate].f;
+            // an array of [(Number) item type,
+            //              (String) name]
+            var paths = rawSearchIndex[crate].p;
+            // a array of [(String) alias name
+            //             [Number] index to items]
+            var aliases = rawSearchIndex[crate].a;
+
+            // convert `rawPaths` entries into object form
+            var len = paths.length;
+            for (i = 0; i < len; ++i) {
+                paths[i] = {ty: paths[i][0], name: paths[i][1]};
+            }
+
+            // convert `item*` into an object form, and construct word indices.
+            //
+            // before any analysis is performed lets gather the search terms to
+            // search against apart from the rest of the data.  This is a quick
+            // operation that is cached for the life of the page state so that
+            // all other search operations have access to this cached data for
+            // faster analysis operations
+            len = itemTypes.length;
+            var lastPath = "";
+            for (i = 0; i < len; ++i) {
+                // This object should have exactly the same set of fields as the "crateRow"
+                // object defined above.
+                if (typeof itemNames[i] === "string") {
+                    word = itemNames[i].toLowerCase();
+                    searchWords.push(word);
+                } else {
+                    word = "";
+                    searchWords.push("");
+                }
+                var row = {
+                    crate: crate,
+                    ty: itemTypes[i],
+                    name: itemNames[i],
+                    path: itemPaths[i] ? itemPaths[i] : lastPath,
+                    desc: itemDescs[i],
+                    parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
+                    type: itemFunctionSearchTypes[i],
+                    id: id,
+                    normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
+                };
+                id += 1;
+                searchIndex.push(row);
+                lastPath = row.path;
+                crateSize += 1;
+            }
+
+            if (aliases) {
+                ALIASES[crate] = {};
+                var j, local_aliases;
+                for (var alias_name in aliases) {
+                    if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
+                        continue;
+                    }
+
+                    if (!hasOwnPropertyRustdoc(ALIASES[crate], alias_name)) {
+                        ALIASES[crate][alias_name] = [];
+                    }
+                    local_aliases = aliases[alias_name];
+                    for (j = 0, len = local_aliases.length; j < len; ++j) {
+                        ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
+                    }
+                }
+            }
+            currentIndex += crateSize;
+        }
+        return searchWords;
+    }
+
+    function registerSearchEvents() {
+        var searchAfter500ms = function() {
+            searchState.clearInputTimeout();
+            if (searchState.input.value.length === 0) {
+                if (searchState.browserSupportsHistoryApi()) {
+                    history.replaceState("", window.currentCrate + " - Rust",
+                        getNakedUrl() + window.location.hash);
+                }
+                searchState.hideResults();
+            } else {
+                searchState.timeout = setTimeout(search, 500);
+            }
+        };
+        searchState.input.onkeyup = searchAfter500ms;
+        searchState.input.oninput = searchAfter500ms;
+        document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
+            e.preventDefault();
+            searchState.clearInputTimeout();
+            search();
+        };
+        searchState.input.onchange = function(e) {
+            if (e.target !== document.activeElement) {
+                // To prevent doing anything when it's from a blur event.
+                return;
+            }
+            // Do NOT e.preventDefault() here. It will prevent pasting.
+            searchState.clearInputTimeout();
+            // zero-timeout necessary here because at the time of event handler execution the
+            // pasted content is not in the input field yet. Shouldn’t make any difference for
+            // change, though.
+            setTimeout(search, 0);
+        };
+        searchState.input.onpaste = searchState.input.onchange;
+
+        searchState.outputElement().addEventListener("keydown", function(e) {
+            // We only handle unmodified keystrokes here. We don't want to interfere with,
+            // for instance, alt-left and alt-right for history navigation.
+            if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
+                return;
+            }
+            // up and down arrow select next/previous search result, or the
+            // search box if we're already at the top.
+            if (e.which === 38) { // up
+                var previous = document.activeElement.previousElementSibling;
+                if (previous) {
+                    previous.focus();
+                } else {
+                    searchState.focus();
+                }
+                e.preventDefault();
+            } else if (e.which === 40) { // down
+                var next = document.activeElement.nextElementSibling;
+                if (next) {
+                    next.focus();
+                }
+                var rect = document.activeElement.getBoundingClientRect();
+                if (window.innerHeight - rect.bottom < rect.height) {
+                    window.scrollBy(0, rect.height);
+                }
+                e.preventDefault();
+            } else if (e.which === 37) { // left
+                nextTab(-1);
+                e.preventDefault();
+            } else if (e.which === 39) { // right
+                nextTab(1);
+                e.preventDefault();
+            }
+        });
+
+        searchState.input.addEventListener("keydown", function(e) {
+            if (e.which === 40) { // down
+                focusSearchResult();
+                e.preventDefault();
+            }
+        });
+
+
+        var selectCrate = document.getElementById("crate-search");
+        if (selectCrate) {
+            selectCrate.onchange = function() {
+                updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value);
+                // In case you "cut" the entry from the search input, then change the crate filter
+                // before paste back the previous search, you get the old search results without
+                // the filter. To prevent this, we need to remove the previous results.
+                currentResults = null;
+                search(undefined, true);
+            };
+        }
+
+        // Push and pop states are used to add search results to the browser
+        // history.
+        if (searchState.browserSupportsHistoryApi()) {
+            // Store the previous <title> so we can revert back to it later.
+            var previousTitle = document.title;
+
+            window.addEventListener("popstate", function(e) {
+                var params = searchState.getQueryStringParams();
+                // Revert to the previous title manually since the History
+                // API ignores the title parameter.
+                document.title = previousTitle;
+                // When browsing forward to search results the previous
+                // search will be repeated, so the currentResults are
+                // cleared to ensure the search is successful.
+                currentResults = null;
+                // Synchronize search bar with query string state and
+                // perform the search. This will empty the bar if there's
+                // nothing there, which lets you really go back to a
+                // previous state with nothing in the bar.
+                if (params.search && params.search.length > 0) {
+                    searchState.input.value = params.search;
+                    // Some browsers fire "onpopstate" for every page load
+                    // (Chrome), while others fire the event only when actually
+                    // popping a state (Firefox), which is why search() is
+                    // called both here and at the end of the startSearch()
+                    // function.
+                    search(e);
+                } else {
+                    searchState.input.value = "";
+                    // When browsing back from search results the main page
+                    // visibility must be reset.
+                    searchState.hideResults();
+                }
+            });
+        }
+
+        // This is required in firefox to avoid this problem: Navigating to a search result
+        // with the keyboard, hitting enter, and then hitting back would take you back to
+        // the doc page, rather than the search that should overlay it.
+        // This was an interaction between the back-forward cache and our handlers
+        // that try to sync state between the URL and the search input. To work around it,
+        // do a small amount of re-init on page show.
+        window.onpageshow = function(){
+            var qSearch = searchState.getQueryStringParams().search;
+            if (searchState.input.value === "" && qSearch) {
+                searchState.input.value = qSearch;
+            }
+            search();
+        };
+    }
+
+    index = buildIndex(rawSearchIndex);
+    registerSearchEvents();
+    // If there's a search term in the URL, execute the search now.
+    if (searchState.getQueryStringParams().search) {
+        search();
+    }
+};
+
+if (window.searchIndex !== undefined) {
+    initSearch(window.searchIndex);
+}
+
+})();
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
new file mode 100644 (file)
index 0000000..4f10e14
--- /dev/null
@@ -0,0 +1,60 @@
+// Local js definitions:
+/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
+
+(function () {
+    function changeSetting(settingName, value) {
+        updateLocalStorage("rustdoc-" + settingName, value);
+
+        switch (settingName) {
+            case "preferred-dark-theme":
+            case "preferred-light-theme":
+            case "use-system-theme":
+                updateSystemTheme();
+                break;
+        }
+    }
+
+    function handleKey(ev) {
+        // Don't interfere with browser shortcuts
+        if (ev.ctrlKey || ev.altKey || ev.metaKey) {
+            return;
+        }
+        switch (getVirtualKey(ev)) {
+            case "Enter":
+            case "Return":
+            case "Space":
+                ev.target.checked = !ev.target.checked;
+                ev.preventDefault();
+                break;
+        }
+    }
+
+    function setEvents() {
+        onEachLazy(document.getElementsByClassName("slider"), function(elem) {
+            var toggle = elem.previousElementSibling;
+            var settingId = toggle.id;
+            var settingValue = getSettingValue(settingId);
+            if (settingValue !== null) {
+                toggle.checked = settingValue === "true";
+            }
+            toggle.onchange = function() {
+                changeSetting(this.id, this.checked);
+            };
+            toggle.onkeyup = handleKey;
+            toggle.onkeyrelease = handleKey;
+        });
+        onEachLazy(document.getElementsByClassName("select-wrapper"), function(elem) {
+            var select = elem.getElementsByTagName("select")[0];
+            var settingId = select.id;
+            var settingValue = getSettingValue(settingId);
+            if (settingValue !== null) {
+                select.value = settingValue;
+            }
+            select.onchange = function() {
+                changeSetting(this.id, this.value);
+            };
+        });
+    }
+
+    window.addEventListener("DOMContentLoaded", setEvents);
+})();
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
new file mode 100644 (file)
index 0000000..4d9a59f
--- /dev/null
@@ -0,0 +1,249 @@
+// From rust:
+/* global search, sourcesIndex */
+
+// Local js definitions:
+/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, searchState */
+/* global updateLocalStorage */
+(function() {
+
+function getCurrentFilePath() {
+    var parts = window.location.pathname.split("/");
+    var rootPathParts = window.rootPath.split("/");
+
+    for (var i = 0, len = rootPathParts.length; i < len; ++i) {
+        if (rootPathParts[i] === "..") {
+            parts.pop();
+        }
+    }
+    var file = window.location.pathname.substring(parts.join("/").length);
+    if (file.startsWith("/")) {
+        file = file.substring(1);
+    }
+    return file.substring(0, file.length - 5);
+}
+
+function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
+    var name = document.createElement("div");
+    name.className = "name";
+
+    fullPath += elem["name"] + "/";
+
+    name.onclick = function() {
+        if (hasClass(this, "expand")) {
+            removeClass(this, "expand");
+        } else {
+            addClass(this, "expand");
+        }
+    };
+    name.innerText = elem["name"];
+
+    var i, len;
+
+    var children = document.createElement("div");
+    children.className = "children";
+    var folders = document.createElement("div");
+    folders.className = "folders";
+    if (elem.dirs) {
+        for (i = 0, len = elem.dirs.length; i < len; ++i) {
+            if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
+                               hasFoundFile)) {
+                addClass(name, "expand");
+                hasFoundFile = true;
+            }
+        }
+    }
+    children.appendChild(folders);
+
+    var files = document.createElement("div");
+    files.className = "files";
+    if (elem.files) {
+        for (i = 0, len = elem.files.length; i < len; ++i) {
+            var file = document.createElement("a");
+            file.innerText = elem.files[i];
+            file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
+            if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
+                file.className = "selected";
+                addClass(name, "expand");
+                hasFoundFile = true;
+            }
+            files.appendChild(file);
+        }
+    }
+    search.fullPath = fullPath;
+    children.appendChild(files);
+    parent.appendChild(name);
+    parent.appendChild(children);
+    return hasFoundFile && currentFile.startsWith(fullPath);
+}
+
+function toggleSidebar() {
+    var sidebar = document.getElementById("source-sidebar");
+    var child = this.children[0].children[0];
+    if (child.innerText === ">") {
+        sidebar.style.left = "";
+        this.style.left = "";
+        child.innerText = "<";
+        updateLocalStorage("rustdoc-source-sidebar-show", "true");
+    } else {
+        sidebar.style.left = "-300px";
+        this.style.left = "0";
+        child.innerText = ">";
+        updateLocalStorage("rustdoc-source-sidebar-show", "false");
+    }
+}
+
+function createSidebarToggle() {
+    var sidebarToggle = document.createElement("div");
+    sidebarToggle.id = "sidebar-toggle";
+    sidebarToggle.onclick = toggleSidebar;
+
+    var inner1 = document.createElement("div");
+    inner1.style.position = "relative";
+
+    var inner2 = document.createElement("div");
+    inner2.style.paddingTop = "3px";
+    if (getCurrentValue("rustdoc-source-sidebar-show") === "true") {
+        inner2.innerText = "<";
+    } else {
+        inner2.innerText = ">";
+        sidebarToggle.style.left = "0";
+    }
+
+    inner1.appendChild(inner2);
+    sidebarToggle.appendChild(inner1);
+    return sidebarToggle;
+}
+
+// This function is called from "source-files.js", generated in `html/render/mod.rs`.
+// eslint-disable-next-line no-unused-vars
+function createSourceSidebar() {
+    if (!window.rootPath.endsWith("/")) {
+        window.rootPath += "/";
+    }
+    var main = document.getElementById("main");
+
+    var sidebarToggle = createSidebarToggle();
+    main.insertBefore(sidebarToggle, main.firstChild);
+
+    var sidebar = document.createElement("div");
+    sidebar.id = "source-sidebar";
+    if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") {
+        sidebar.style.left = "-300px";
+    }
+
+    var currentFile = getCurrentFilePath();
+    var hasFoundFile = false;
+
+    var title = document.createElement("div");
+    title.className = "title";
+    title.innerText = "Files";
+    sidebar.appendChild(title);
+    Object.keys(sourcesIndex).forEach(function(key) {
+        sourcesIndex[key].name = key;
+        hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
+                                      currentFile, hasFoundFile);
+    });
+
+    main.insertBefore(sidebar, main.firstChild);
+    // Focus on the current file in the source files sidebar.
+    var selected_elem = sidebar.getElementsByClassName("selected")[0];
+    if (typeof selected_elem !== "undefined") {
+        selected_elem.focus();
+    }
+}
+
+var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
+
+function highlightSourceLines(scrollTo, match) {
+    if (typeof match === "undefined") {
+        match = window.location.hash.match(lineNumbersRegex);
+    }
+    if (!match) {
+        return;
+    }
+    var from = parseInt(match[1], 10);
+    var to = from;
+    if (typeof match[2] !== "undefined") {
+        to = parseInt(match[2], 10);
+    }
+    if (to < from) {
+        var tmp = to;
+        to = from;
+        from = tmp;
+    }
+    var elem = document.getElementById(from);
+    if (!elem) {
+        return;
+    }
+    if (scrollTo) {
+        var x = document.getElementById(from);
+        if (x) {
+            x.scrollIntoView();
+        }
+    }
+    onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
+        onEachLazy(e.getElementsByTagName("span"), function(i_e) {
+            removeClass(i_e, "line-highlighted");
+        });
+    });
+    for (var i = from; i <= to; ++i) {
+        elem = document.getElementById(i);
+        if (!elem) {
+            break;
+        }
+        addClass(elem, "line-highlighted");
+    }
+}
+
+var handleSourceHighlight = (function() {
+    var prev_line_id = 0;
+
+    var set_fragment = function(name) {
+        var x = window.scrollX,
+            y = window.scrollY;
+        if (searchState.browserSupportsHistoryApi()) {
+            history.replaceState(null, null, "#" + name);
+            highlightSourceLines(true);
+        } else {
+            location.replace("#" + name);
+        }
+        // Prevent jumps when selecting one or many lines
+        window.scrollTo(x, y);
+    };
+
+    return function(ev) {
+        var cur_line_id = parseInt(ev.target.id, 10);
+        ev.preventDefault();
+
+        if (ev.shiftKey && prev_line_id) {
+            // Swap selection if needed
+            if (prev_line_id > cur_line_id) {
+                var tmp = prev_line_id;
+                prev_line_id = cur_line_id;
+                cur_line_id = tmp;
+            }
+
+            set_fragment(prev_line_id + "-" + cur_line_id);
+        } else {
+            prev_line_id = cur_line_id;
+
+            set_fragment(cur_line_id);
+        }
+    };
+}());
+
+window.addEventListener("hashchange", function() {
+    var match = window.location.hash.match(lineNumbersRegex);
+    if (match) {
+        return highlightSourceLines(false, match);
+    }
+});
+
+onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
+    el.addEventListener("click", handleSourceHighlight);
+});
+
+highlightSourceLines(true);
+
+window.createSourceSidebar = createSourceSidebar;
+})();
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
new file mode 100644 (file)
index 0000000..2eaa81a
--- /dev/null
@@ -0,0 +1,219 @@
+// From rust:
+/* global resourcesSuffix */
+var darkThemes = ["dark", "ayu"];
+window.currentTheme = document.getElementById("themeStyle");
+window.mainTheme = document.getElementById("mainThemeStyle");
+
+var settingsDataset = (function () {
+    var settingsElement = document.getElementById("default-settings");
+    if (settingsElement === null) {
+        return null;
+    }
+    var dataset = settingsElement.dataset;
+    if (dataset === undefined) {
+        return null;
+    }
+    return dataset;
+})();
+
+function getSettingValue(settingName) {
+    var current = getCurrentValue('rustdoc-' + settingName);
+    if (current !== null) {
+        return current;
+    }
+    if (settingsDataset !== null) {
+        var def = settingsDataset[settingName.replace(/-/g,'_')];
+        if (def !== undefined) {
+            return def;
+        }
+    }
+    return null;
+}
+
+var localStoredTheme = getSettingValue("theme");
+
+var savedHref = [];
+
+// eslint-disable-next-line no-unused-vars
+function hasClass(elem, className) {
+    return elem && elem.classList && elem.classList.contains(className);
+}
+
+// eslint-disable-next-line no-unused-vars
+function addClass(elem, className) {
+    if (!elem || !elem.classList) {
+        return;
+    }
+    elem.classList.add(className);
+}
+
+// eslint-disable-next-line no-unused-vars
+function removeClass(elem, className) {
+    if (!elem || !elem.classList) {
+        return;
+    }
+    elem.classList.remove(className);
+}
+
+function onEach(arr, func, reversed) {
+    if (arr && arr.length > 0 && func) {
+        var length = arr.length;
+        var i;
+        if (reversed) {
+            for (i = length - 1; i >= 0; --i) {
+                if (func(arr[i])) {
+                    return true;
+                }
+            }
+        } else {
+            for (i = 0; i < length; ++i) {
+                if (func(arr[i])) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+function onEachLazy(lazyArray, func, reversed) {
+    return onEach(
+        Array.prototype.slice.call(lazyArray),
+        func,
+        reversed);
+}
+
+// eslint-disable-next-line no-unused-vars
+function hasOwnPropertyRustdoc(obj, property) {
+    return Object.prototype.hasOwnProperty.call(obj, property);
+}
+
+function updateLocalStorage(name, value) {
+    try {
+        window.localStorage.setItem(name, value);
+    } catch(e) {
+        // localStorage is not accessible, do nothing
+    }
+}
+
+function getCurrentValue(name) {
+    try {
+        return window.localStorage.getItem(name);
+    } catch(e) {
+        return null;
+    }
+}
+
+function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
+    var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
+    var fullNewTheme = newTheme + resourcesSuffix + ".css";
+    var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
+
+    // If this new value comes from a system setting or from the previously
+    // saved theme, no need to save it.
+    if (saveTheme) {
+        updateLocalStorage("rustdoc-theme", newTheme);
+    }
+
+    if (styleElem.href === newHref) {
+        return;
+    }
+
+    var found = false;
+    if (savedHref.length === 0) {
+        onEachLazy(document.getElementsByTagName("link"), function(el) {
+            savedHref.push(el.href);
+        });
+    }
+    onEach(savedHref, function(el) {
+        if (el === newHref) {
+            found = true;
+            return true;
+        }
+    });
+    if (found) {
+        styleElem.href = newHref;
+    }
+}
+
+// This function is called from "main.js".
+// eslint-disable-next-line no-unused-vars
+function useSystemTheme(value) {
+    if (value === undefined) {
+        value = true;
+    }
+
+    updateLocalStorage("rustdoc-use-system-theme", value);
+
+    // update the toggle if we're on the settings page
+    var toggle = document.getElementById("use-system-theme");
+    if (toggle && toggle instanceof HTMLInputElement) {
+        toggle.checked = value;
+    }
+}
+
+var updateSystemTheme = (function() {
+    if (!window.matchMedia) {
+        // fallback to the CSS computed value
+        return function() {
+            var cssTheme = getComputedStyle(document.documentElement)
+                .getPropertyValue('content');
+
+            switchTheme(
+                window.currentTheme,
+                window.mainTheme,
+                JSON.parse(cssTheme) || "light",
+                true
+            );
+        };
+    }
+
+    // only listen to (prefers-color-scheme: dark) because light is the default
+    var mql = window.matchMedia("(prefers-color-scheme: dark)");
+
+    function handlePreferenceChange(mql) {
+        // maybe the user has disabled the setting in the meantime!
+        if (getSettingValue("use-system-theme") !== "false") {
+            var lightTheme = getSettingValue("preferred-light-theme") || "light";
+            var darkTheme = getSettingValue("preferred-dark-theme") || "dark";
+
+            if (mql.matches) {
+                // prefers a dark theme
+                switchTheme(window.currentTheme, window.mainTheme, darkTheme, true);
+            } else {
+                // prefers a light theme, or has no preference
+                switchTheme(window.currentTheme, window.mainTheme, lightTheme, true);
+            }
+
+            // note: we save the theme so that it doesn't suddenly change when
+            // the user disables "use-system-theme" and reloads the page or
+            // navigates to another page
+        }
+    }
+
+    mql.addListener(handlePreferenceChange);
+
+    return function() {
+        handlePreferenceChange(mql);
+    };
+})();
+
+if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
+    // update the preferred dark theme if the user is already using a dark theme
+    // See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
+    if (getSettingValue("use-system-theme") === null
+        && getSettingValue("preferred-dark-theme") === null
+        && darkThemes.indexOf(localStoredTheme) >= 0) {
+        updateLocalStorage("rustdoc-preferred-dark-theme", localStoredTheme);
+    }
+
+    // call the function to initialize the theme at least once!
+    updateSystemTheme();
+} else {
+    switchTheme(
+        window.currentTheme,
+        window.mainTheme,
+        getSettingValue("theme") || "light",
+        false
+    );
+}
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
deleted file mode 100644 (file)
index 9812887..0000000
+++ /dev/null
@@ -1,1018 +0,0 @@
-// Local js definitions:
-/* global addClass, getSettingValue, hasClass, searchState */
-/* global onEach, onEachLazy, removeClass */
-/* global switchTheme, useSystemTheme */
-
-if (!String.prototype.startsWith) {
-    String.prototype.startsWith = function(searchString, position) {
-        position = position || 0;
-        return this.indexOf(searchString, position) === position;
-    };
-}
-if (!String.prototype.endsWith) {
-    String.prototype.endsWith = function(suffix, length) {
-        var l = length || this.length;
-        return this.indexOf(suffix, l - suffix.length) !== -1;
-    };
-}
-
-if (!DOMTokenList.prototype.add) {
-    DOMTokenList.prototype.add = function(className) {
-        if (className && !hasClass(this, className)) {
-            if (this.className && this.className.length > 0) {
-                this.className += " " + className;
-            } else {
-                this.className = className;
-            }
-        }
-    };
-}
-
-if (!DOMTokenList.prototype.remove) {
-    DOMTokenList.prototype.remove = function(className) {
-        if (className && this.className) {
-            this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
-                                                         .trim();
-        }
-    };
-}
-
-(function () {
-    var rustdocVars = document.getElementById("rustdoc-vars");
-    if (rustdocVars) {
-        window.rootPath = rustdocVars.attributes["data-root-path"].value;
-        window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
-        window.searchJS = rustdocVars.attributes["data-search-js"].value;
-        window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
-    }
-    var sidebarVars = document.getElementById("sidebar-vars");
-    if (sidebarVars) {
-        window.sidebarCurrent = {
-            name: sidebarVars.attributes["data-name"].value,
-            ty: sidebarVars.attributes["data-ty"].value,
-            relpath: sidebarVars.attributes["data-relpath"].value,
-        };
-    }
-}());
-
-// Gets the human-readable string for the virtual-key code of the
-// given KeyboardEvent, ev.
-//
-// This function is meant as a polyfill for KeyboardEvent#key,
-// since it is not supported in IE 11 or Chrome for Android. We also test for
-// KeyboardEvent#keyCode because the handleShortcut handler is
-// also registered for the keydown event, because Blink doesn't fire
-// keypress on hitting the Escape key.
-//
-// So I guess you could say things are getting pretty interoperable.
-function getVirtualKey(ev) {
-    if ("key" in ev && typeof ev.key != "undefined") {
-        return ev.key;
-    }
-
-    var c = ev.charCode || ev.keyCode;
-    if (c == 27) {
-        return "Escape";
-    }
-    return String.fromCharCode(c);
-}
-
-var THEME_PICKER_ELEMENT_ID = "theme-picker";
-var THEMES_ELEMENT_ID = "theme-choices";
-
-function getThemesElement() {
-    return document.getElementById(THEMES_ELEMENT_ID);
-}
-
-function getThemePickerElement() {
-    return document.getElementById(THEME_PICKER_ELEMENT_ID);
-}
-
-// Returns the current URL without any query parameter or hash.
-function getNakedUrl() {
-    return window.location.href.split("?")[0].split("#")[0];
-}
-
-function showThemeButtonState() {
-    var themePicker = getThemePickerElement();
-    var themeChoices = getThemesElement();
-
-    themeChoices.style.display = "block";
-    themePicker.style.borderBottomRightRadius = "0";
-    themePicker.style.borderBottomLeftRadius = "0";
-}
-
-function hideThemeButtonState() {
-    var themePicker = getThemePickerElement();
-    var themeChoices = getThemesElement();
-
-    themeChoices.style.display = "none";
-    themePicker.style.borderBottomRightRadius = "3px";
-    themePicker.style.borderBottomLeftRadius = "3px";
-}
-
-// Set up the theme picker list.
-(function () {
-    var themeChoices = getThemesElement();
-    var themePicker = getThemePickerElement();
-    var availableThemes/* INSERT THEMES HERE */;
-
-    function switchThemeButtonState() {
-        if (themeChoices.style.display === "block") {
-            hideThemeButtonState();
-        } else {
-            showThemeButtonState();
-        }
-    }
-
-    function handleThemeButtonsBlur(e) {
-        var active = document.activeElement;
-        var related = e.relatedTarget;
-
-        if (active.id !== THEME_PICKER_ELEMENT_ID &&
-            (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
-            (!related ||
-             (related.id !== THEME_PICKER_ELEMENT_ID &&
-              (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
-            hideThemeButtonState();
-        }
-    }
-
-    themePicker.onclick = switchThemeButtonState;
-    themePicker.onblur = handleThemeButtonsBlur;
-    availableThemes.forEach(function(item) {
-        var but = document.createElement("button");
-        but.textContent = item;
-        but.onclick = function() {
-            switchTheme(window.currentTheme, window.mainTheme, item, true);
-            useSystemTheme(false);
-        };
-        but.onblur = handleThemeButtonsBlur;
-        themeChoices.appendChild(but);
-    });
-}());
-
-(function() {
-    "use strict";
-
-    window.searchState = {
-        loadingText: "Loading search results...",
-        input: document.getElementsByClassName("search-input")[0],
-        outputElement: function() {
-            return document.getElementById("search");
-        },
-        title: document.title,
-        titleBeforeSearch: document.title,
-        timeout: null,
-        // On the search screen, so you remain on the last tab you opened.
-        //
-        // 0 for "In Names"
-        // 1 for "In Parameters"
-        // 2 for "In Return Types"
-        currentTab: 0,
-        // tab and back preserves the element that was focused.
-        focusedByTab: [null, null, null],
-        clearInputTimeout: function() {
-            if (searchState.timeout !== null) {
-                clearTimeout(searchState.timeout);
-                searchState.timeout = null;
-            }
-        },
-        // Sets the focus on the search bar at the top of the page
-        focus: function() {
-            searchState.input.focus();
-        },
-        // Removes the focus from the search bar.
-        defocus: function() {
-            searchState.input.blur();
-        },
-        showResults: function(search) {
-            if (search === null || typeof search === 'undefined') {
-                search = searchState.outputElement();
-            }
-            addClass(main, "hidden");
-            removeClass(search, "hidden");
-            searchState.mouseMovedAfterSearch = false;
-            document.title = searchState.title;
-        },
-        hideResults: function(search) {
-            if (search === null || typeof search === 'undefined') {
-                search = searchState.outputElement();
-            }
-            addClass(search, "hidden");
-            removeClass(main, "hidden");
-            document.title = searchState.titleBeforeSearch;
-            // We also remove the query parameter from the URL.
-            if (searchState.browserSupportsHistoryApi()) {
-                history.replaceState("", window.currentCrate + " - Rust",
-                    getNakedUrl() + window.location.hash);
-            }
-        },
-        getQueryStringParams: function() {
-            var params = {};
-            window.location.search.substring(1).split("&").
-                map(function(s) {
-                    var pair = s.split("=");
-                    params[decodeURIComponent(pair[0])] =
-                        typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
-                });
-            return params;
-        },
-        putBackSearch: function(search_input) {
-            var search = searchState.outputElement();
-            if (search_input.value !== "" && hasClass(search, "hidden")) {
-                searchState.showResults(search);
-                if (searchState.browserSupportsHistoryApi()) {
-                    var extra = "?search=" + encodeURIComponent(search_input.value);
-                    history.replaceState(search_input.value, "",
-                        getNakedUrl() + extra + window.location.hash);
-                }
-                document.title = searchState.title;
-            }
-        },
-        browserSupportsHistoryApi: function() {
-            return window.history && typeof window.history.pushState === "function";
-        },
-        setup: function() {
-            var search_input = searchState.input;
-            if (!searchState.input) {
-                return;
-            }
-            function loadScript(url) {
-                var script = document.createElement('script');
-                script.src = url;
-                document.head.append(script);
-            }
-
-            var searchLoaded = false;
-            function loadSearch() {
-                if (!searchLoaded) {
-                    searchLoaded = true;
-                    loadScript(window.searchJS);
-                    loadScript(window.searchIndexJS);
-                }
-            }
-
-            search_input.addEventListener("focus", function() {
-                searchState.putBackSearch(this);
-                search_input.origPlaceholder = searchState.input.placeholder;
-                search_input.placeholder = "Type your search here.";
-                loadSearch();
-            });
-            search_input.addEventListener("blur", function() {
-                search_input.placeholder = searchState.input.origPlaceholder;
-            });
-
-            search_input.removeAttribute('disabled');
-
-            // `crates{version}.js` should always be loaded before this script, so we can use it
-            // safely.
-            searchState.addCrateDropdown(window.ALL_CRATES);
-            var params = searchState.getQueryStringParams();
-            if (params.search !== undefined) {
-                var search = searchState.outputElement();
-                search.innerHTML = "<h3 style=\"text-align: center;\">" +
-                   searchState.loadingText + "</h3>";
-                searchState.showResults(search);
-                loadSearch();
-            }
-        },
-        addCrateDropdown: function(crates) {
-            var elem = document.getElementById("crate-search");
-
-            if (!elem) {
-                return;
-            }
-            var savedCrate = getSettingValue("saved-filter-crate");
-            for (var i = 0, len = crates.length; i < len; ++i) {
-                var option = document.createElement("option");
-                option.value = crates[i];
-                option.innerText = crates[i];
-                elem.appendChild(option);
-                // Set the crate filter from saved storage, if the current page has the saved crate
-                // filter.
-                //
-                // If not, ignore the crate filter -- we want to support filtering for crates on
-                // sites like doc.rust-lang.org where the crates may differ from page to page while
-                // on the
-                // same domain.
-                if (crates[i] === savedCrate) {
-                    elem.value = savedCrate;
-                }
-            }
-        },
-    };
-
-    function getPageId() {
-        if (window.location.hash) {
-            var tmp = window.location.hash.replace(/^#/, "");
-            if (tmp.length > 0) {
-                return tmp;
-            }
-        }
-        return null;
-    }
-
-    function showSidebar() {
-        var elems = document.getElementsByClassName("sidebar-elems")[0];
-        if (elems) {
-            addClass(elems, "show-it");
-        }
-        var sidebar = document.getElementsByClassName("sidebar")[0];
-        if (sidebar) {
-            addClass(sidebar, "mobile");
-            var filler = document.getElementById("sidebar-filler");
-            if (!filler) {
-                var div = document.createElement("div");
-                div.id = "sidebar-filler";
-                sidebar.appendChild(div);
-            }
-        }
-    }
-
-    function hideSidebar() {
-        var elems = document.getElementsByClassName("sidebar-elems")[0];
-        if (elems) {
-            removeClass(elems, "show-it");
-        }
-        var sidebar = document.getElementsByClassName("sidebar")[0];
-        removeClass(sidebar, "mobile");
-        var filler = document.getElementById("sidebar-filler");
-        if (filler) {
-            filler.remove();
-        }
-        document.getElementsByTagName("body")[0].style.marginTop = "";
-    }
-
-    var toggleAllDocsId = "toggle-all-docs";
-    var main = document.getElementById("main");
-    var savedHash = "";
-
-    function handleHashes(ev) {
-        var elem;
-        var search = searchState.outputElement();
-        if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
-            // This block occurs when clicking on an element in the navbar while
-            // in a search.
-            searchState.hideResults(search);
-            var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
-            if (searchState.browserSupportsHistoryApi()) {
-                // `window.location.search`` contains all the query parameters, not just `search`.
-                history.replaceState(hash, "",
-                    getNakedUrl() + window.location.search + "#" + hash);
-            }
-            elem = document.getElementById(hash);
-            if (elem) {
-                elem.scrollIntoView();
-            }
-        }
-        // This part is used in case an element is not visible.
-        if (savedHash !== window.location.hash) {
-            savedHash = window.location.hash;
-            if (savedHash.length === 0) {
-                return;
-            }
-            expandSection(savedHash.slice(1)); // we remove the '#'
-        }
-    }
-
-    function onHashChange(ev) {
-        // If we're in mobile mode, we should hide the sidebar in any case.
-        hideSidebar();
-        handleHashes(ev);
-    }
-
-    function openParentDetails(elem) {
-        while (elem) {
-            if (elem.tagName === "DETAILS") {
-                elem.open = true;
-            }
-            elem = elem.parentNode;
-        }
-    }
-
-    function expandSection(id) {
-        openParentDetails(document.getElementById(id));
-    }
-
-    function getHelpElement(build) {
-        if (build) {
-            buildHelperPopup();
-        }
-        return document.getElementById("help");
-    }
-
-    function displayHelp(display, ev, help) {
-        if (display) {
-            help = help ? help : getHelpElement(true);
-            if (hasClass(help, "hidden")) {
-                ev.preventDefault();
-                removeClass(help, "hidden");
-                addClass(document.body, "blur");
-            }
-        } else {
-            // No need to build the help popup if we want to hide it in case it hasn't been
-            // built yet...
-            help = help ? help : getHelpElement(false);
-            if (help && !hasClass(help, "hidden")) {
-                ev.preventDefault();
-                addClass(help, "hidden");
-                removeClass(document.body, "blur");
-            }
-        }
-    }
-
-    function handleEscape(ev) {
-        var help = getHelpElement(false);
-        var search = searchState.outputElement();
-        if (help && !hasClass(help, "hidden")) {
-            displayHelp(false, ev, help);
-        } else if (search && !hasClass(search, "hidden")) {
-            searchState.clearInputTimeout();
-            ev.preventDefault();
-            searchState.hideResults(search);
-        }
-        searchState.defocus();
-        hideThemeButtonState();
-    }
-
-    var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
-    function handleShortcut(ev) {
-        // Don't interfere with browser shortcuts
-        if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
-            return;
-        }
-
-        if (document.activeElement.tagName === "INPUT") {
-            switch (getVirtualKey(ev)) {
-            case "Escape":
-                handleEscape(ev);
-                break;
-            }
-        } else {
-            switch (getVirtualKey(ev)) {
-            case "Escape":
-                handleEscape(ev);
-                break;
-
-            case "s":
-            case "S":
-                displayHelp(false, ev);
-                ev.preventDefault();
-                searchState.focus();
-                break;
-
-            case "+":
-            case "-":
-                ev.preventDefault();
-                toggleAllDocs();
-                break;
-
-            case "?":
-                displayHelp(true, ev);
-                break;
-
-            case "t":
-            case "T":
-                displayHelp(false, ev);
-                ev.preventDefault();
-                var themePicker = getThemePickerElement();
-                themePicker.click();
-                themePicker.focus();
-                break;
-
-            default:
-                if (getThemePickerElement().parentNode.contains(ev.target)) {
-                    handleThemeKeyDown(ev);
-                }
-            }
-        }
-    }
-
-    function handleThemeKeyDown(ev) {
-        var active = document.activeElement;
-        var themes = getThemesElement();
-        switch (getVirtualKey(ev)) {
-        case "ArrowUp":
-            ev.preventDefault();
-            if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
-                active.previousElementSibling.focus();
-            } else {
-                showThemeButtonState();
-                themes.lastElementChild.focus();
-            }
-            break;
-        case "ArrowDown":
-            ev.preventDefault();
-            if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
-                active.nextElementSibling.focus();
-            } else {
-                showThemeButtonState();
-                themes.firstElementChild.focus();
-            }
-            break;
-        case "Enter":
-        case "Return":
-        case "Space":
-            if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
-                ev.preventDefault();
-                showThemeButtonState();
-                themes.firstElementChild.focus();
-            }
-            break;
-        case "Home":
-            ev.preventDefault();
-            themes.firstElementChild.focus();
-            break;
-        case "End":
-            ev.preventDefault();
-            themes.lastElementChild.focus();
-            break;
-        // The escape key is handled in handleEscape, not here,
-        // so that pressing escape will close the menu even if it isn't focused
-        }
-    }
-
-    document.addEventListener("keypress", handleShortcut);
-    document.addEventListener("keydown", handleShortcut);
-
-    (function() {
-        var x = document.getElementsByClassName("version-selector");
-        if (x.length > 0) {
-            x[0].onchange = function() {
-                var i, match,
-                    url = document.location.href,
-                    stripped = "",
-                    len = window.rootPath.match(/\.\.\//g).length + 1;
-
-                for (i = 0; i < len; ++i) {
-                    match = url.match(/\/[^/]*$/);
-                    if (i < len - 1) {
-                        stripped = match[0] + stripped;
-                    }
-                    url = url.substring(0, url.length - match[0].length);
-                }
-
-                var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
-                url += "/" + selectedVersion + stripped;
-
-                document.location.href = url;
-            };
-        }
-    }());
-
-    // delayed sidebar rendering.
-    window.initSidebarItems = function(items) {
-        var sidebar = document.getElementsByClassName("sidebar-elems")[0];
-        var current = window.sidebarCurrent;
-
-        function addSidebarCrates(crates) {
-            if (!hasClass(document.body, "crate")) {
-                // We only want to list crates on the crate page.
-                return;
-            }
-            // Draw a convenient sidebar of known crates if we have a listing
-            var div = document.createElement("div");
-            div.className = "block crate";
-            div.innerHTML = "<h3>Crates</h3>";
-            var ul = document.createElement("ul");
-            div.appendChild(ul);
-
-            for (var i = 0; i < crates.length; ++i) {
-                var klass = "crate";
-                if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
-                    klass += " current";
-                }
-                var link = document.createElement("a");
-                link.href = window.rootPath + crates[i] + "/index.html";
-                link.className = klass;
-                link.textContent = crates[i];
-
-                var li = document.createElement("li");
-                li.appendChild(link);
-                ul.appendChild(li);
-            }
-            sidebar.appendChild(div);
-        }
-
-        function block(shortty, longty) {
-            var filtered = items[shortty];
-            if (!filtered) {
-                return;
-            }
-
-            var div = document.createElement("div");
-            div.className = "block " + shortty;
-            var h3 = document.createElement("h3");
-            h3.textContent = longty;
-            div.appendChild(h3);
-            var ul = document.createElement("ul");
-
-            for (var i = 0, len = filtered.length; i < len; ++i) {
-                var item = filtered[i];
-                var name = item[0];
-                var desc = item[1]; // can be null
-
-                var klass = shortty;
-                if (name === current.name && shortty === current.ty) {
-                    klass += " current";
-                }
-                var path;
-                if (shortty === "mod") {
-                    path = name + "/index.html";
-                } else {
-                    path = shortty + "." + name + ".html";
-                }
-                var link = document.createElement("a");
-                link.href = current.relpath + path;
-                link.title = desc;
-                link.className = klass;
-                link.textContent = name;
-                var li = document.createElement("li");
-                li.appendChild(link);
-                ul.appendChild(li);
-            }
-            div.appendChild(ul);
-            sidebar.appendChild(div);
-        }
-
-        if (sidebar) {
-            var isModule = hasClass(document.body, "mod");
-            if (!isModule) {
-                block("primitive", "Primitive Types");
-                block("mod", "Modules");
-                block("macro", "Macros");
-                block("struct", "Structs");
-                block("enum", "Enums");
-                block("union", "Unions");
-                block("constant", "Constants");
-                block("static", "Statics");
-                block("trait", "Traits");
-                block("fn", "Functions");
-                block("type", "Type Definitions");
-                block("foreigntype", "Foreign Types");
-                block("keyword", "Keywords");
-                block("traitalias", "Trait Aliases");
-            }
-
-            // `crates{version}.js` should always be loaded before this script, so we can use
-            // it safely.
-            addSidebarCrates(window.ALL_CRATES);
-        }
-    };
-
-    window.register_implementors = function(imp) {
-        var implementors = document.getElementById("implementors-list");
-        var synthetic_implementors = document.getElementById("synthetic-implementors-list");
-
-        if (synthetic_implementors) {
-            // This `inlined_types` variable is used to avoid having the same implementation
-            // showing up twice. For example "String" in the "Sync" doc page.
-            //
-            // By the way, this is only used by and useful for traits implemented automatically
-            // (like "Send" and "Sync").
-            var inlined_types = new Set();
-            onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
-                var aliases = el.getAttribute("data-aliases");
-                if (!aliases) {
-                    return;
-                }
-                aliases.split(",").forEach(function(alias) {
-                    inlined_types.add(alias);
-                });
-            });
-        }
-
-        var libs = Object.getOwnPropertyNames(imp);
-        for (var i = 0, llength = libs.length; i < llength; ++i) {
-            if (libs[i] === window.currentCrate) { continue; }
-            var structs = imp[libs[i]];
-
-            struct_loop:
-            for (var j = 0, slength = structs.length; j < slength; ++j) {
-                var struct = structs[j];
-
-                var list = struct.synthetic ? synthetic_implementors : implementors;
-
-                if (struct.synthetic) {
-                    for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
-                        if (inlined_types.has(struct.types[k])) {
-                            continue struct_loop;
-                        }
-                        inlined_types.add(struct.types[k]);
-                    }
-                }
-
-                var code = document.createElement("code");
-                code.innerHTML = struct.text;
-
-                onEachLazy(code.getElementsByTagName("a"), function(elem) {
-                    var href = elem.getAttribute("href");
-
-                    if (href && href.indexOf("http") !== 0) {
-                        elem.setAttribute("href", window.rootPath + href);
-                    }
-                });
-
-                var display = document.createElement("h3");
-                addClass(display, "impl");
-                display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
-                    "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
-                    "</tbody></table></span>";
-                list.appendChild(display);
-            }
-        }
-    };
-    if (window.pending_implementors) {
-        window.register_implementors(window.pending_implementors);
-    }
-
-    function labelForToggleButton(sectionIsCollapsed) {
-        if (sectionIsCollapsed) {
-            // button will expand the section
-            return "+";
-        }
-        // button will collapse the section
-        // note that this text is also set in the HTML template in ../render/mod.rs
-        return "\u2212"; // "\u2212" is "−" minus sign
-    }
-
-    function toggleAllDocs() {
-        var innerToggle = document.getElementById(toggleAllDocsId);
-        if (!innerToggle) {
-            return;
-        }
-        var sectionIsCollapsed = false;
-        if (hasClass(innerToggle, "will-expand")) {
-            removeClass(innerToggle, "will-expand");
-            onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
-                if (!hasClass(e, "type-contents-toggle")) {
-                    e.open = true;
-                }
-            });
-            innerToggle.title = "collapse all docs";
-        } else {
-            addClass(innerToggle, "will-expand");
-            onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
-                if (e.parentNode.id !== "main" ||
-                    (!hasClass(e, "implementors-toggle") &&
-                     !hasClass(e, "type-contents-toggle")))
-                {
-                    e.open = false;
-                }
-            });
-            sectionIsCollapsed = true;
-            innerToggle.title = "expand all docs";
-        }
-        innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
-    }
-
-    function insertAfter(newNode, referenceNode) {
-        referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
-    }
-
-    (function() {
-        var toggles = document.getElementById(toggleAllDocsId);
-        if (toggles) {
-            toggles.onclick = toggleAllDocs;
-        }
-
-        var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
-        var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
-        var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
-
-        function setImplementorsTogglesOpen(id, open) {
-            var list = document.getElementById(id);
-            if (list !== null) {
-                onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
-                    e.open = open;
-                });
-            }
-        }
-
-        if (hideImplementations) {
-            setImplementorsTogglesOpen("trait-implementations-list", false);
-            setImplementorsTogglesOpen("blanket-implementations-list", false);
-        }
-
-        onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
-            if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
-                e.open = true;
-            }
-            if (hideMethodDocs && hasClass(e, "method-toggle")) {
-                e.open = false;
-            }
-
-        });
-
-        var pageId = getPageId();
-        if (pageId !== null) {
-            expandSection(pageId);
-        }
-    }());
-
-    (function() {
-        // To avoid checking on "rustdoc-line-numbers" value on every loop...
-        var lineNumbersFunc = function() {};
-        if (getSettingValue("line-numbers") === "true") {
-            lineNumbersFunc = function(x) {
-                var count = x.textContent.split("\n").length;
-                var elems = [];
-                for (var i = 0; i < count; ++i) {
-                    elems.push(i + 1);
-                }
-                var node = document.createElement("pre");
-                addClass(node, "line-number");
-                node.innerHTML = elems.join("\n");
-                x.parentNode.insertBefore(node, x);
-            };
-        }
-        onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
-            if (hasClass(e, "compile_fail")) {
-                e.addEventListener("mouseover", function() {
-                    this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
-                });
-                e.addEventListener("mouseout", function() {
-                    this.parentElement.previousElementSibling.childNodes[0].style.color = "";
-                });
-            } else if (hasClass(e, "ignore")) {
-                e.addEventListener("mouseover", function() {
-                    this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
-                });
-                e.addEventListener("mouseout", function() {
-                    this.parentElement.previousElementSibling.childNodes[0].style.color = "";
-                });
-            }
-            lineNumbersFunc(e);
-        });
-    }());
-
-    function handleClick(id, f) {
-        var elem = document.getElementById(id);
-        if (elem) {
-            elem.addEventListener("click", f);
-        }
-    }
-    handleClick("help-button", function(ev) {
-        displayHelp(true, ev);
-    });
-
-    onEachLazy(document.getElementsByTagName("a"), function(el) {
-        // For clicks on internal links (<A> tags with a hash property), we expand the section we're
-        // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
-        // the height of the document so we wind up scrolled to the wrong place.
-        if (el.hash) {
-            el.addEventListener("click", function() {
-                expandSection(el.hash.slice(1));
-            });
-        }
-    });
-
-    onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
-        e.onclick = function() {
-            this.getElementsByClassName('notable-traits-tooltiptext')[0]
-                .classList.toggle("force-tooltip");
-        };
-    });
-
-    var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
-    if (sidebar_menu) {
-        sidebar_menu.onclick = function() {
-            var sidebar = document.getElementsByClassName("sidebar")[0];
-            if (hasClass(sidebar, "mobile")) {
-                hideSidebar();
-            } else {
-                showSidebar();
-            }
-        };
-    }
-
-    var buildHelperPopup = function() {
-        var popup = document.createElement("aside");
-        addClass(popup, "hidden");
-        popup.id = "help";
-
-        popup.addEventListener("click", function(ev) {
-            if (ev.target === popup) {
-                // Clicked the blurred zone outside the help popup; dismiss help.
-                displayHelp(false, ev);
-            }
-        });
-
-        var book_info = document.createElement("span");
-        book_info.innerHTML = "You can find more information in \
-            <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
-
-        var container = document.createElement("div");
-        var shortcuts = [
-            ["?", "Show this help dialog"],
-            ["S", "Focus the search field"],
-            ["T", "Focus the theme picker menu"],
-            ["↑", "Move up in search results"],
-            ["↓", "Move down in search results"],
-            ["← / →", "Switch result tab (when results focused)"],
-            ["&#9166;", "Go to active search result"],
-            ["+", "Expand all sections"],
-            ["-", "Collapse all sections"],
-        ].map(function(x) {
-            return "<dt>" +
-                x[0].split(" ")
-                    .map(function(y, index) {
-                        return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
-                    })
-                    .join("") + "</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 item kind.",
-            "Accepted kinds 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 -&gt; usize</code> or \
-             <code>* -&gt; 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(function(x) {
-            return "<p>" + x + "</p>";
-        }).join("");
-        var div_infos = document.createElement("div");
-        addClass(div_infos, "infos");
-        div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
-
-        container.appendChild(book_info);
-        container.appendChild(div_shortcuts);
-        container.appendChild(div_infos);
-
-        popup.appendChild(container);
-        insertAfter(popup, searchState.outputElement());
-        // So that it's only built once and then it'll do nothing when called!
-        buildHelperPopup = function() {};
-    };
-
-    onHashChange(null);
-    window.addEventListener("hashchange", onHashChange);
-    searchState.setup();
-}());
-
-(function () {
-    var reset_button_timeout = null;
-
-    window.copy_path = function(but) {
-        var parent = but.parentElement;
-        var path = [];
-
-        onEach(parent.childNodes, function(child) {
-            if (child.tagName === 'A') {
-                path.push(child.textContent);
-            }
-        });
-
-        var el = document.createElement('textarea');
-        el.value = 'use ' + path.join('::') + ';';
-        el.setAttribute('readonly', '');
-        // To not make it appear on the screen.
-        el.style.position = 'absolute';
-        el.style.left = '-9999px';
-
-        document.body.appendChild(el);
-        el.select();
-        document.execCommand('copy');
-        document.body.removeChild(el);
-
-        // There is always one children, but multiple childNodes.
-        but.children[0].style.display = 'none';
-
-        var tmp;
-        if (but.childNodes.length < 2) {
-            tmp = document.createTextNode('✓');
-            but.appendChild(tmp);
-        } else {
-            onEachLazy(but.childNodes, function(e) {
-                if (e.nodeType === Node.TEXT_NODE) {
-                    tmp = e;
-                    return true;
-                }
-            });
-            tmp.textContent = '✓';
-        }
-
-        if (reset_button_timeout !== null) {
-            window.clearTimeout(reset_button_timeout);
-        }
-
-        function reset_button() {
-            tmp.textContent = '';
-            reset_button_timeout = null;
-            but.children[0].style.display = "";
-        }
-
-        reset_button_timeout = window.setTimeout(reset_button, 1000);
-    };
-}());
diff --git a/src/librustdoc/html/static/normalize.css b/src/librustdoc/html/static/normalize.css
deleted file mode 100644 (file)
index fdb8a8c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* ignore-tidy-linelength */
-/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
diff --git a/src/librustdoc/html/static/noscript.css b/src/librustdoc/html/static/noscript.css
deleted file mode 100644 (file)
index 0a196ed..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-This whole CSS file is used only in case rustdoc is rendered with javascript disabled. Since a lot
-of content is hidden by default (depending on the settings too), we have to overwrite some of the
-rules.
-*/
-
-#main .attributes {
-       /* Since there is no toggle (the "[-]") when JS is disabled, no need for this margin either. */
-       margin-left: 0 !important;
-}
-
-#copy-path {
-       /* It requires JS to work so no need to display it in this case. */
-       display: none;
-}
diff --git a/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt b/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt
deleted file mode 100644 (file)
index 922d5fd..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff b/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff
deleted file mode 100644 (file)
index 01d6b6b..0000000
Binary files a/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff and /dev/null differ
diff --git a/src/librustdoc/html/static/rust-logo.png b/src/librustdoc/html/static/rust-logo.png
deleted file mode 100644 (file)
index 74b4bd6..0000000
Binary files a/src/librustdoc/html/static/rust-logo.png and /dev/null differ
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
deleted file mode 100644 (file)
index 71123aa..0000000
+++ /dev/null
@@ -1,1888 +0,0 @@
-/* See FiraSans-LICENSE.txt for the Fira Sans license. */
-@font-face {
-       font-family: 'Fira Sans';
-       font-style: normal;
-       font-weight: 400;
-       src: local('Fira Sans'),
-               url("FiraSans-Regular.woff2") format("woff2"),
-               url("FiraSans-Regular.woff") format('woff');
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Fira Sans';
-       font-style: normal;
-       font-weight: 500;
-       src: local('Fira Sans Medium'),
-               url("FiraSans-Medium.woff2") format("woff2"),
-               url("FiraSans-Medium.woff") format('woff');
-       font-display: swap;
-}
-
-/* See SourceSerif4-LICENSE.md for the Source Serif 4 license. */
-@font-face {
-       font-family: 'Source Serif 4';
-       font-style: normal;
-       font-weight: 400;
-       src: local('Source Serif 4'),
-               url("SourceSerif4-Regular.ttf.woff2") format("woff2"),
-               url("SourceSerif4-Regular.ttf.woff") format("woff");
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Serif 4';
-       font-style: italic;
-       font-weight: 400;
-       src: local('Source Serif 4 Italic'),
-               url("SourceSerif4-It.ttf.woff2") format("woff2"),
-               url("SourceSerif4-It.ttf.woff") format("woff");
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Serif 4';
-       font-style: normal;
-       font-weight: 700;
-       src: local('Source Serif 4 Bold'),
-               url("SourceSerif4-Bold.ttf.woff2") format("woff2"),
-               url("SourceSerif4-Bold.ttf.woff") format("woff");
-       font-display: swap;
-}
-
-/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */
-@font-face {
-       font-family: 'Source Code Pro';
-       font-style: normal;
-       font-weight: 400;
-       /* Avoid using locally installed font because bad versions are in circulation:
-        * see https://github.com/rust-lang/rust/issues/24355 */
-       src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"),
-               url("SourceCodePro-Regular.ttf.woff") format("woff");
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Code Pro';
-       font-style: italic;
-       font-weight: 400;
-       src: url("SourceCodePro-It.ttf.woff2") format("woff2"),
-               url("SourceCodePro-It.ttf.woff") format("woff");
-       font-display: swap;
-}
-@font-face {
-       font-family: 'Source Code Pro';
-       font-style: normal;
-       font-weight: 600;
-       src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"),
-               url("SourceCodePro-Semibold.ttf.woff") format("woff");
-       font-display: swap;
-}
-
-/* Avoid using legacy CJK serif fonts in Windows like Batang */
-@font-face {
-       font-family: 'Noto Sans KR';
-       src: url("noto-sans-kr-v13-korean-regular.woff") format("woff");
-       font-display: swap;
-       unicode-range: U+A960-A97F, U+AC00-D7AF, U+D7B0-D7FF;
-}
-
-* {
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-}
-
-/* This part handles the "default" theme being used depending on the system one. */
-html {
-       content: "";
-}
-@media (prefers-color-scheme: light) {
-       html {
-               content: "light";
-       }
-}
-@media (prefers-color-scheme: dark) {
-       html {
-               content: "dark";
-       }
-}
-
-/* General structure and fonts */
-
-body {
-       font: 16px/1.4 "Source Serif 4", "Noto Sans KR", serif;
-       margin: 0;
-       position: relative;
-       padding: 10px 15px 20px 15px;
-
-       -webkit-font-feature-settings: "kern", "liga";
-       -moz-font-feature-settings: "kern", "liga";
-       font-feature-settings: "kern", "liga";
-}
-
-h1 {
-       font-size: 1.5em;
-}
-h2 {
-       font-size: 1.4em;
-}
-h3 {
-       font-size: 1.3em;
-}
-h1, h2, h3, h4 {
-       font-weight: 500;
-       margin: 20px 0 15px 0;
-       padding-bottom: 6px;
-}
-h1.fqn {
-       display: flex;
-       border-bottom: 1px dashed;
-       margin-top: 0;
-
-       /* workaround to keep flex from breaking below 700 px width due to the float: right on the nav
-          above the h1 */
-       padding-left: 1px;
-}
-h1.fqn > .in-band > a:hover {
-       text-decoration: underline;
-}
-h2, h3, h4 {
-       border-bottom: 1px solid;
-}
-.impl,
-.impl-items .method,
-.methods .method,
-.impl-items .type,
-.methods .type,
-.impl-items .associatedconstant,
-.methods .associatedconstant,
-.impl-items .associatedtype,
-.methods .associatedtype {
-       flex-basis: 100%;
-       font-weight: 600;
-       margin-top: 16px;
-       margin-bottom: 10px;
-       position: relative;
-}
-.impl, .method.trait-impl,
-.type.trait-impl,
-.associatedconstant.trait-impl,
-.associatedtype.trait-impl {
-       padding-left: 15px;
-}
-
-div.impl-items > div {
-       padding-left: 0;
-}
-
-h1, h2, h3, h4,
-.sidebar, a.source, .search-input, .search-results .result-name,
-.content table td:first-child > a,
-.item-left > a,
-div.item-list .out-of-band, span.since,
-#source-sidebar, #sidebar-toggle,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before,
-div.impl-items > div:not(.docblock):not(.item-info),
-.content ul.crate a.crate, a.srclink,
-/* This selector is for the items listed in the "all items" page. */
-#main > ul.docblock > li > a {
-       font-family: "Fira Sans", Arial, sans-serif;
-}
-
-.content ul.crate a.crate {
-       font-size: 16px/1.6;
-}
-
-ol, ul {
-       padding-left: 25px;
-}
-ul ul, ol ul, ul ol, ol ol {
-       margin-bottom: .6em;
-}
-
-p {
-       margin: 0 0 .6em 0;
-}
-
-summary {
-       outline: none;
-}
-
-/* Fix some style changes due to normalize.css 8 */
-
-td,
-th {
-       padding: 0;
-}
-
-table {
-       border-collapse: collapse;
-}
-
-button,
-input,
-optgroup,
-select,
-textarea {
-       color: inherit;
-       font: inherit;
-       margin: 0;
-}
-
-/* end tweaks for normalize.css 8 */
-
-details:not(.rustdoc-toggle) summary {
-       margin-bottom: .6em;
-}
-
-code, pre, a.test-arrow {
-       font-family: "Source Code Pro", monospace;
-}
-.docblock code, .docblock-short code {
-       border-radius: 3px;
-       padding: 0 0.1em;
-}
-.docblock pre code, .docblock-short pre code {
-       padding: 0;
-       padding-right: 1ex;
-}
-pre {
-       padding: 14px;
-}
-
-.source .content pre {
-       padding: 20px;
-}
-
-img {
-       max-width: 100%;
-}
-
-li {
-       position: relative;
-}
-
-.source .content {
-       margin-top: 50px;
-       max-width: none;
-       overflow: visible;
-       margin-left: 0px;
-}
-
-nav.sub {
-       font-size: 16px;
-       text-transform: uppercase;
-}
-
-.sidebar {
-       width: 200px;
-       position: fixed;
-       left: 0;
-       top: 0;
-       bottom: 0;
-       overflow: auto;
-}
-
-/* Improve the scrollbar display on firefox */
-* {
-       scrollbar-width: initial;
-}
-.sidebar {
-       scrollbar-width: thin;
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar {
-       width: 12px;
-}
-.sidebar::-webkit-scrollbar {
-       width: 8px;
-}
-::-webkit-scrollbar-track {
-       -webkit-box-shadow: inset 0;
-}
-
-.sidebar .block > ul > li {
-       margin-right: -10px;
-}
-
-.content, nav {
-       max-width: 960px;
-}
-
-/* Everything else */
-
-.hidden {
-       display: none !important;
-}
-
-.logo-container {
-       height: 100px;
-       width: 100px;
-       position: relative;
-       margin: 20px auto;
-       display: block;
-       margin-top: 10px;
-}
-
-.logo-container > img {
-       max-width: 100px;
-       max-height: 100px;
-       position: absolute;
-       left: 50%;
-       top: 50%;
-       transform: translate(-50%, -50%);
-       display: block;
-}
-
-.sidebar .location {
-       border: 1px solid;
-       font-size: 17px;
-       margin: 30px 10px 20px 10px;
-       text-align: center;
-       word-wrap: break-word;
-}
-
-.sidebar .version {
-       font-size: 15px;
-       text-align: center;
-       border-bottom: 1px solid;
-       overflow-wrap: break-word;
-       word-wrap: break-word; /* deprecated */
-       word-break: break-word; /* Chrome, non-standard */
-}
-
-.location:empty {
-       border: none;
-}
-
-.location a:first-of-type {
-       font-weight: 500;
-}
-.location a:hover {
-       text-decoration: underline;
-}
-
-.block {
-       padding: 0;
-       margin-bottom: 14px;
-}
-.block h2, .block h3 {
-       text-align: center;
-}
-.block ul, .block li {
-       margin: 0 10px;
-       padding: 0;
-       list-style: none;
-}
-
-.block a {
-       display: block;
-       text-overflow: ellipsis;
-       overflow: hidden;
-       line-height: 15px;
-       padding: 7px 5px;
-       font-size: 14px;
-       font-weight: 300;
-       transition: border 500ms ease-out;
-}
-
-.sidebar-title {
-       border-top: 1px solid;
-       border-bottom: 1px solid;
-       text-align: center;
-       font-size: 17px;
-       margin-bottom: 5px;
-}
-
-.sidebar-links {
-       margin-bottom: 15px;
-}
-
-.sidebar-links > a {
-       padding-left: 10px;
-       width: 100%;
-}
-
-.sidebar-menu {
-       display: none;
-}
-
-.content {
-       padding: 15px 0;
-}
-
-.source .content pre.rust {
-       white-space: pre;
-       overflow: auto;
-       padding-left: 0;
-}
-
-.rustdoc .example-wrap {
-       display: inline-flex;
-       margin-bottom: 10px;
-}
-
-.example-wrap {
-       position: relative;
-       width: 100%;
-}
-
-.example-wrap > pre.line-number {
-       overflow: initial;
-       border: 1px solid;
-       padding: 13px 8px;
-       text-align: right;
-       border-top-left-radius: 5px;
-       border-bottom-left-radius: 5px;
-}
-
-.rustdoc:not(.source) .example-wrap > pre.rust {
-       width: 100%;
-       overflow-x: auto;
-}
-
-.rustdoc .example-wrap > pre {
-       margin: 0;
-}
-
-#search {
-       margin-left: 230px;
-       position: relative;
-}
-
-#results > table {
-       width: 100%;
-       table-layout: fixed;
-}
-
-.content > .example-wrap pre.line-numbers {
-       position: relative;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-}
-.line-numbers span {
-       cursor: pointer;
-}
-
-.docblock-short {
-       overflow-wrap: anywhere;
-}
-.docblock-short p {
-       display: inline;
-}
-
-.docblock-short p {
-       overflow: hidden;
-       text-overflow: ellipsis;
-       margin: 0;
-}
-/* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock > :not(pre) > code,
-.docblock-short > :not(pre) > code {
-       white-space: pre-wrap;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
-       border-bottom: 1px solid;
-}
-
-.top-doc .docblock h1 { font-size: 1.3em; }
-.top-doc .docblock h2 { font-size: 1.15em; }
-.top-doc .docblock h3,
-.top-doc .docblock h4,
-.top-doc .docblock h5 {
-       font-size: 1em;
-}
-
-.docblock h1 { font-size: 1em; }
-.docblock h2 { font-size: 0.95em; }
-.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
-
-.docblock {
-       margin-left: 24px;
-       position: relative;
-}
-
-.content .out-of-band {
-       flex-grow: 0;
-       text-align: right;
-       font-size: 23px;
-       margin: 0px;
-       padding: 0 0 0 12px;
-       font-weight: normal;
-}
-
-.method > code, .trait-impl > code, .invisible > code {
-       max-width: calc(100% - 41px);
-       display: block;
-}
-
-.invisible {
-       width: 100%;
-       display: inline-block;
-}
-
-.content .in-band {
-       flex-grow: 1;
-       margin: 0px;
-       padding: 0px;
-}
-
-.in-band > code {
-       display: inline-block;
-}
-
-#main {
-       position: relative;
-}
-#main > .since {
-       top: inherit;
-       font-family: "Fira Sans", Arial, sans-serif;
-}
-
-.content table:not(.table-display) {
-       border-spacing: 0 5px;
-}
-.content td { vertical-align: top; }
-.content td:first-child { padding-right: 20px; }
-.content td p:first-child { margin-top: 0; }
-.content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; }
-.content tr:first-child td { border-top: 0; }
-
-.docblock table {
-       margin: .5em 0;
-       width: calc(100% - 2px);
-       border: 1px dashed;
-}
-
-.docblock table td {
-       padding: .5em;
-       border: 1px dashed;
-}
-
-.docblock table th {
-       padding: .5em;
-       text-align: left;
-       border: 1px solid;
-}
-
-.fields + table {
-       margin-bottom: 1em;
-}
-
-.content .item-list {
-       list-style-type: none;
-       padding: 0;
-}
-
-.content .multi-column {
-       -moz-column-count: 5;
-       -moz-column-gap: 2.5em;
-       -webkit-column-count: 5;
-       -webkit-column-gap: 2.5em;
-       column-count: 5;
-       column-gap: 2.5em;
-}
-.content .multi-column li { width: 100%; display: inline-block; }
-
-.content > .methods > .method {
-       font-size: 1em;
-       position: relative;
-}
-/* Shift "where ..." part of method or fn definition down a line */
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
-       display: block;
-       font-size: 0.8em;
-}
-
-.content .methods > div:not(.notable-traits):not(.method) {
-       margin-left: 40px;
-       margin-bottom: 15px;
-}
-
-.content .docblock > .impl-items {
-       margin-left: 20px;
-       margin-top: -34px;
-}
-.content .docblock >.impl-items .table-display {
-       margin: 0;
-}
-.content .docblock >.impl-items table td {
-       padding: 0;
-}
-.content .docblock > .impl-items .table-display, .impl-items table td {
-       border: none;
-}
-
-.content .item-info code {
-       font-size: 90%;
-}
-
-.content .item-info {
-       position: relative;
-       margin-left: 33px;
-}
-
-.sub-variant > div > .item-info {
-       margin-top: initial;
-}
-
-.content .item-info::before {
-       content: '⬑';
-       font-size: 25px;
-       position: absolute;
-       top: -6px;
-       left: -19px;
-}
-
-.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant,
-.impl-items > .associatedtype, .content .impl-items details > summary > .type,
-.impl-items details > summary > .associatedconstant,
-.impl-items details > summary > .associatedtype {
-       margin-left: 20px;
-}
-
-.content .impl-items .docblock, .content .impl-items .item-info {
-       margin-bottom: .6em;
-}
-
-.content .impl-items > .item-info {
-       margin-left: 40px;
-}
-
-.methods > .item-info, .content .impl-items > .item-info {
-       margin-top: -8px;
-}
-
-.impl-items {
-       flex-basis: 100%;
-}
-
-#main > .item-info {
-       margin-top: 0;
-}
-
-nav:not(.sidebar) {
-       border-bottom: 1px solid;
-       padding-bottom: 10px;
-       margin-bottom: 10px;
-}
-nav.main {
-       padding: 20px 0;
-       text-align: center;
-}
-nav.main .current {
-       border-top: 1px solid;
-       border-bottom: 1px solid;
-}
-nav.main .separator {
-       border: 1px solid;
-       display: inline-block;
-       height: 23px;
-       margin: 0 20px;
-}
-nav.sum { text-align: right; }
-nav.sub form { display: inline; }
-
-nav.sub, .content {
-       margin-left: 230px;
-}
-
-a {
-       text-decoration: none;
-       background: transparent;
-}
-
-.small-section-header {
-       display: flex;
-       justify-content: space-between;
-       position: relative;
-}
-
-.small-section-header:hover > .anchor {
-       display: initial;
-}
-
-.in-band:hover > .anchor, .impl:hover > .anchor, .method.trait-impl:hover > .anchor,
-.type.trait-impl:hover > .anchor, .associatedconstant.trait-impl:hover > .anchor,
-.associatedtype.trait-impl:hover > .anchor {
-       display: inline-block;
-       position: absolute;
-}
-.anchor {
-       display: none;
-       position: absolute;
-       left: -7px;
-}
-.anchor.field {
-       left: -5px;
-}
-.small-section-header > .anchor {
-       left: -28px;
-       padding-right: 10px; /* avoid gap that causes hover to disappear */
-}
-.anchor:before {
-       content: '\2002\00a7\2002';
-}
-
-.docblock a:not(.srclink):not(.test-arrow):hover,
-.docblock-short a:not(.srclink):not(.test-arrow):hover, .item-info a {
-       text-decoration: underline;
-}
-
-.invisible > .srclink,
-.method > code + .srclink {
-       position: absolute;
-       top: 0;
-       right: 0;
-       font-size: 17px;
-       font-weight: normal;
-}
-
-.block a.current.crate { font-weight: 500; }
-
-.item-table {
-       display: grid;
-       column-gap: 1.2rem;
-       row-gap: 0.0rem;
-       grid-template-columns: auto 1fr;
-       /* align content left */
-       justify-items: start;
-}
-
-.item-left, .item-right {
-       display: block;
-}
-.item-left {
-       grid-column: 1;
-}
-.item-right {
-       grid-column: 2;
-}
-
-.search-container {
-       position: relative;
-}
-.search-container > div {
-       display: inline-flex;
-       width: calc(100% - 63px);
-}
-#crate-search {
-       min-width: 115px;
-       margin-top: 5px;
-       padding: 6px;
-       padding-right: 19px;
-       flex: none;
-       border: 0;
-       border-right: 0;
-       border-radius: 4px 0 0 4px;
-       outline: none;
-       cursor: pointer;
-       border-right: 1px solid;
-       -moz-appearance: none;
-       -webkit-appearance: none;
-       /* Removes default arrow from firefox */
-       text-indent: 0.01px;
-       text-overflow: "";
-       background-repeat: no-repeat;
-       background-color: transparent;
-       background-size: 20px;
-       background-position: calc(100% - 1px) 56%;
-}
-.search-container > .top-button {
-       position: absolute;
-       right: 0;
-       top: 10px;
-}
-.search-input {
-       /* Override Normalize.css: we have margins and do
-        not want to overflow - the `moz` attribute is necessary
-        until Firefox 29, too early to drop at this point */
-       -moz-box-sizing: border-box !important;
-       box-sizing: border-box !important;
-       outline: none;
-       border: none;
-       border-radius: 1px;
-       margin-top: 5px;
-       padding: 10px 16px;
-       font-size: 17px;
-       transition: border-color 300ms ease;
-       transition: border-radius 300ms ease-in-out;
-       transition: box-shadow 300ms ease-in-out;
-       width: 100%;
-}
-
-#crate-search + .search-input {
-       border-radius: 0 1px 1px 0;
-       width: calc(100% - 32px);
-}
-
-.search-input:focus {
-       border-radius: 2px;
-       border: 0;
-       outline: 0;
-}
-
-.search-results {
-       display: none;
-       padding-bottom: 2em;
-}
-
-.search-results.active {
-       display: block;
-       /* prevent overhanging tabs from moving the first result */
-       clear: both;
-}
-
-.search-results .desc > span {
-       white-space: nowrap;
-       text-overflow: ellipsis;
-       overflow: hidden;
-       display: block;
-}
-
-.search-results > a {
-       display: block;
-       width: 100%;
-       /* A little margin ensures the browser's outlining of focused links has room to display. */
-       margin-left: 2px;
-       margin-right: 2px;
-       border-bottom: 1px solid #aaa3;
-}
-
-.search-results > a > div {
-       display: flex;
-       flex-flow: row wrap;
-}
-
-.search-results .result-name, .search-results div.desc, .search-results .result-description {
-       width: 50%;
-}
-.search-results .result-name {
-       padding-right: 1em;
-}
-
-.search-results .result-name > span {
-       display: inline-block;
-       margin: 0;
-       font-weight: normal;
-}
-
-body.blur > :not(#help) {
-       filter: blur(8px);
-       -webkit-filter: blur(8px);
-       opacity: .7;
-}
-
-#help {
-       width: 100%;
-       height: 100vh;
-       position: fixed;
-       top: 0;
-       left: 0;
-       display: flex;
-       justify-content: center;
-       align-items: center;
-}
-#help > div {
-       flex: 0 0 auto;
-       box-shadow: 0 0 6px rgba(0,0,0,.2);
-       width: 550px;
-       height: auto;
-       border: 1px solid;
-}
-#help dt {
-       float: left;
-       clear: left;
-       display: block;
-       margin-right: 0.5rem;
-}
-#help > div > span {
-       text-align: center;
-       display: block;
-       margin: 10px 0;
-       font-size: 18px;
-       border-bottom: 1px solid #ccc;
-       padding-bottom: 4px;
-       margin-bottom: 6px;
-}
-#help dd { margin: 5px 35px; }
-#help .infos { padding-left: 0; }
-#help h1, #help h2 { margin-top: 0; }
-#help > div div {
-       width: 50%;
-       float: left;
-       padding: 0 20px 20px 17px;;
-}
-
-.stab {
-       border-width: 1px;
-       border-style: solid;
-       padding: 3px;
-       margin-bottom: 5px;
-       font-size: 90%;
-       font-weight: normal;
-}
-.stab p {
-       display: inline;
-}
-
-.stab .emoji {
-       font-size: 1.5em;
-}
-
-/* Black one-pixel outline around emoji shapes */
-.emoji {
-       text-shadow:
-               1px 0 0 black,
-               -1px 0 0 black,
-               0  1px 0 black,
-               0 -1px 0 black;
-}
-
-.module-item .stab,
-.import-item .stab {
-       border-radius: 3px;
-       display: inline-block;
-       font-size: 80%;
-       line-height: 1.2;
-       margin-bottom: 0;
-       margin-left: .3em;
-       padding: 2px;
-       vertical-align: text-bottom;
-}
-
-.module-item.unstable,
-.import-item.unstable {
-       opacity: 0.65;
-}
-
-.since {
-       font-weight: normal;
-       font-size: initial;
-}
-
-.impl-items .since, .impl .since, .methods .since {
-       padding-left: 12px;
-       padding-right: 2px;
-       position: initial;
-}
-
-.impl-items .srclink, .impl .srclink, .methods .srclink {
-       /* Override header settings otherwise it's too bold */
-       font-size: 17px;
-       font-weight: normal;
-}
-
-.rightside {
-       float: right;
-}
-
-.has-srclink {
-       font-size: 16px;
-       margin-bottom: 12px;
-       /* Push the src link out to the right edge consistently */
-       justify-content: space-between;
-}
-
-.variants_table {
-       width: 100%;
-}
-
-.variants_table tbody tr td:first-child {
-       width: 1%; /* make the variant name as small as possible */
-}
-
-td.summary-column {
-       width: 100%;
-}
-
-.summary {
-       padding-right: 0px;
-}
-
-pre.rust .question-mark {
-       font-weight: bold;
-}
-
-a.test-arrow {
-       display: inline-block;
-       position: absolute;
-       padding: 5px 10px 5px 10px;
-       border-radius: 5px;
-       font-size: 130%;
-       top: 5px;
-       right: 5px;
-       z-index: 1;
-}
-a.test-arrow:hover{
-       text-decoration: none;
-}
-
-.section-header:hover a:before {
-       position: absolute;
-       left: -25px;
-       padding-right: 10px; /* avoid gap that causes hover to disappear */
-       content: '\2002\00a7\2002';
-}
-
-.section-header:hover a {
-       text-decoration: none;
-}
-
-.section-header a {
-       color: inherit;
-}
-
-.code-attribute {
-       font-weight: 300;
-}
-
-.since + .srclink {
-       padding-left: 10px;
-}
-
-.item-spacer {
-       width: 100%;
-       height: 12px;
-}
-
-.out-of-band > span.since {
-       position: initial;
-       font-size: 20px;
-       margin-right: 5px;
-}
-
-.sub-variant, .sub-variant > h3 {
-       margin-top: 0px !important;
-       padding-top: 1px;
-}
-
-#main > details > .sub-variant > h3 {
-       font-size: 15px;
-       margin-left: 25px;
-       margin-bottom: 5px;
-}
-
-.sub-variant > div {
-       margin-left: 20px;
-       margin-bottom: 10px;
-}
-
-.sub-variant > div > span {
-       display: block;
-       position: relative;
-}
-
-.toggle-label {
-       display: inline-block;
-       margin-left: 4px;
-       margin-top: 3px;
-}
-
-.docblock > .section-header:first-child {
-       margin-left: 15px;
-       margin-top: 0;
-}
-
-.docblock > .section-header:first-child:hover > a:before {
-       left: -10px;
-}
-
-#main > .variant, #main > .structfield {
-       display: block;
-}
-
-
-:target > code {
-       opacity: 1;
-}
-
-:target {
-       padding-right: 3px;
-}
-
-.information {
-       position: absolute;
-       left: -25px;
-       margin-top: 7px;
-       z-index: 1;
-}
-
-.tooltip {
-       position: relative;
-       display: inline-block;
-       cursor: pointer;
-}
-
-.tooltip::after {
-       display: none;
-       text-align: center;
-       padding: 5px 3px 3px 3px;
-       border-radius: 6px;
-       margin-left: 5px;
-       font-size: 16px;
-}
-
-.tooltip.ignore::after {
-       content: "This example is not tested";
-}
-.tooltip.compile_fail::after {
-       content: "This example deliberately fails to compile";
-}
-.tooltip.should_panic::after {
-       content: "This example panics";
-}
-.tooltip.edition::after {
-       content: "This code runs with edition " attr(data-edition);
-}
-
-.tooltip::before {
-       content: " ";
-       position: absolute;
-       top: 50%;
-       left: 16px;
-       margin-top: -5px;
-       border-width: 5px;
-       border-style: solid;
-       display: none;
-}
-
-.tooltip:hover::before, .tooltip:hover::after {
-       display: inline;
-}
-
-.tooltip.compile_fail, .tooltip.should_panic, .tooltip.ignore {
-       font-weight: bold;
-       font-size: 20px;
-}
-
-.notable-traits-tooltip {
-       display: inline-block;
-       cursor: pointer;
-}
-
-.notable-traits:hover .notable-traits-tooltiptext,
-.notable-traits .notable-traits-tooltiptext.force-tooltip {
-       display: inline-block;
-}
-
-.notable-traits .notable-traits-tooltiptext {
-       display: none;
-       padding: 5px 3px 3px 3px;
-       border-radius: 6px;
-       margin-left: 5px;
-       z-index: 10;
-       font-size: 16px;
-       cursor: default;
-       position: absolute;
-       border: 1px solid;
-}
-
-.notable-traits-tooltip::after {
-       /* The margin on the tooltip does not capture hover events,
-          this extends the area of hover enough so that mouse hover is not
-          lost when moving the mouse to the tooltip */
-       content: "\00a0\00a0\00a0";
-}
-
-.notable-traits .notable, .notable-traits .docblock {
-       margin: 0;
-}
-
-.notable-traits .notable {
-       margin: 0;
-       margin-bottom: 13px;
-       font-size: 19px;
-       font-weight: 600;
-}
-
-.notable-traits .docblock code.content{
-       margin: 0;
-       padding: 0;
-       font-size: 20px;
-}
-
-/* Example code has the "Run" button that needs to be positioned relative to the pre */
-pre.rust.rust-example-rendered {
-       position: relative;
-}
-
-pre.rust {
-       tab-size: 4;
-       -moz-tab-size: 4;
-}
-
-.search-failed {
-       text-align: center;
-       margin-top: 20px;
-       display: none;
-}
-
-.search-failed.active {
-       display: block;
-}
-
-.search-failed > ul {
-       text-align: left;
-       max-width: 570px;
-       margin-left: auto;
-       margin-right: auto;
-}
-
-#titles {
-       height: 35px;
-}
-
-#titles > button {
-       float: left;
-       width: 33.3%;
-       text-align: center;
-       font-size: 18px;
-       cursor: pointer;
-       border: 0;
-       border-top: 2px solid;
-}
-
-#titles > button:not(:last-child) {
-       margin-right: 1px;
-       width: calc(33.3% - 1px);
-}
-
-#titles > button > div.count {
-       display: inline-block;
-       font-size: 16px;
-}
-
-.notable-traits {
-       cursor: pointer;
-       z-index: 2;
-       margin-left: 5px;
-}
-
-#all-types {
-       text-align: center;
-       border: 1px solid;
-       margin: 0 10px;
-       margin-bottom: 10px;
-       display: block;
-       border-radius: 7px;
-}
-#all-types > p {
-       margin: 5px 0;
-}
-
-#sidebar-toggle {
-       position: fixed;
-       top: 30px;
-       left: 300px;
-       z-index: 10;
-       padding: 3px;
-       border-top-right-radius: 3px;
-       border-bottom-right-radius: 3px;
-       cursor: pointer;
-       font-weight: bold;
-       transition: left .5s;
-       font-size: 1.2em;
-       border: 1px solid;
-       border-left: 0;
-}
-#source-sidebar {
-       position: fixed;
-       top: 0;
-       bottom: 0;
-       left: 0;
-       width: 300px;
-       z-index: 1;
-       overflow: auto;
-       transition: left .5s;
-       border-right: 1px solid;
-}
-#source-sidebar > .title {
-       font-size: 1.5em;
-       text-align: center;
-       border-bottom: 1px solid;
-       margin-bottom: 6px;
-}
-
-.theme-picker {
-       position: absolute;
-       left: 211px;
-       top: 19px;
-}
-
-.theme-picker button {
-       outline: none;
-}
-
-#settings-menu, #help-button {
-       position: absolute;
-       top: 10px;
-}
-
-#settings-menu {
-       right: 0;
-       outline: none;
-}
-
-#theme-picker, #settings-menu, #help-button, #copy-path {
-       padding: 4px;
-       width: 27px;
-       height: 29px;
-       border: 1px solid;
-       border-radius: 3px;
-       cursor: pointer;
-}
-
-#help-button {
-       right: 30px;
-       font-family: "Fira Sans", Arial, sans-serif;
-       text-align: center;
-       font-size: 17px;
-       padding-top: 2px;
-}
-
-#copy-path {
-       background: initial;
-       margin-left: 10px;
-       padding: 0;
-       padding-left: 2px;
-       border: 0;
-}
-
-#theme-choices {
-       display: none;
-       position: absolute;
-       left: 0;
-       top: 28px;
-       border: 1px solid;
-       border-radius: 3px;
-       z-index: 1;
-       cursor: pointer;
-}
-
-#theme-choices > button {
-       border: none;
-       width: 100%;
-       padding: 4px 8px;
-       text-align: center;
-       background: rgba(0,0,0,0);
-}
-
-#theme-choices > button:not(:first-child) {
-       border-top: 1px solid;
-}
-
-kbd {
-       display: inline-block;
-       padding: 3px 5px;
-       font: 15px monospace;
-       line-height: 10px;
-       vertical-align: middle;
-       border: solid 1px;
-       border-radius: 3px;
-       box-shadow: inset 0 -1px 0;
-       cursor: default;
-}
-
-.hidden-by-impl-hider,
-.hidden-by-usual-hider {
-       /* important because of conflicting rule for small screens */
-       display: none !important;
-}
-
-#implementations-list > h3 > span.in-band {
-       width: 100%;
-}
-
-.table-display {
-       width: 100%;
-       border: 0;
-       border-collapse: collapse;
-       border-spacing: 0;
-       font-size: 16px;
-}
-
-.table-display tr td:first-child {
-       padding-right: 0;
-}
-
-.table-display tr td:last-child {
-       float: right;
-}
-.table-display .out-of-band {
-       position: relative;
-       font-size: 19px;
-       display: block;
-}
-#implementors-list > .impl-items .table-display .out-of-band {
-       font-size: 17px;
-}
-
-.table-display td:hover .anchor {
-       display: block;
-       top: 2px;
-       left: -5px;
-}
-
-#main > ul {
-       padding-left: 10px;
-}
-#main > ul > li {
-       list-style: none;
-}
-
-.non-exhaustive {
-       margin-bottom: 1em;
-}
-
-div.children {
-       padding-left: 27px;
-       display: none;
-}
-div.name {
-       cursor: pointer;
-       position: relative;
-       margin-left: 16px;
-}
-div.files > a {
-       display: block;
-       padding: 0 3px;
-}
-div.files > a:hover, div.name:hover {
-       background-color: #a14b4b;
-}
-div.name.expand + .children {
-       display: block;
-}
-div.name::before {
-       content: "\25B6";
-       padding-left: 4px;
-       font-size: 0.7em;
-       position: absolute;
-       left: -16px;
-       top: 4px;
-}
-div.name.expand::before {
-       transform: rotate(90deg);
-       left: -15px;
-       top: 2px;
-}
-
-/* The hideme class is used on summary tags that contain a span with
-       placeholder text shown only when the toggle is closed. For instance,
-       "Expand description" or "Show methods". */
-details.rustdoc-toggle > summary.hideme {
-       cursor: pointer;
-}
-
-details.rustdoc-toggle > summary, details.undocumented > summary {
-       list-style: none;
-}
-details.rustdoc-toggle > summary::-webkit-details-marker,
-details.rustdoc-toggle > summary::marker,
-details.undocumented > summary::-webkit-details-marker,
-details.undocumented > summary::marker {
-       display: none;
-}
-
-details.rustdoc-toggle > summary.hideme > span {
-       margin-left: 9px;
-}
-
-details.rustdoc-toggle > summary::before {
-       content: "[+]";
-       font-weight: 300;
-       font-size: 0.8em;
-       letter-spacing: 1px;
-       cursor: pointer;
-}
-
-details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.top-doc > summary::before,
-details.rustdoc-toggle.non-exhaustive > summary,
-details.rustdoc-toggle.non-exhaustive > summary::before {
-       font-family: 'Fira Sans';
-       font-size: 16px;
-}
-
-details.non-exhaustive {
-       margin-bottom: 8px;
-}
-
-details.rustdoc-toggle > summary.hideme::before {
-       position: relative;
-}
-
-details.rustdoc-toggle > summary:not(.hideme)::before {
-       position: absolute;
-       left: -23px;
-       top: 3px;
-}
-
-.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before,
-.undocumented > details.rustdoc-toggle > summary:not(.hideme)::before {
-       position: absolute;
-       left: -2px;
-}
-
-/* When a "hideme" summary is open and the "Expand description" or "Show
-       methods" text is hidden, we want the [-] toggle that remains to not
-       affect the layout of the items to its right. To do that, we use
-       absolute positioning. Note that we also set position: relative
-       on the parent <details> to make this work properly. */
-details.rustdoc-toggle[open] > summary.hideme {
-       position: absolute;
-}
-
-details.rustdoc-toggle, details.undocumented {
-       position: relative;
-}
-
-details.rustdoc-toggle[open] > summary.hideme > span {
-       display: none;
-}
-
-details.rustdoc-toggle[open] > summary::before {
-       content: "[−]";
-       display: inline;
-}
-
-details.undocumented > summary::before {
-       content: "[+] Show hidden undocumented items";
-       cursor: pointer;
-       font-size: 16px;
-       font-weight: 300;
-}
-
-details.undocumented[open] > summary::before {
-       content: "[−] Hide undocumented items";
-}
-
-/* Media Queries */
-
-@media (min-width: 701px) {
-       /* In case there is no documentation before a code block, we need to add some margin at the top
-       to prevent an overlay between the "collapse toggle" and the information tooltip.
-       However, it's not needed with smaller screen width because the doc/code block is always put
-       "one line" below. */
-       .docblock > .information:first-child > .tooltip {
-               margin-top: 16px;
-       }
-}
-
-@media (max-width: 700px) {
-       body {
-               padding-top: 0px;
-       }
-
-       .rustdoc > .sidebar {
-               height: 45px;
-               min-height: 40px;
-               margin: 0;
-               margin-left: -15px;
-               padding: 0 15px;
-               position: static;
-               z-index: 11;
-       }
-
-       .sidebar > .location {
-               float: right;
-               margin: 0px;
-               margin-top: 2px;
-               padding: 3px 10px 1px 10px;
-               min-height: 39px;
-               background: inherit;
-               text-align: left;
-               font-size: 24px;
-       }
-
-       .sidebar .location:empty {
-               padding: 0;
-       }
-
-       .sidebar .logo-container {
-               width: 35px;
-               height: 35px;
-               margin-top: 5px;
-               margin-bottom: 5px;
-               float: left;
-               margin-left: 50px;
-       }
-
-       .sidebar .logo-container > img {
-               max-width: 35px;
-               max-height: 35px;
-       }
-
-       .sidebar-menu {
-               position: fixed;
-               z-index: 10;
-               font-size: 2rem;
-               cursor: pointer;
-               width: 45px;
-               left: 0;
-               text-align: center;
-               display: block;
-               border-bottom: 1px solid;
-               border-right: 1px solid;
-               height: 45px;
-       }
-
-       .rustdoc.source > .sidebar > .sidebar-menu {
-               display: none;
-       }
-
-       .sidebar-elems {
-               position: fixed;
-               z-index: 1;
-               left: 0;
-               top: 45px;
-               bottom: 0;
-               overflow-y: auto;
-               border-right: 1px solid;
-               display: none;
-       }
-
-       .sidebar > .block.version {
-               overflow: hidden;
-               border-bottom: none;
-               margin-bottom: 0;
-               height: 100%;
-               padding-left: 12px;
-       }
-       .sidebar > .block.version > div.narrow-helper {
-               float: left;
-               width: 1px;
-               height: 100%;
-       }
-       .sidebar > .block.version > p {
-               /* hide Version text if too narrow */
-               margin: 0;
-               min-width: 55px;
-               /* vertically center */
-               display: flex;
-               align-items: center;
-               height: 100%;
-       }
-
-       nav.sub {
-               width: calc(100% - 32px);
-               float: right;
-       }
-
-       .content {
-               margin-left: 0px;
-       }
-
-       #main, #search {
-               margin-top: 45px;
-               padding: 0;
-       }
-
-       #search {
-               margin-left: 0;
-       }
-
-       .anchor {
-               display: none !important;
-       }
-
-       .theme-picker {
-               left: 10px;
-               top: 54px;
-               z-index: 1;
-       }
-
-       .notable-traits {
-               position: absolute;
-               left: -22px;
-               top: 24px;
-       }
-
-       #titles > button > div.count {
-               float: left;
-               width: 100%;
-       }
-
-       #titles {
-               height: 50px;
-       }
-
-       .sidebar.mobile {
-               position: fixed;
-               width: 100%;
-               margin-left: 0;
-               background-color: rgba(0,0,0,0);
-               height: 100%;
-       }
-       /*
-       This allows to prevent the version text to overflow the sidebar title on mobile mode when the
-       sidebar is displayed (after clicking on the "hamburger" button).
-       */
-       .sidebar.mobile > div.version {
-               overflow: hidden;
-               max-height: 33px;
-       }
-       .sidebar {
-               width: calc(100% + 30px);
-       }
-
-       .show-it {
-               display: block;
-               width: 246px;
-       }
-
-       .show-it > .block.items {
-               margin: 8px 0;
-       }
-
-       .show-it > .block.items > ul {
-               margin: 0;
-       }
-
-       .show-it > .block.items > ul > li {
-               text-align: center;
-               margin: 2px 0;
-       }
-
-       .show-it > .block.items > ul > li > a {
-               font-size: 21px;
-       }
-
-       /* Because of ios, we need to actually have a full height sidebar title so the
-        * actual sidebar can show up. But then we need to make it transparent so we don't
-        * hide content. The filler just allows to create the background for the sidebar
-        * title. But because of the absolute position, I had to lower the z-index.
-        */
-       #sidebar-filler {
-               position: fixed;
-               left: 45px;
-               width: calc(100% - 45px);
-               top: 0;
-               height: 45px;
-               z-index: -1;
-               border-bottom: 1px solid;
-       }
-
-       #main > details.rustdoc-toggle > summary::before,
-       #main > div > details.rustdoc-toggle > summary::before {
-               left: -11px;
-       }
-
-       #all-types {
-               margin: 10px;
-       }
-
-       #sidebar-toggle {
-               top: 100px;
-               width: 30px;
-               font-size: 1.5rem;
-               text-align: center;
-               padding: 0;
-       }
-
-       #source-sidebar {
-               z-index: 11;
-       }
-
-       #main > .line-numbers {
-               margin-top: 0;
-       }
-
-       .notable-traits .notable-traits-tooltiptext {
-               left: 0;
-               top: 100%;
-       }
-
-       /* We don't display the help button on mobile devices. */
-       #help-button {
-               display: none;
-       }
-
-       /* Display an alternating layout on tablets and phones */
-       .item-table {
-               display: flex;
-               flex-flow: column wrap;
-       }
-       .item-left, .item-right {
-               width: 100%;
-       }
-
-       .search-container > div {
-               width: calc(100% - 32px);
-       }
-
-       /* Display an alternating layout on tablets and phones */
-       .search-results > a {
-               border-bottom: 1px solid #aaa9;
-               padding: 5px 0px;
-       }
-       .search-results .result-name, .search-results div.desc, .search-results .result-description {
-               width: 100%;
-       }
-       .search-results div.desc, .search-results .result-description, .item-right {
-               padding-left: 2em;
-       }
-}
-
-@media print {
-       nav.sub, .content .out-of-band {
-               display: none;
-       }
-}
-
-@media (max-width: 464px) {
-       #titles, #titles > button {
-               height: 73px;
-       }
-
-       /* This is to prevent the search bar from being underneath the <section>
-        * element following it.
-        */
-       #main, #search {
-               margin-top: 100px;
-       }
-
-       #main > table:not(.table-display) td {
-               word-break: break-word;
-               width: 50%;
-       }
-
-       .search-container > div {
-               display: block;
-               width: calc(100% - 37px);
-       }
-
-       #crate-search {
-               width: 100%;
-               border-radius: 4px;
-               border: 0;
-       }
-
-       #crate-search + .search-input {
-               width: calc(100% + 71px);
-               margin-left: -36px;
-       }
-
-       #theme-picker, #settings-menu {
-               padding: 5px;
-               width: 31px;
-               height: 31px;
-       }
-
-       #theme-picker {
-               margin-top: -2px;
-       }
-
-       #settings-menu {
-               top: 7px;
-       }
-
-       .docblock {
-               margin-left: 12px;
-       }
-}
diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js
deleted file mode 100644 (file)
index a7fc0b8..0000000
+++ /dev/null
@@ -1,1561 +0,0 @@
-/* global addClass, getNakedUrl, getSettingValue, hasOwnPropertyRustdoc, initSearch, onEach */
-/* global onEachLazy, removeClass, searchState, updateLocalStorage */
-
-(function() {
-// This mapping table should match the discriminants of
-// `rustdoc::html::item_type::ItemType` type in Rust.
-var itemTypes = ["mod",
-                    "externcrate",
-                    "import",
-                    "struct",
-                    "enum",
-                    "fn",
-                    "type",
-                    "static",
-                    "trait",
-                    "impl",
-                    "tymethod",
-                    "method",
-                    "structfield",
-                    "variant",
-                    "macro",
-                    "primitive",
-                    "associatedtype",
-                    "constant",
-                    "associatedconstant",
-                    "union",
-                    "foreigntype",
-                    "keyword",
-                    "existential",
-                    "attr",
-                    "derive",
-                    "traitalias"];
-
-// used for special search precedence
-var TY_PRIMITIVE = itemTypes.indexOf("primitive");
-var TY_KEYWORD = itemTypes.indexOf("keyword");
-
-// In the search display, allows to switch between tabs.
-function printTab(nb) {
-    if (nb === 0 || nb === 1 || nb === 2) {
-        searchState.currentTab = nb;
-    }
-    var nb_copy = nb;
-    onEachLazy(document.getElementById("titles").childNodes, function(elem) {
-        if (nb_copy === 0) {
-            addClass(elem, "selected");
-        } else {
-            removeClass(elem, "selected");
-        }
-        nb_copy -= 1;
-    });
-    onEachLazy(document.getElementById("results").childNodes, function(elem) {
-        if (nb === 0) {
-            addClass(elem, "active");
-        } else {
-            removeClass(elem, "active");
-        }
-        nb -= 1;
-    });
-}
-
-function removeEmptyStringsFromArray(x) {
-    for (var i = 0, len = x.length; i < len; ++i) {
-        if (x[i] === "") {
-            x.splice(i, 1);
-            i -= 1;
-        }
-    }
-}
-
-/**
- * A function to compute the Levenshtein distance between two strings
- * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
- * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
- * This code is an unmodified version of the code written by Marco de Wit
- * and was found at https://stackoverflow.com/a/18514751/745719
- */
-var levenshtein_row2 = [];
-function levenshtein(s1, s2) {
-    if (s1 === s2) {
-        return 0;
-    }
-    var s1_len = s1.length, s2_len = s2.length;
-    if (s1_len && s2_len) {
-        var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
-        while (i1 < s1_len) {
-            row[i1] = ++i1;
-        }
-        while (i2 < s2_len) {
-            c2 = s2.charCodeAt(i2);
-            a = i2;
-            ++i2;
-            b = i2;
-            for (i1 = 0; i1 < s1_len; ++i1) {
-                c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
-                a = row[i1];
-                b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
-                row[i1] = b;
-            }
-        }
-        return b;
-    }
-    return s1_len + s2_len;
-}
-
-window.initSearch = function(rawSearchIndex) {
-    var MAX_LEV_DISTANCE = 3;
-    var MAX_RESULTS = 200;
-    var GENERICS_DATA = 2;
-    var NAME = 0;
-    var INPUTS_DATA = 0;
-    var OUTPUT_DATA = 1;
-    var NO_TYPE_FILTER = -1;
-    var currentResults, index, searchIndex;
-    var ALIASES = {};
-    var params = searchState.getQueryStringParams();
-
-    // Populate search bar with query string search term when provided,
-    // but only if the input bar is empty. This avoid the obnoxious issue
-    // where you start trying to do a search, and the index loads, and
-    // suddenly your search is gone!
-    if (searchState.input.value === "") {
-        searchState.input.value = params.search || "";
-    }
-
-    /**
-     * Executes the query and builds an index of results
-     * @param  {[Object]} query      [The user query]
-     * @param  {[type]} searchWords  [The list of search words to query
-     *                                against]
-     * @param  {[type]} filterCrates [Crate to search in if defined]
-     * @return {[type]}              [A search index of results]
-     */
-    function execQuery(query, searchWords, filterCrates) {
-        function itemTypeFromName(typename) {
-            for (var i = 0, len = itemTypes.length; i < len; ++i) {
-                if (itemTypes[i] === typename) {
-                    return i;
-                }
-            }
-            return NO_TYPE_FILTER;
-        }
-
-        var valLower = query.query.toLowerCase(),
-            val = valLower,
-            typeFilter = itemTypeFromName(query.type),
-            results = {}, results_in_args = {}, results_returned = {},
-            split = valLower.split("::");
-
-        removeEmptyStringsFromArray(split);
-
-        function transformResults(results) {
-            var out = [];
-            for (var i = 0, len = results.length; i < len; ++i) {
-                if (results[i].id > -1) {
-                    var obj = searchIndex[results[i].id];
-                    obj.lev = results[i].lev;
-                    var res = buildHrefAndPath(obj);
-                    obj.displayPath = pathSplitter(res[0]);
-                    obj.fullPath = obj.displayPath + obj.name;
-                    // To be sure than it some items aren't considered as duplicate.
-                    obj.fullPath += "|" + obj.ty;
-                    obj.href = res[1];
-                    out.push(obj);
-                    if (out.length >= MAX_RESULTS) {
-                        break;
-                    }
-                }
-            }
-            return out;
-        }
-
-        function sortResults(results, isType) {
-            var ar = [];
-            for (var entry in results) {
-                if (hasOwnPropertyRustdoc(results, entry)) {
-                    ar.push(results[entry]);
-                }
-            }
-            results = ar;
-            var i, len, result;
-            for (i = 0, len = results.length; i < len; ++i) {
-                result = results[i];
-                result.word = searchWords[result.id];
-                result.item = searchIndex[result.id] || {};
-            }
-            // if there are no results then return to default and fail
-            if (results.length === 0) {
-                return [];
-            }
-
-            results.sort(function(aaa, bbb) {
-                var a, b;
-
-                // sort by exact match with regard to the last word (mismatch goes later)
-                a = (aaa.word !== val);
-                b = (bbb.word !== val);
-                if (a !== b) { return a - b; }
-
-                // Sort by non levenshtein results and then levenshtein results by the distance
-                // (less changes required to match means higher rankings)
-                a = (aaa.lev);
-                b = (bbb.lev);
-                if (a !== b) { return a - b; }
-
-                // sort by crate (non-current crate goes later)
-                a = (aaa.item.crate !== window.currentCrate);
-                b = (bbb.item.crate !== window.currentCrate);
-                if (a !== b) { return a - b; }
-
-                // sort by item name length (longer goes later)
-                a = aaa.word.length;
-                b = bbb.word.length;
-                if (a !== b) { return a - b; }
-
-                // sort by item name (lexicographically larger goes later)
-                a = aaa.word;
-                b = bbb.word;
-                if (a !== b) { return (a > b ? +1 : -1); }
-
-                // sort by index of keyword in item name (no literal occurrence goes later)
-                a = (aaa.index < 0);
-                b = (bbb.index < 0);
-                if (a !== b) { return a - b; }
-                // (later literal occurrence, if any, goes later)
-                a = aaa.index;
-                b = bbb.index;
-                if (a !== b) { return a - b; }
-
-                // special precedence for primitive and keyword pages
-                if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
-                    (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
-                    return -1;
-                }
-                if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
-                    (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
-                    return 1;
-                }
-
-                // sort by description (no description goes later)
-                a = (aaa.item.desc === "");
-                b = (bbb.item.desc === "");
-                if (a !== b) { return a - b; }
-
-                // sort by type (later occurrence in `itemTypes` goes later)
-                a = aaa.item.ty;
-                b = bbb.item.ty;
-                if (a !== b) { return a - b; }
-
-                // sort by path (lexicographically larger goes later)
-                a = aaa.item.path;
-                b = bbb.item.path;
-                if (a !== b) { return (a > b ? +1 : -1); }
-
-                // que sera, sera
-                return 0;
-            });
-
-            for (i = 0, len = results.length; i < len; ++i) {
-                result = results[i];
-
-                // this validation does not make sense when searching by types
-                if (result.dontValidate) {
-                    continue;
-                }
-                var name = result.item.name.toLowerCase(),
-                    path = result.item.path.toLowerCase(),
-                    parent = result.item.parent;
-
-                if (!isType && !validateResult(name, path, split, parent)) {
-                    result.id = -1;
-                }
-            }
-            return transformResults(results);
-        }
-
-        function extractGenerics(val) {
-            val = val.toLowerCase();
-            if (val.indexOf("<") !== -1) {
-                var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
-                return {
-                    name: val.substring(0, val.indexOf("<")),
-                    generics: values.split(/\s*,\s*/),
-                };
-            }
-            return {
-                name: val,
-                generics: [],
-            };
-        }
-
-        function getObjectNameFromId(id) {
-            if (typeof id === "number") {
-                return searchIndex[id].name;
-            }
-            return id;
-        }
-
-        function checkGenerics(obj, val) {
-            // The names match, but we need to be sure that all generics kinda
-            // match as well.
-            var tmp_lev, elem_name;
-            if (val.generics.length > 0) {
-                if (obj.length > GENERICS_DATA &&
-                      obj[GENERICS_DATA].length >= val.generics.length) {
-                    var elems = Object.create(null);
-                    var elength = obj[GENERICS_DATA].length;
-                    for (var x = 0; x < elength; ++x) {
-                        if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) {
-                            elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0;
-                        }
-                        elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
-                    }
-                    var total = 0;
-                    var done = 0;
-                    // We need to find the type that matches the most to remove it in order
-                    // to move forward.
-                    var vlength = val.generics.length;
-                    for (x = 0; x < vlength; ++x) {
-                        var lev = MAX_LEV_DISTANCE + 1;
-                        var firstGeneric = getObjectNameFromId(val.generics[x]);
-                        var match = null;
-                        if (elems[firstGeneric]) {
-                            match = firstGeneric;
-                            lev = 0;
-                        } else {
-                            for (elem_name in elems) {
-                                tmp_lev = levenshtein(elem_name, firstGeneric);
-                                if (tmp_lev < lev) {
-                                    lev = tmp_lev;
-                                    match = elem_name;
-                                }
-                            }
-                        }
-                        if (match !== null) {
-                            elems[match] -= 1;
-                            if (elems[match] == 0) {
-                                delete elems[match];
-                            }
-                            total += lev;
-                            done += 1;
-                        } else {
-                            return MAX_LEV_DISTANCE + 1;
-                        }
-                    }
-                    return Math.ceil(total / done);
-                }
-            }
-            return MAX_LEV_DISTANCE + 1;
-        }
-
-        // Check for type name and type generics (if any).
-        function checkType(obj, val, literalSearch) {
-            var lev_distance = MAX_LEV_DISTANCE + 1;
-            var len, x, firstGeneric;
-            if (obj[NAME] === val.name) {
-                if (literalSearch) {
-                    if (val.generics && val.generics.length !== 0) {
-                        if (obj.length > GENERICS_DATA &&
-                             obj[GENERICS_DATA].length > 0) {
-                            var elems = Object.create(null);
-                            len = obj[GENERICS_DATA].length;
-                            for (x = 0; x < len; ++x) {
-                                if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) {
-                                    elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0;
-                                }
-                                elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
-                            }
-
-                            var allFound = true;
-                            len = val.generics.length;
-                            for (x = 0; x < len; ++x) {
-                                firstGeneric = getObjectNameFromId(val.generics[x]);
-                                if (elems[firstGeneric]) {
-                                    elems[firstGeneric] -= 1;
-                                } else {
-                                    allFound = false;
-                                    break;
-                                }
-                            }
-                            if (allFound) {
-                                return true;
-                            }
-                        }
-                        return false;
-                    }
-                    return true;
-                } else {
-                    // If the type has generics but don't match, then it won't return at this point.
-                    // Otherwise, `checkGenerics` will return 0 and it'll return.
-                    if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
-                        var tmp_lev = checkGenerics(obj, val);
-                        if (tmp_lev <= MAX_LEV_DISTANCE) {
-                            return tmp_lev;
-                        }
-                    }
-                }
-            } else if (literalSearch) {
-                if ((!val.generics || val.generics.length === 0) &&
-                      obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                    return obj[GENERICS_DATA].some(
-                        function(name) {
-                            return name === val.name;
-                        });
-                }
-                return false;
-            }
-            lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
-            if (lev_distance <= MAX_LEV_DISTANCE) {
-                // The generics didn't match but the name kinda did so we give it
-                // a levenshtein distance value that isn't *this* good so it goes
-                // into the search results but not too high.
-                lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
-            } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                // We can check if the type we're looking for is inside the generics!
-                var olength = obj[GENERICS_DATA].length;
-                for (x = 0; x < olength; ++x) {
-                    lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
-                                            lev_distance);
-                }
-            }
-            // Now whatever happens, the returned distance is "less good" so we should mark it
-            // as such, and so we add 1 to the distance to make it "less good".
-            return lev_distance + 1;
-        }
-
-        function findArg(obj, val, literalSearch, typeFilter) {
-            var lev_distance = MAX_LEV_DISTANCE + 1;
-
-            if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
-                var length = obj.type[INPUTS_DATA].length;
-                for (var i = 0; i < length; i++) {
-                    var tmp = obj.type[INPUTS_DATA][i];
-                    if (!typePassesFilter(typeFilter, tmp[1])) {
-                        continue;
-                    }
-                    tmp = checkType(tmp, val, literalSearch);
-                    if (literalSearch) {
-                        if (tmp) {
-                            return true;
-                        }
-                        continue;
-                    }
-                    lev_distance = Math.min(tmp, lev_distance);
-                    if (lev_distance === 0) {
-                        return 0;
-                    }
-                }
-            }
-            return literalSearch ? false : lev_distance;
-        }
-
-        function checkReturned(obj, val, literalSearch, typeFilter) {
-            var lev_distance = MAX_LEV_DISTANCE + 1;
-
-            if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
-                var ret = obj.type[OUTPUT_DATA];
-                if (typeof ret[0] === "string") {
-                    ret = [ret];
-                }
-                for (var x = 0, len = ret.length; x < len; ++x) {
-                    var tmp = ret[x];
-                    if (!typePassesFilter(typeFilter, tmp[1])) {
-                        continue;
-                    }
-                    tmp = checkType(tmp, val, literalSearch);
-                    if (literalSearch) {
-                        if (tmp) {
-                            return true;
-                        }
-                        continue;
-                    }
-                    lev_distance = Math.min(tmp, lev_distance);
-                    if (lev_distance === 0) {
-                        return 0;
-                    }
-                }
-            }
-            return literalSearch ? false : lev_distance;
-        }
-
-        function checkPath(contains, lastElem, ty) {
-            if (contains.length === 0) {
-                return 0;
-            }
-            var ret_lev = MAX_LEV_DISTANCE + 1;
-            var path = ty.path.split("::");
-
-            if (ty.parent && ty.parent.name) {
-                path.push(ty.parent.name.toLowerCase());
-            }
-
-            var length = path.length;
-            var clength = contains.length;
-            if (clength > length) {
-                return MAX_LEV_DISTANCE + 1;
-            }
-            for (var i = 0; i < length; ++i) {
-                if (i + clength > length) {
-                    break;
-                }
-                var lev_total = 0;
-                var aborted = false;
-                for (var x = 0; x < clength; ++x) {
-                    var lev = levenshtein(path[i + x], contains[x]);
-                    if (lev > MAX_LEV_DISTANCE) {
-                        aborted = true;
-                        break;
-                    }
-                    lev_total += lev;
-                }
-                if (!aborted) {
-                    ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
-                }
-            }
-            return ret_lev;
-        }
-
-        function typePassesFilter(filter, type) {
-            // No filter
-            if (filter <= NO_TYPE_FILTER) return true;
-
-            // Exact match
-            if (filter === type) return true;
-
-            // Match related items
-            var name = itemTypes[type];
-            switch (itemTypes[filter]) {
-                case "constant":
-                    return name === "associatedconstant";
-                case "fn":
-                    return name === "method" || name === "tymethod";
-                case "type":
-                    return name === "primitive" || name === "associatedtype";
-                case "trait":
-                    return name === "traitalias";
-            }
-
-            // No match
-            return false;
-        }
-
-        function createAliasFromItem(item) {
-            return {
-                crate: item.crate,
-                name: item.name,
-                path: item.path,
-                desc: item.desc,
-                ty: item.ty,
-                parent: item.parent,
-                type: item.type,
-                is_alias: true,
-            };
-        }
-
-        function handleAliases(ret, query, filterCrates) {
-            // We separate aliases and crate aliases because we want to have current crate
-            // aliases to be before the others in the displayed results.
-            var aliases = [];
-            var crateAliases = [];
-            if (filterCrates !== undefined) {
-                if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
-                    var query_aliases = ALIASES[filterCrates][query.search];
-                    var len = query_aliases.length;
-                    for (var i = 0; i < len; ++i) {
-                        aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
-                    }
-                }
-            } else {
-                Object.keys(ALIASES).forEach(function(crate) {
-                    if (ALIASES[crate][query.search]) {
-                        var pushTo = crate === window.currentCrate ? crateAliases : aliases;
-                        var query_aliases = ALIASES[crate][query.search];
-                        var len = query_aliases.length;
-                        for (var i = 0; i < len; ++i) {
-                            pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
-                        }
-                    }
-                });
-            }
-
-            var sortFunc = function(aaa, bbb) {
-                if (aaa.path < bbb.path) {
-                    return 1;
-                } else if (aaa.path === bbb.path) {
-                    return 0;
-                }
-                return -1;
-            };
-            crateAliases.sort(sortFunc);
-            aliases.sort(sortFunc);
-
-            var pushFunc = function(alias) {
-                alias.alias = query.raw;
-                var res = buildHrefAndPath(alias);
-                alias.displayPath = pathSplitter(res[0]);
-                alias.fullPath = alias.displayPath + alias.name;
-                alias.href = res[1];
-
-                ret.others.unshift(alias);
-                if (ret.others.length > MAX_RESULTS) {
-                    ret.others.pop();
-                }
-            };
-            onEach(aliases, pushFunc);
-            onEach(crateAliases, pushFunc);
-        }
-
-        // quoted values mean literal search
-        var nSearchWords = searchWords.length;
-        var i, it;
-        var ty;
-        var fullId;
-        var returned;
-        var in_args;
-        var len;
-        if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
-            val.charAt(val.length - 1) === val.charAt(0))
-        {
-            val = extractGenerics(val.substr(1, val.length - 2));
-            for (i = 0; i < nSearchWords; ++i) {
-                if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
-                    continue;
-                }
-                in_args = findArg(searchIndex[i], val, true, typeFilter);
-                returned = checkReturned(searchIndex[i], val, true, typeFilter);
-                ty = searchIndex[i];
-                fullId = ty.id;
-
-                if (searchWords[i] === val.name
-                    && typePassesFilter(typeFilter, searchIndex[i].ty)
-                    && results[fullId] === undefined) {
-                    results[fullId] = {
-                        id: i,
-                        index: -1,
-                        dontValidate: true,
-                    };
-                }
-                if (in_args && results_in_args[fullId] === undefined) {
-                    results_in_args[fullId] = {
-                        id: i,
-                        index: -1,
-                        dontValidate: true,
-                    };
-                }
-                if (returned && results_returned[fullId] === undefined) {
-                    results_returned[fullId] = {
-                        id: i,
-                        index: -1,
-                        dontValidate: true,
-                    };
-                }
-            }
-            query.inputs = [val];
-            query.output = val;
-            query.search = val;
-        // searching by type
-        } else if (val.search("->") > -1) {
-            var trimmer = function(s) { return s.trim(); };
-            var parts = val.split("->").map(trimmer);
-            var input = parts[0];
-            // sort inputs so that order does not matter
-            var inputs = input.split(",").map(trimmer).sort();
-            for (i = 0, len = inputs.length; i < len; ++i) {
-                inputs[i] = extractGenerics(inputs[i]);
-            }
-            var output = extractGenerics(parts[1]);
-
-            for (i = 0; i < nSearchWords; ++i) {
-                if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
-                    continue;
-                }
-                var type = searchIndex[i].type;
-                ty = searchIndex[i];
-                if (!type) {
-                    continue;
-                }
-                fullId = ty.id;
-
-                returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
-                if (output.name === "*" || returned) {
-                    in_args = false;
-                    var is_module = false;
-
-                    if (input === "*") {
-                        is_module = true;
-                    } else {
-                        var allFound = true;
-                        for (it = 0, len = inputs.length; allFound && it < len; it++) {
-                            allFound = checkType(type, inputs[it], true);
-                        }
-                        in_args = allFound;
-                    }
-                    if (in_args) {
-                        results_in_args[fullId] = {
-                            id: i,
-                            index: -1,
-                            dontValidate: true,
-                        };
-                    }
-                    if (returned) {
-                        results_returned[fullId] = {
-                            id: i,
-                            index: -1,
-                            dontValidate: true,
-                        };
-                    }
-                    if (is_module) {
-                        results[fullId] = {
-                            id: i,
-                            index: -1,
-                            dontValidate: true,
-                        };
-                    }
-                }
-            }
-            query.inputs = inputs.map(function(input) {
-                return input.name;
-            });
-            query.output = output.name;
-        } else {
-            query.inputs = [val];
-            query.output = val;
-            query.search = val;
-            // gather matching search results up to a certain maximum
-            val = val.replace(/_/g, "");
-
-            var valGenerics = extractGenerics(val);
-
-            var paths = valLower.split("::");
-            removeEmptyStringsFromArray(paths);
-            val = paths[paths.length - 1];
-            var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
-
-            var lev, j;
-            for (j = 0; j < nSearchWords; ++j) {
-                ty = searchIndex[j];
-                if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
-                    continue;
-                }
-                var lev_add = 0;
-                if (paths.length > 1) {
-                    lev = checkPath(contains, paths[paths.length - 1], ty);
-                    if (lev > MAX_LEV_DISTANCE) {
-                        continue;
-                    } else if (lev > 0) {
-                        lev_add = lev / 10;
-                    }
-                }
-
-                returned = MAX_LEV_DISTANCE + 1;
-                in_args = MAX_LEV_DISTANCE + 1;
-                var index = -1;
-                // we want lev results to go lower than others
-                lev = MAX_LEV_DISTANCE + 1;
-                fullId = ty.id;
-
-                if (searchWords[j].indexOf(split[i]) > -1 ||
-                    searchWords[j].indexOf(val) > -1 ||
-                    ty.normalizedName.indexOf(val) > -1)
-                {
-                    // filter type: ... queries
-                    if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
-                        index = ty.normalizedName.indexOf(val);
-                    }
-                }
-                if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
-                    if (typePassesFilter(typeFilter, ty.ty)) {
-                        lev += 1;
-                    } else {
-                        lev = MAX_LEV_DISTANCE + 1;
-                    }
-                }
-                in_args = findArg(ty, valGenerics, false, typeFilter);
-                returned = checkReturned(ty, valGenerics, false, typeFilter);
-
-                lev += lev_add;
-                if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
-                    if (val.length < 6) {
-                        lev -= 1;
-                    } else {
-                        lev = 0;
-                    }
-                }
-                if (in_args <= MAX_LEV_DISTANCE) {
-                    if (results_in_args[fullId] === undefined) {
-                        results_in_args[fullId] = {
-                            id: j,
-                            index: index,
-                            lev: in_args,
-                        };
-                    }
-                    results_in_args[fullId].lev =
-                        Math.min(results_in_args[fullId].lev, in_args);
-                }
-                if (returned <= MAX_LEV_DISTANCE) {
-                    if (results_returned[fullId] === undefined) {
-                        results_returned[fullId] = {
-                            id: j,
-                            index: index,
-                            lev: returned,
-                        };
-                    }
-                    results_returned[fullId].lev =
-                        Math.min(results_returned[fullId].lev, returned);
-                }
-                if (typePassesFilter(typeFilter, ty.ty) &&
-                        (index !== -1 || lev <= MAX_LEV_DISTANCE)) {
-                    if (index !== -1 && paths.length < 2) {
-                        lev = 0;
-                    }
-                    if (results[fullId] === undefined) {
-                        results[fullId] = {
-                            id: j,
-                            index: index,
-                            lev: lev,
-                        };
-                    }
-                    results[fullId].lev = Math.min(results[fullId].lev, lev);
-                }
-            }
-        }
-
-        var ret = {
-            "in_args": sortResults(results_in_args, true),
-            "returned": sortResults(results_returned, true),
-            "others": sortResults(results, false),
-        };
-        handleAliases(ret, query, filterCrates);
-        return ret;
-    }
-
-    /**
-     * Validate performs the following boolean logic. For example:
-     * "File::open" will give IF A PARENT EXISTS => ("file" && "open")
-     * exists in (name || path || parent) OR => ("file" && "open") exists in
-     * (name || path )
-     *
-     * This could be written functionally, but I wanted to minimise
-     * functions on stack.
-     *
-     * @param  {[string]} name   [The name of the result]
-     * @param  {[string]} path   [The path of the result]
-     * @param  {[string]} keys   [The keys to be used (["file", "open"])]
-     * @param  {[object]} parent [The parent of the result]
-     * @return {boolean}       [Whether the result is valid or not]
-     */
-    function validateResult(name, path, keys, parent) {
-        for (var i = 0, len = keys.length; i < len; ++i) {
-            // each check is for validation so we negate the conditions and invalidate
-            if (!(
-                // check for an exact name match
-                name.indexOf(keys[i]) > -1 ||
-                // then an exact path match
-                path.indexOf(keys[i]) > -1 ||
-                // next if there is a parent, check for exact parent match
-                (parent !== undefined && parent.name !== undefined &&
-                    parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
-                // lastly check to see if the name was a levenshtein match
-                levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    function getQuery(raw) {
-        var matches, type, query;
-        query = raw;
-
-        matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
-        if (matches) {
-            type = matches[1].replace(/^const$/, "constant");
-            query = query.substring(matches[0].length);
-        }
-
-        return {
-            raw: raw,
-            query: query,
-            type: type,
-            id: query + type
-        };
-    }
-
-    function nextTab(direction) {
-        var next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length;
-        searchState.focusedByTab[searchState.currentTab] = document.activeElement;
-        printTab(next);
-        focusSearchResult();
-    }
-
-    // Focus the first search result on the active tab, or the result that
-    // was focused last time this tab was active.
-    function focusSearchResult() {
-        var target = searchState.focusedByTab[searchState.currentTab] ||
-            document.querySelectorAll(".search-results.active a").item(0) ||
-            document.querySelectorAll("#titles > button").item(searchState.currentTab);
-        if (target) {
-            target.focus();
-        }
-    }
-
-    function buildHrefAndPath(item) {
-        var displayPath;
-        var href;
-        var type = itemTypes[item.ty];
-        var name = item.name;
-        var path = item.path;
-
-        if (type === "mod") {
-            displayPath = path + "::";
-            href = window.rootPath + path.replace(/::/g, "/") + "/" +
-                   name + "/index.html";
-        } else if (type === "primitive" || type === "keyword") {
-            displayPath = "";
-            href = window.rootPath + path.replace(/::/g, "/") +
-                   "/" + type + "." + name + ".html";
-        } else if (type === "externcrate") {
-            displayPath = "";
-            href = window.rootPath + name + "/index.html";
-        } else if (item.parent !== undefined) {
-            var myparent = item.parent;
-            var anchor = "#" + type + "." + name;
-            var parentType = itemTypes[myparent.ty];
-            var pageType = parentType;
-            var pageName = myparent.name;
-
-            if (parentType === "primitive") {
-                displayPath = myparent.name + "::";
-            } else if (type === "structfield" && parentType === "variant") {
-                // Structfields belonging to variants are special: the
-                // final path element is the enum name.
-                var enumNameIdx = item.path.lastIndexOf("::");
-                var enumName = item.path.substr(enumNameIdx + 2);
-                path = item.path.substr(0, enumNameIdx);
-                displayPath = path + "::" + enumName + "::" + myparent.name + "::";
-                anchor = "#variant." + myparent.name + ".field." + name;
-                pageType = "enum";
-                pageName = enumName;
-            } else {
-                displayPath = path + "::" + myparent.name + "::";
-            }
-            href = window.rootPath + path.replace(/::/g, "/") +
-                   "/" + pageType +
-                   "." + pageName +
-                   ".html" + anchor;
-        } else {
-            displayPath = item.path + "::";
-            href = window.rootPath + item.path.replace(/::/g, "/") +
-                   "/" + type + "." + name + ".html";
-        }
-        return [displayPath, href];
-    }
-
-    function escape(content) {
-        var h1 = document.createElement("h1");
-        h1.textContent = content;
-        return h1.innerHTML;
-    }
-
-    function pathSplitter(path) {
-        var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
-        if (tmp.endsWith("<span>")) {
-            return tmp.slice(0, tmp.length - 6);
-        }
-        return tmp;
-    }
-
-    function addTab(array, query, display) {
-        var extraClass = "";
-        if (display === true) {
-            extraClass = " active";
-        }
-
-        var output = document.createElement("div");
-        var duplicates = {};
-        var length = 0;
-        if (array.length > 0) {
-            output.className = "search-results " + extraClass;
-
-            array.forEach(function(item) {
-                if (item.is_alias !== true) {
-                    if (duplicates[item.fullPath]) {
-                        return;
-                    }
-                    duplicates[item.fullPath] = true;
-                }
-
-                var name = item.name;
-                var type = itemTypes[item.ty];
-
-                length += 1;
-
-                var extra = "";
-                if (type === "primitive") {
-                    extra = " <i>(primitive type)</i>";
-                } else if (type === "keyword") {
-                    extra = " <i>(keyword)</i>";
-                }
-
-                var link = document.createElement("a");
-                link.className = "result-" + type;
-                link.href = item.href;
-
-                var wrapper = document.createElement("div");
-                var resultName = document.createElement("div");
-                resultName.className = "result-name";
-
-                if (item.is_alias) {
-                    var alias = document.createElement("span");
-                    alias.className = "alias";
-
-                    var bold = document.createElement("b");
-                    bold.innerText = item.alias;
-                    alias.appendChild(bold);
-
-                    alias.insertAdjacentHTML(
-                        "beforeend",
-                        "<span class=\"grey\"><i>&nbsp;- see&nbsp;</i></span>");
-
-                    resultName.appendChild(alias);
-                }
-                resultName.insertAdjacentHTML(
-                    "beforeend",
-                    item.displayPath + "<span class=\"" + type + "\">" + name + extra + "</span>");
-                wrapper.appendChild(resultName);
-
-                var description = document.createElement("div");
-                description.className = "desc";
-                var spanDesc = document.createElement("span");
-                spanDesc.insertAdjacentHTML("beforeend", item.desc);
-
-                description.appendChild(spanDesc);
-                wrapper.appendChild(description);
-                link.appendChild(wrapper);
-                output.appendChild(link);
-            });
-        } else {
-            output.className = "search-failed" + extraClass;
-            output.innerHTML = "No results :(<br/>" +
-                "Try on <a href=\"https://duckduckgo.com/?q=" +
-                encodeURIComponent("rust " + query.query) +
-                "\">DuckDuckGo</a>?<br/><br/>" +
-                "Or try looking in one of these:<ul><li>The <a " +
-                "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
-                " for technical details about the language.</li><li><a " +
-                "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
-                "Example</a> for expository code examples.</a></li><li>The <a " +
-                "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
-                "introductions to language features and the language itself.</li><li><a " +
-                "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
-                " <a href=\"https://crates.io/\">crates.io</a>.</li></ul>";
-        }
-        return [output, length];
-    }
-
-    function makeTabHeader(tabNb, text, nbElems) {
-        if (searchState.currentTab === tabNb) {
-            return "<button class=\"selected\">" + text +
-                   " <div class=\"count\">(" + nbElems + ")</div></button>";
-        }
-        return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
-    }
-
-    function showResults(results, go_to_first) {
-        var search = searchState.outputElement();
-        if (go_to_first || (results.others.length === 1
-            && getSettingValue("go-to-only-result") === "true"
-            // By default, the search DOM element is "empty" (meaning it has no children not
-            // text content). Once a search has been run, it won't be empty, even if you press
-            // ESC or empty the search input (which also "cancels" the search).
-            && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)))
-        {
-            var elem = document.createElement("a");
-            elem.href = results.others[0].href;
-            removeClass(elem, "active");
-            // For firefox, we need the element to be in the DOM so it can be clicked.
-            document.body.appendChild(elem);
-            elem.click();
-            return;
-        }
-        var query = getQuery(searchState.input.value);
-
-        currentResults = query.id;
-
-        var ret_others = addTab(results.others, query);
-        var ret_in_args = addTab(results.in_args, query, false);
-        var ret_returned = addTab(results.returned, query, false);
-
-        // Navigate to the relevant tab if the current tab is empty, like in case users search
-        // for "-> String". If they had selected another tab previously, they have to click on
-        // it again.
-        var currentTab = searchState.currentTab;
-        if ((currentTab === 0 && ret_others[1] === 0) ||
-                (currentTab === 1 && ret_in_args[1] === 0) ||
-                (currentTab === 2 && ret_returned[1] === 0)) {
-            if (ret_others[1] !== 0) {
-                currentTab = 0;
-            } else if (ret_in_args[1] !== 0) {
-                currentTab = 1;
-            } else if (ret_returned[1] !== 0) {
-                currentTab = 2;
-            }
-        }
-
-        var output = "<h1>Results for " + escape(query.query) +
-            (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
-            "<div id=\"titles\">" +
-            makeTabHeader(0, "In Names", ret_others[1]) +
-            makeTabHeader(1, "In Parameters", ret_in_args[1]) +
-            makeTabHeader(2, "In Return Types", ret_returned[1]) +
-            "</div>";
-
-        var resultsElem = document.createElement("div");
-        resultsElem.id = "results";
-        resultsElem.appendChild(ret_others[0]);
-        resultsElem.appendChild(ret_in_args[0]);
-        resultsElem.appendChild(ret_returned[0]);
-
-        search.innerHTML = output;
-        search.appendChild(resultsElem);
-        // Reset focused elements.
-        searchState.focusedByTab = [null, null, null];
-        searchState.showResults(search);
-        var elems = document.getElementById("titles").childNodes;
-        elems[0].onclick = function() { printTab(0); };
-        elems[1].onclick = function() { printTab(1); };
-        elems[2].onclick = function() { printTab(2); };
-        printTab(currentTab);
-    }
-
-    function execSearch(query, searchWords, filterCrates) {
-        function getSmallest(arrays, positions, notDuplicates) {
-            var start = null;
-
-            for (var it = 0, len = positions.length; it < len; ++it) {
-                if (arrays[it].length > positions[it] &&
-                    (start === null || start > arrays[it][positions[it]].lev) &&
-                    !notDuplicates[arrays[it][positions[it]].fullPath]) {
-                    start = arrays[it][positions[it]].lev;
-                }
-            }
-            return start;
-        }
-
-        function mergeArrays(arrays) {
-            var ret = [];
-            var positions = [];
-            var notDuplicates = {};
-
-            for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
-                positions.push(0);
-            }
-            while (ret.length < MAX_RESULTS) {
-                var smallest = getSmallest(arrays, positions, notDuplicates);
-
-                if (smallest === null) {
-                    break;
-                }
-                for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
-                    if (arrays[x].length > positions[x] &&
-                            arrays[x][positions[x]].lev === smallest &&
-                            !notDuplicates[arrays[x][positions[x]].fullPath]) {
-                        ret.push(arrays[x][positions[x]]);
-                        notDuplicates[arrays[x][positions[x]].fullPath] = true;
-                        positions[x] += 1;
-                    }
-                }
-            }
-            return ret;
-        }
-
-        // Split search query by ",", while respecting angle bracket nesting.
-        // Since "<" is an alias for the Ord family of traits, it also uses
-        // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket.
-        //
-        // tokenizeQuery("A<B, C>, D") == ["A<B, C>", "D"]
-        // tokenizeQuery("A<B, C, D") == ["A<B", "C", "D"]
-        function tokenizeQuery(raw) {
-            var i, matched;
-            var l = raw.length;
-            var depth = 0;
-            var nextAngle = /(<|>)/g;
-            var ret = [];
-            var start = 0;
-            for (i = 0; i < l; ++i) {
-                switch (raw[i]) {
-                    case "<":
-                        nextAngle.lastIndex = i + 1;
-                        matched = nextAngle.exec(raw);
-                        if (matched && matched[1] === '>') {
-                            depth += 1;
-                        }
-                        break;
-                    case ">":
-                        if (depth > 0) {
-                            depth -= 1;
-                        }
-                        break;
-                    case ",":
-                        if (depth === 0) {
-                            ret.push(raw.substring(start, i));
-                            start = i + 1;
-                        }
-                        break;
-                }
-            }
-            if (start !== i) {
-                ret.push(raw.substring(start, i));
-            }
-            return ret;
-        }
-
-        var queries = tokenizeQuery(query.raw);
-        var results = {
-            "in_args": [],
-            "returned": [],
-            "others": [],
-        };
-
-        for (var i = 0, len = queries.length; i < len; ++i) {
-            query = queries[i].trim();
-            if (query.length !== 0) {
-                var tmp = execQuery(getQuery(query), searchWords, filterCrates);
-
-                results.in_args.push(tmp.in_args);
-                results.returned.push(tmp.returned);
-                results.others.push(tmp.others);
-            }
-        }
-        if (queries.length > 1) {
-            return {
-                "in_args": mergeArrays(results.in_args),
-                "returned": mergeArrays(results.returned),
-                "others": mergeArrays(results.others),
-            };
-        }
-        return {
-            "in_args": results.in_args[0],
-            "returned": results.returned[0],
-            "others": results.others[0],
-        };
-    }
-
-    function getFilterCrates() {
-        var elem = document.getElementById("crate-search");
-
-        if (elem && elem.value !== "All crates" &&
-            hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
-        {
-            return elem.value;
-        }
-        return undefined;
-    }
-
-    function search(e, forced) {
-        var params = searchState.getQueryStringParams();
-        var query = getQuery(searchState.input.value.trim());
-
-        if (e) {
-            e.preventDefault();
-        }
-
-        if (query.query.length === 0) {
-            return;
-        }
-        if (!forced && query.id === currentResults) {
-            if (query.query.length > 0) {
-                searchState.putBackSearch(searchState.input);
-            }
-            return;
-        }
-
-        // Update document title to maintain a meaningful browser history
-        searchState.title = "Results for " + query.query + " - Rust";
-
-        // Because searching is incremental by character, only the most
-        // recent search query is added to the browser history.
-        if (searchState.browserSupportsHistoryApi()) {
-            var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
-                window.location.hash;
-            if (!history.state && !params.search) {
-                history.pushState(query, "", newURL);
-            } else {
-                history.replaceState(query, "", newURL);
-            }
-        }
-
-        var filterCrates = getFilterCrates();
-        showResults(execSearch(query, index, filterCrates), params.go_to_first);
-    }
-
-    function buildIndex(rawSearchIndex) {
-        searchIndex = [];
-        var searchWords = [];
-        var i, word;
-        var currentIndex = 0;
-        var id = 0;
-
-        for (var crate in rawSearchIndex) {
-            if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
-                continue;
-            }
-
-            var crateSize = 0;
-
-            searchWords.push(crate);
-            // This object should have exactly the same set of fields as the "row"
-            // object defined below. Your JavaScript runtime will thank you.
-            // https://mathiasbynens.be/notes/shapes-ics
-            var crateRow = {
-                crate: crate,
-                ty: 1, // == ExternCrate
-                name: crate,
-                path: "",
-                desc: rawSearchIndex[crate].doc,
-                parent: undefined,
-                type: null,
-                id: id,
-                normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
-            };
-            id += 1;
-            searchIndex.push(crateRow);
-            currentIndex += 1;
-
-            // an array of (Number) item types
-            var itemTypes = rawSearchIndex[crate].t;
-            // an array of (String) item names
-            var itemNames = rawSearchIndex[crate].n;
-            // an array of (String) full paths (or empty string for previous path)
-            var itemPaths = rawSearchIndex[crate].q;
-            // an array of (String) descriptions
-            var itemDescs = rawSearchIndex[crate].d;
-            // an array of (Number) the parent path index + 1 to `paths`, or 0 if none
-            var itemParentIdxs = rawSearchIndex[crate].i;
-            // an array of (Object | null) the type of the function, if any
-            var itemFunctionSearchTypes = rawSearchIndex[crate].f;
-            // an array of [(Number) item type,
-            //              (String) name]
-            var paths = rawSearchIndex[crate].p;
-            // a array of [(String) alias name
-            //             [Number] index to items]
-            var aliases = rawSearchIndex[crate].a;
-
-            // convert `rawPaths` entries into object form
-            var len = paths.length;
-            for (i = 0; i < len; ++i) {
-                paths[i] = {ty: paths[i][0], name: paths[i][1]};
-            }
-
-            // convert `item*` into an object form, and construct word indices.
-            //
-            // before any analysis is performed lets gather the search terms to
-            // search against apart from the rest of the data.  This is a quick
-            // operation that is cached for the life of the page state so that
-            // all other search operations have access to this cached data for
-            // faster analysis operations
-            len = itemTypes.length;
-            var lastPath = "";
-            for (i = 0; i < len; ++i) {
-                // This object should have exactly the same set of fields as the "crateRow"
-                // object defined above.
-                if (typeof itemNames[i] === "string") {
-                    word = itemNames[i].toLowerCase();
-                    searchWords.push(word);
-                } else {
-                    word = "";
-                    searchWords.push("");
-                }
-                var row = {
-                    crate: crate,
-                    ty: itemTypes[i],
-                    name: itemNames[i],
-                    path: itemPaths[i] ? itemPaths[i] : lastPath,
-                    desc: itemDescs[i],
-                    parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
-                    type: itemFunctionSearchTypes[i],
-                    id: id,
-                    normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
-                };
-                id += 1;
-                searchIndex.push(row);
-                lastPath = row.path;
-                crateSize += 1;
-            }
-
-            if (aliases) {
-                ALIASES[crate] = {};
-                var j, local_aliases;
-                for (var alias_name in aliases) {
-                    if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
-                        continue;
-                    }
-
-                    if (!hasOwnPropertyRustdoc(ALIASES[crate], alias_name)) {
-                        ALIASES[crate][alias_name] = [];
-                    }
-                    local_aliases = aliases[alias_name];
-                    for (j = 0, len = local_aliases.length; j < len; ++j) {
-                        ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
-                    }
-                }
-            }
-            currentIndex += crateSize;
-        }
-        return searchWords;
-    }
-
-    function registerSearchEvents() {
-        var searchAfter500ms = function() {
-            searchState.clearInputTimeout();
-            if (searchState.input.value.length === 0) {
-                if (searchState.browserSupportsHistoryApi()) {
-                    history.replaceState("", window.currentCrate + " - Rust",
-                        getNakedUrl() + window.location.hash);
-                }
-                searchState.hideResults();
-            } else {
-                searchState.timeout = setTimeout(search, 500);
-            }
-        };
-        searchState.input.onkeyup = searchAfter500ms;
-        searchState.input.oninput = searchAfter500ms;
-        document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
-            e.preventDefault();
-            searchState.clearInputTimeout();
-            search();
-        };
-        searchState.input.onchange = function(e) {
-            if (e.target !== document.activeElement) {
-                // To prevent doing anything when it's from a blur event.
-                return;
-            }
-            // Do NOT e.preventDefault() here. It will prevent pasting.
-            searchState.clearInputTimeout();
-            // zero-timeout necessary here because at the time of event handler execution the
-            // pasted content is not in the input field yet. Shouldn’t make any difference for
-            // change, though.
-            setTimeout(search, 0);
-        };
-        searchState.input.onpaste = searchState.input.onchange;
-
-        searchState.outputElement().addEventListener("keydown", function(e) {
-            // We only handle unmodified keystrokes here. We don't want to interfere with,
-            // for instance, alt-left and alt-right for history navigation.
-            if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
-                return;
-            }
-            // up and down arrow select next/previous search result, or the
-            // search box if we're already at the top.
-            if (e.which === 38) { // up
-                var previous = document.activeElement.previousElementSibling;
-                if (previous) {
-                    previous.focus();
-                } else {
-                    searchState.focus();
-                }
-                e.preventDefault();
-            } else if (e.which === 40) { // down
-                var next = document.activeElement.nextElementSibling;
-                if (next) {
-                    next.focus();
-                }
-                var rect = document.activeElement.getBoundingClientRect();
-                if (window.innerHeight - rect.bottom < rect.height) {
-                    window.scrollBy(0, rect.height);
-                }
-                e.preventDefault();
-            } else if (e.which === 37) { // left
-                nextTab(-1);
-                e.preventDefault();
-            } else if (e.which === 39) { // right
-                nextTab(1);
-                e.preventDefault();
-            }
-        });
-
-        searchState.input.addEventListener("keydown", function(e) {
-            if (e.which === 40) { // down
-                focusSearchResult();
-                e.preventDefault();
-            }
-        });
-
-
-        var selectCrate = document.getElementById("crate-search");
-        if (selectCrate) {
-            selectCrate.onchange = function() {
-                updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value);
-                // In case you "cut" the entry from the search input, then change the crate filter
-                // before paste back the previous search, you get the old search results without
-                // the filter. To prevent this, we need to remove the previous results.
-                currentResults = null;
-                search(undefined, true);
-            };
-        }
-
-        // Push and pop states are used to add search results to the browser
-        // history.
-        if (searchState.browserSupportsHistoryApi()) {
-            // Store the previous <title> so we can revert back to it later.
-            var previousTitle = document.title;
-
-            window.addEventListener("popstate", function(e) {
-                var params = searchState.getQueryStringParams();
-                // Revert to the previous title manually since the History
-                // API ignores the title parameter.
-                document.title = previousTitle;
-                // When browsing forward to search results the previous
-                // search will be repeated, so the currentResults are
-                // cleared to ensure the search is successful.
-                currentResults = null;
-                // Synchronize search bar with query string state and
-                // perform the search. This will empty the bar if there's
-                // nothing there, which lets you really go back to a
-                // previous state with nothing in the bar.
-                if (params.search && params.search.length > 0) {
-                    searchState.input.value = params.search;
-                    // Some browsers fire "onpopstate" for every page load
-                    // (Chrome), while others fire the event only when actually
-                    // popping a state (Firefox), which is why search() is
-                    // called both here and at the end of the startSearch()
-                    // function.
-                    search(e);
-                } else {
-                    searchState.input.value = "";
-                    // When browsing back from search results the main page
-                    // visibility must be reset.
-                    searchState.hideResults();
-                }
-            });
-        }
-
-        // This is required in firefox to avoid this problem: Navigating to a search result
-        // with the keyboard, hitting enter, and then hitting back would take you back to
-        // the doc page, rather than the search that should overlay it.
-        // This was an interaction between the back-forward cache and our handlers
-        // that try to sync state between the URL and the search input. To work around it,
-        // do a small amount of re-init on page show.
-        window.onpageshow = function(){
-            var qSearch = searchState.getQueryStringParams().search;
-            if (searchState.input.value === "" && qSearch) {
-                searchState.input.value = qSearch;
-            }
-            search();
-        };
-    }
-
-    index = buildIndex(rawSearchIndex);
-    registerSearchEvents();
-    // If there's a search term in the URL, execute the search now.
-    if (searchState.getQueryStringParams().search) {
-        search();
-    }
-};
-
-if (window.searchIndex !== undefined) {
-    initSearch(window.searchIndex);
-}
-
-})();
diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css
deleted file mode 100644 (file)
index fb8990b..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-.setting-line {
-       padding: 5px;
-       position: relative;
-}
-
-.setting-line > div {
-       display: inline-block;
-       vertical-align: top;
-       font-size: 17px;
-       padding-top: 2px;
-}
-
-.setting-line > .title {
-       font-size: 19px;
-       width: 100%;
-       max-width: none;
-       border-bottom: 1px solid;
-}
-
-.toggle {
-       position: relative;
-       display: inline-block;
-       width: 45px;
-       height: 27px;
-       margin-right: 20px;
-}
-
-.toggle input {
-       opacity: 0;
-       position: absolute;
-}
-
-.select-wrapper {
-       float: right;
-       position: relative;
-       height: 27px;
-       min-width: 25%;
-}
-
-.select-wrapper select {
-       appearance: none;
-       -moz-appearance: none;
-       -webkit-appearance: none;
-       background: none;
-       border: 2px solid #ccc;
-       padding-right: 28px;
-       width: 100%;
-}
-
-.select-wrapper img {
-       pointer-events: none;
-       position: absolute;
-       right: 0;
-       bottom: 0;
-       background: #ccc;
-       height: 100%;
-       width: 28px;
-       padding: 0px 4px;
-}
-
-.select-wrapper select option {
-       color: initial;
-}
-
-.slider {
-       position: absolute;
-       cursor: pointer;
-       top: 0;
-       left: 0;
-       right: 0;
-       bottom: 0;
-       background-color: #ccc;
-       -webkit-transition: .3s;
-       transition: .3s;
-}
-
-.slider:before {
-       position: absolute;
-       content: "";
-       height: 19px;
-       width: 19px;
-       left: 4px;
-       bottom: 4px;
-       background-color: white;
-       -webkit-transition: .3s;
-       transition: .3s;
-}
-
-input:checked + .slider {
-       background-color: #2196F3;
-}
-
-input:focus + .slider {
-       box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
-}
-
-input:checked + .slider:before {
-       -webkit-transform: translateX(19px);
-       -ms-transform: translateX(19px);
-       transform: translateX(19px);
-}
-
-.setting-line > .sub-settings {
-       padding-left: 42px;
-       width: 100%;
-       display: block;
-}
diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js
deleted file mode 100644 (file)
index 4f10e14..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// Local js definitions:
-/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
-
-(function () {
-    function changeSetting(settingName, value) {
-        updateLocalStorage("rustdoc-" + settingName, value);
-
-        switch (settingName) {
-            case "preferred-dark-theme":
-            case "preferred-light-theme":
-            case "use-system-theme":
-                updateSystemTheme();
-                break;
-        }
-    }
-
-    function handleKey(ev) {
-        // Don't interfere with browser shortcuts
-        if (ev.ctrlKey || ev.altKey || ev.metaKey) {
-            return;
-        }
-        switch (getVirtualKey(ev)) {
-            case "Enter":
-            case "Return":
-            case "Space":
-                ev.target.checked = !ev.target.checked;
-                ev.preventDefault();
-                break;
-        }
-    }
-
-    function setEvents() {
-        onEachLazy(document.getElementsByClassName("slider"), function(elem) {
-            var toggle = elem.previousElementSibling;
-            var settingId = toggle.id;
-            var settingValue = getSettingValue(settingId);
-            if (settingValue !== null) {
-                toggle.checked = settingValue === "true";
-            }
-            toggle.onchange = function() {
-                changeSetting(this.id, this.checked);
-            };
-            toggle.onkeyup = handleKey;
-            toggle.onkeyrelease = handleKey;
-        });
-        onEachLazy(document.getElementsByClassName("select-wrapper"), function(elem) {
-            var select = elem.getElementsByTagName("select")[0];
-            var settingId = select.id;
-            var settingValue = getSettingValue(settingId);
-            if (settingValue !== null) {
-                select.value = settingValue;
-            }
-            select.onchange = function() {
-                changeSetting(this.id, this.value);
-            };
-        });
-    }
-
-    window.addEventListener("DOMContentLoaded", setEvents);
-})();
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
deleted file mode 100644 (file)
index 4d9a59f..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-// From rust:
-/* global search, sourcesIndex */
-
-// Local js definitions:
-/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, searchState */
-/* global updateLocalStorage */
-(function() {
-
-function getCurrentFilePath() {
-    var parts = window.location.pathname.split("/");
-    var rootPathParts = window.rootPath.split("/");
-
-    for (var i = 0, len = rootPathParts.length; i < len; ++i) {
-        if (rootPathParts[i] === "..") {
-            parts.pop();
-        }
-    }
-    var file = window.location.pathname.substring(parts.join("/").length);
-    if (file.startsWith("/")) {
-        file = file.substring(1);
-    }
-    return file.substring(0, file.length - 5);
-}
-
-function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
-    var name = document.createElement("div");
-    name.className = "name";
-
-    fullPath += elem["name"] + "/";
-
-    name.onclick = function() {
-        if (hasClass(this, "expand")) {
-            removeClass(this, "expand");
-        } else {
-            addClass(this, "expand");
-        }
-    };
-    name.innerText = elem["name"];
-
-    var i, len;
-
-    var children = document.createElement("div");
-    children.className = "children";
-    var folders = document.createElement("div");
-    folders.className = "folders";
-    if (elem.dirs) {
-        for (i = 0, len = elem.dirs.length; i < len; ++i) {
-            if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
-                               hasFoundFile)) {
-                addClass(name, "expand");
-                hasFoundFile = true;
-            }
-        }
-    }
-    children.appendChild(folders);
-
-    var files = document.createElement("div");
-    files.className = "files";
-    if (elem.files) {
-        for (i = 0, len = elem.files.length; i < len; ++i) {
-            var file = document.createElement("a");
-            file.innerText = elem.files[i];
-            file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
-            if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
-                file.className = "selected";
-                addClass(name, "expand");
-                hasFoundFile = true;
-            }
-            files.appendChild(file);
-        }
-    }
-    search.fullPath = fullPath;
-    children.appendChild(files);
-    parent.appendChild(name);
-    parent.appendChild(children);
-    return hasFoundFile && currentFile.startsWith(fullPath);
-}
-
-function toggleSidebar() {
-    var sidebar = document.getElementById("source-sidebar");
-    var child = this.children[0].children[0];
-    if (child.innerText === ">") {
-        sidebar.style.left = "";
-        this.style.left = "";
-        child.innerText = "<";
-        updateLocalStorage("rustdoc-source-sidebar-show", "true");
-    } else {
-        sidebar.style.left = "-300px";
-        this.style.left = "0";
-        child.innerText = ">";
-        updateLocalStorage("rustdoc-source-sidebar-show", "false");
-    }
-}
-
-function createSidebarToggle() {
-    var sidebarToggle = document.createElement("div");
-    sidebarToggle.id = "sidebar-toggle";
-    sidebarToggle.onclick = toggleSidebar;
-
-    var inner1 = document.createElement("div");
-    inner1.style.position = "relative";
-
-    var inner2 = document.createElement("div");
-    inner2.style.paddingTop = "3px";
-    if (getCurrentValue("rustdoc-source-sidebar-show") === "true") {
-        inner2.innerText = "<";
-    } else {
-        inner2.innerText = ">";
-        sidebarToggle.style.left = "0";
-    }
-
-    inner1.appendChild(inner2);
-    sidebarToggle.appendChild(inner1);
-    return sidebarToggle;
-}
-
-// This function is called from "source-files.js", generated in `html/render/mod.rs`.
-// eslint-disable-next-line no-unused-vars
-function createSourceSidebar() {
-    if (!window.rootPath.endsWith("/")) {
-        window.rootPath += "/";
-    }
-    var main = document.getElementById("main");
-
-    var sidebarToggle = createSidebarToggle();
-    main.insertBefore(sidebarToggle, main.firstChild);
-
-    var sidebar = document.createElement("div");
-    sidebar.id = "source-sidebar";
-    if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") {
-        sidebar.style.left = "-300px";
-    }
-
-    var currentFile = getCurrentFilePath();
-    var hasFoundFile = false;
-
-    var title = document.createElement("div");
-    title.className = "title";
-    title.innerText = "Files";
-    sidebar.appendChild(title);
-    Object.keys(sourcesIndex).forEach(function(key) {
-        sourcesIndex[key].name = key;
-        hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
-                                      currentFile, hasFoundFile);
-    });
-
-    main.insertBefore(sidebar, main.firstChild);
-    // Focus on the current file in the source files sidebar.
-    var selected_elem = sidebar.getElementsByClassName("selected")[0];
-    if (typeof selected_elem !== "undefined") {
-        selected_elem.focus();
-    }
-}
-
-var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
-
-function highlightSourceLines(scrollTo, match) {
-    if (typeof match === "undefined") {
-        match = window.location.hash.match(lineNumbersRegex);
-    }
-    if (!match) {
-        return;
-    }
-    var from = parseInt(match[1], 10);
-    var to = from;
-    if (typeof match[2] !== "undefined") {
-        to = parseInt(match[2], 10);
-    }
-    if (to < from) {
-        var tmp = to;
-        to = from;
-        from = tmp;
-    }
-    var elem = document.getElementById(from);
-    if (!elem) {
-        return;
-    }
-    if (scrollTo) {
-        var x = document.getElementById(from);
-        if (x) {
-            x.scrollIntoView();
-        }
-    }
-    onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
-        onEachLazy(e.getElementsByTagName("span"), function(i_e) {
-            removeClass(i_e, "line-highlighted");
-        });
-    });
-    for (var i = from; i <= to; ++i) {
-        elem = document.getElementById(i);
-        if (!elem) {
-            break;
-        }
-        addClass(elem, "line-highlighted");
-    }
-}
-
-var handleSourceHighlight = (function() {
-    var prev_line_id = 0;
-
-    var set_fragment = function(name) {
-        var x = window.scrollX,
-            y = window.scrollY;
-        if (searchState.browserSupportsHistoryApi()) {
-            history.replaceState(null, null, "#" + name);
-            highlightSourceLines(true);
-        } else {
-            location.replace("#" + name);
-        }
-        // Prevent jumps when selecting one or many lines
-        window.scrollTo(x, y);
-    };
-
-    return function(ev) {
-        var cur_line_id = parseInt(ev.target.id, 10);
-        ev.preventDefault();
-
-        if (ev.shiftKey && prev_line_id) {
-            // Swap selection if needed
-            if (prev_line_id > cur_line_id) {
-                var tmp = prev_line_id;
-                prev_line_id = cur_line_id;
-                cur_line_id = tmp;
-            }
-
-            set_fragment(prev_line_id + "-" + cur_line_id);
-        } else {
-            prev_line_id = cur_line_id;
-
-            set_fragment(cur_line_id);
-        }
-    };
-}());
-
-window.addEventListener("hashchange", function() {
-    var match = window.location.hash.match(lineNumbersRegex);
-    if (match) {
-        return highlightSourceLines(false, match);
-    }
-});
-
-onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
-    el.addEventListener("click", handleSourceHighlight);
-});
-
-highlightSourceLines(true);
-
-window.createSourceSidebar = createSourceSidebar;
-})();
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
deleted file mode 100644 (file)
index 2eaa81a..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-// From rust:
-/* global resourcesSuffix */
-var darkThemes = ["dark", "ayu"];
-window.currentTheme = document.getElementById("themeStyle");
-window.mainTheme = document.getElementById("mainThemeStyle");
-
-var settingsDataset = (function () {
-    var settingsElement = document.getElementById("default-settings");
-    if (settingsElement === null) {
-        return null;
-    }
-    var dataset = settingsElement.dataset;
-    if (dataset === undefined) {
-        return null;
-    }
-    return dataset;
-})();
-
-function getSettingValue(settingName) {
-    var current = getCurrentValue('rustdoc-' + settingName);
-    if (current !== null) {
-        return current;
-    }
-    if (settingsDataset !== null) {
-        var def = settingsDataset[settingName.replace(/-/g,'_')];
-        if (def !== undefined) {
-            return def;
-        }
-    }
-    return null;
-}
-
-var localStoredTheme = getSettingValue("theme");
-
-var savedHref = [];
-
-// eslint-disable-next-line no-unused-vars
-function hasClass(elem, className) {
-    return elem && elem.classList && elem.classList.contains(className);
-}
-
-// eslint-disable-next-line no-unused-vars
-function addClass(elem, className) {
-    if (!elem || !elem.classList) {
-        return;
-    }
-    elem.classList.add(className);
-}
-
-// eslint-disable-next-line no-unused-vars
-function removeClass(elem, className) {
-    if (!elem || !elem.classList) {
-        return;
-    }
-    elem.classList.remove(className);
-}
-
-function onEach(arr, func, reversed) {
-    if (arr && arr.length > 0 && func) {
-        var length = arr.length;
-        var i;
-        if (reversed) {
-            for (i = length - 1; i >= 0; --i) {
-                if (func(arr[i])) {
-                    return true;
-                }
-            }
-        } else {
-            for (i = 0; i < length; ++i) {
-                if (func(arr[i])) {
-                    return true;
-                }
-            }
-        }
-    }
-    return false;
-}
-
-function onEachLazy(lazyArray, func, reversed) {
-    return onEach(
-        Array.prototype.slice.call(lazyArray),
-        func,
-        reversed);
-}
-
-// eslint-disable-next-line no-unused-vars
-function hasOwnPropertyRustdoc(obj, property) {
-    return Object.prototype.hasOwnProperty.call(obj, property);
-}
-
-function updateLocalStorage(name, value) {
-    try {
-        window.localStorage.setItem(name, value);
-    } catch(e) {
-        // localStorage is not accessible, do nothing
-    }
-}
-
-function getCurrentValue(name) {
-    try {
-        return window.localStorage.getItem(name);
-    } catch(e) {
-        return null;
-    }
-}
-
-function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
-    var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
-    var fullNewTheme = newTheme + resourcesSuffix + ".css";
-    var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
-
-    // If this new value comes from a system setting or from the previously
-    // saved theme, no need to save it.
-    if (saveTheme) {
-        updateLocalStorage("rustdoc-theme", newTheme);
-    }
-
-    if (styleElem.href === newHref) {
-        return;
-    }
-
-    var found = false;
-    if (savedHref.length === 0) {
-        onEachLazy(document.getElementsByTagName("link"), function(el) {
-            savedHref.push(el.href);
-        });
-    }
-    onEach(savedHref, function(el) {
-        if (el === newHref) {
-            found = true;
-            return true;
-        }
-    });
-    if (found) {
-        styleElem.href = newHref;
-    }
-}
-
-// This function is called from "main.js".
-// eslint-disable-next-line no-unused-vars
-function useSystemTheme(value) {
-    if (value === undefined) {
-        value = true;
-    }
-
-    updateLocalStorage("rustdoc-use-system-theme", value);
-
-    // update the toggle if we're on the settings page
-    var toggle = document.getElementById("use-system-theme");
-    if (toggle && toggle instanceof HTMLInputElement) {
-        toggle.checked = value;
-    }
-}
-
-var updateSystemTheme = (function() {
-    if (!window.matchMedia) {
-        // fallback to the CSS computed value
-        return function() {
-            var cssTheme = getComputedStyle(document.documentElement)
-                .getPropertyValue('content');
-
-            switchTheme(
-                window.currentTheme,
-                window.mainTheme,
-                JSON.parse(cssTheme) || "light",
-                true
-            );
-        };
-    }
-
-    // only listen to (prefers-color-scheme: dark) because light is the default
-    var mql = window.matchMedia("(prefers-color-scheme: dark)");
-
-    function handlePreferenceChange(mql) {
-        // maybe the user has disabled the setting in the meantime!
-        if (getSettingValue("use-system-theme") !== "false") {
-            var lightTheme = getSettingValue("preferred-light-theme") || "light";
-            var darkTheme = getSettingValue("preferred-dark-theme") || "dark";
-
-            if (mql.matches) {
-                // prefers a dark theme
-                switchTheme(window.currentTheme, window.mainTheme, darkTheme, true);
-            } else {
-                // prefers a light theme, or has no preference
-                switchTheme(window.currentTheme, window.mainTheme, lightTheme, true);
-            }
-
-            // note: we save the theme so that it doesn't suddenly change when
-            // the user disables "use-system-theme" and reloads the page or
-            // navigates to another page
-        }
-    }
-
-    mql.addListener(handlePreferenceChange);
-
-    return function() {
-        handlePreferenceChange(mql);
-    };
-})();
-
-if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
-    // update the preferred dark theme if the user is already using a dark theme
-    // See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
-    if (getSettingValue("use-system-theme") === null
-        && getSettingValue("preferred-dark-theme") === null
-        && darkThemes.indexOf(localStoredTheme) >= 0) {
-        updateLocalStorage("rustdoc-preferred-dark-theme", localStoredTheme);
-    }
-
-    // call the function to initialize the theme at least once!
-    updateSystemTheme();
-} else {
-    switchTheme(
-        window.currentTheme,
-        window.mainTheme,
-        getSettingValue("theme") || "light",
-        false
-    );
-}
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
deleted file mode 100644 (file)
index 171d06c..0000000
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
-Based off of the Ayu theme
-Original by Dempfi (https://github.com/dempfi/ayu)
-*/
-
-/* General structure and fonts */
-
-body {
-       background-color: #0f1419;
-       color: #c5c5c5;
-}
-
-h1, h2, h3, h4 {
-       color: white;
-}
-h1.fqn {
-       border-bottom-color: #5c6773;
-}
-h1.fqn  a {
-       color: #fff;
-}
-h2, h3, h4 {
-       border-bottom-color: #5c6773;
-}
-h4 {
-       border: none;
-}
-
-.in-band {
-       background-color: #0f1419;
-}
-
-.invisible {
-       background: rgba(0, 0, 0, 0);
-}
-
-code {
-       color: #ffb454;
-}
-h3 > code, h4 > code, h5 > code {
-       color: #e6e1cf;
-}
-pre > code {
-       color: #e6e1cf;
-}
-span code {
-       color: #e6e1cf;
-}
-.docblock a > code {
-       color: #39AFD7 !important;
-}
-.docblock code, .docblock-short code {
-       background-color: #191f26;
-}
-pre, .rustdoc.source .example-wrap {
-       color: #e6e1cf;
-       background-color: #191f26;
-}
-
-.sidebar {
-       background-color: #14191f;
-}
-
-.logo-container.rust-logo > img {
-       filter: drop-shadow(1px 0 0px #fff)
-               drop-shadow(0 1px 0 #fff)
-               drop-shadow(-1px 0 0 #fff)
-               drop-shadow(0 -1px 0 #fff);
-}
-
-/* Improve the scrollbar display on firefox */
-* {
-       scrollbar-color: #5c6773 transparent;
-}
-
-.sidebar {
-       scrollbar-color: #5c6773 transparent;
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar-track {
-       background-color: transparent;
-}
-::-webkit-scrollbar-thumb {
-       background-color: #5c6773;
-}
-.sidebar::-webkit-scrollbar-track {
-       background-color: transparent;
-}
-.sidebar::-webkit-scrollbar-thumb {
-       background-color: #5c6773;
-}
-
-.sidebar .current {
-       background-color: transparent;
-       color: #ffb44c;
-}
-
-.source .sidebar {
-       background-color: #0f1419;
-}
-
-.sidebar .location {
-       border-color: #000;
-       background-color: #0f1419;
-       color: #fff;
-}
-
-.sidebar-elems .location {
-       color: #ff7733;
-}
-
-.sidebar-elems .location a {
-       color: #fff;
-}
-
-.sidebar .version {
-       border-bottom-color: #424c57;
-}
-
-.sidebar-title {
-       border-top-color: #5c6773;
-       border-bottom-color: #5c6773;
-}
-
-.block a:hover {
-       background: transparent;
-       color: #ffb44c;
-}
-
-.line-numbers span { color: #5c6773; }
-.line-numbers .line-highlighted {
-       color: #708090;
-       background-color: rgba(255, 236, 164, 0.06);
-       padding-right: 4px;
-       border-right: 1px solid #ffb44c;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
-       border-bottom-color: #5c6773;
-}
-
-.docblock table, .docblock table td, .docblock table th {
-       border-color: #5c6773;
-}
-
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
-       color: #c5c5c5;
-}
-
-.search-results a:hover {
-       background-color: #777;
-}
-
-.search-results a:focus {
-       color: #000 !important;
-       background-color: #c6afb3;
-}
-.search-results a {
-       color: #0096cf;
-}
-.search-results a span.desc {
-       color: #c5c5c5;
-}
-
-.content .item-info::before { color: #ccc; }
-
-.content span.foreigntype, .content a.foreigntype { color: #ef57ff; }
-.content span.union, .content a.union { color: #98a01c; }
-.content span.constant, .content a.constant,
-.content span.static, .content a.static { color: #6380a0; }
-.content span.primitive, .content a.primitive { color: #32889b; }
-.content span.traitalias, .content a.traitalias { color: #57d399; }
-.content span.keyword, .content a.keyword { color: #de5249; }
-
-.content span.externcrate, .content span.mod, .content a.mod {
-       color: #acccf9;
-}
-.content span.struct, .content a.struct {
-       color: #ffa0a5;
-}
-.content span.enum, .content a.enum {
-       color: #99e0c9;
-}
-.content span.trait, .content a.trait {
-       color: #39AFD7;
-}
-.content span.type, .content a.type {
-       color: #cfbcf5;
-}
-.content span.fn, .content a.fn, .content span.method,
-.content a.method, .content span.tymethod,
-.content a.tymethod, .content .fnname {
-       color: #fdd687;
-}
-.content span.attr, .content a.attr, .content span.derive,
-.content a.derive, .content span.macro, .content a.macro {
-       color: #a37acc;
-}
-
-pre.rust .comment { color: #788797; }
-pre.rust .doccomment { color: #a1ac88; }
-
-nav:not(.sidebar) {
-       border-bottom-color: #424c57;
-}
-nav.main .current {
-       border-top-color: #5c6773;
-       border-bottom-color: #5c6773;
-}
-nav.main .separator {
-       border: 1px solid #5c6773;
-}
-a {
-       color: #c5c5c5;
-}
-
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
-.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
-#help a {
-       color: #39AFD7;
-}
-
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before {
-       color: #999;
-}
-
-#crate-search {
-       color: #c5c5c5;
-       background-color: #141920;
-       box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
-       border-color: #424c57;
-}
-
-.search-input {
-       color: #ffffff;
-       background-color: #141920;
-       box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
-       transition: box-shadow 150ms ease-in-out;
-}
-
-#crate-search+.search-input:focus {
-       box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
-}
-
-.search-input:disabled {
-       background-color: #3e3e3e;
-}
-
-.module-item .stab,
-.import-item .stab {
-       color: #000;
-}
-
-.stab.unstable,
-.stab.deprecated,
-.stab.portability {
-       color: #c5c5c5;
-       background: #314559 !important;
-       border-style: none !important;
-       border-radius: 4px;
-       padding: 3px 6px 3px 6px;
-}
-
-.stab.portability > code {
-       color: #e6e1cf;
-       background: none;
-}
-
-#help > div {
-       background: #14191f;
-       box-shadow: 0px 6px 20px 0px black;
-       border: none;
-       border-radius: 4px;
-}
-
-#help > div > span {
-       border-bottom-color: #5c6773;
-}
-
-.since {
-       color: grey;
-}
-
-tr.result span.primitive::after, tr.result span.keyword::after {
-       color: #788797;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .number, pre.rust .string { color: #b8cc52; }
-pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty,
-pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .op, pre.rust .lifetime { color: #ff7733; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; }
-pre.rust .question-mark {
-       color: #ff9011;
-}
-pre.rust .self {
-       color: #36a3d9;
-       font-style: italic;
-}
-pre.rust .attribute {
-       color: #e6e1cf;
-}
-pre.rust .attribute .ident, pre.rust .attribute .op {
-       color: #e6e1cf;
-}
-
-.example-wrap > pre.line-number {
-       color: #5c67736e;
-       border: none;
-}
-
-a.test-arrow {
-       font-size: 100%;
-       color: #788797;
-       border-radius: 4px;
-       background-color: rgba(57, 175, 215, 0.09);
-}
-
-a.test-arrow:hover {
-       background-color: rgba(57, 175, 215, 0.368);
-       color: #c5c5c5;
-}
-
-.toggle-label,
-.code-attribute {
-       color: #999;
-}
-
-:target, :target * {
-       background: rgba(255, 236, 164, 0.06);
-}
-
-:target {
-       border-right: 3px solid rgba(255, 180, 76, 0.85);
-}
-
-pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.4);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
-       border-left: 2px solid #f00;
-}
-
-pre.should_panic {
-       border-left: 2px solid rgba(255,0,0,.4);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
-       border-left: 2px solid #f00;
-}
-
-pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
-       border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .compile_fail:hover {
-       color: #f00;
-}
-
-.tooltip.should_panic {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .should_panic:hover {
-       color: #f00;
-}
-
-.tooltip.ignore {
-       color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
-       color: #ff9200;
-}
-
-.search-failed a {
-       color: #39AFD7;
-}
-
-.tooltip::after {
-       background-color: #314559;
-       color: #c5c5c5;
-       border: 1px solid #5c6773;
-}
-
-.tooltip::before {
-       border-color: transparent #314559 transparent transparent;
-}
-
-.notable-traits-tooltiptext {
-       background-color: #314559;
-       border-color: #5c6773;
-}
-
-.notable-traits-tooltiptext .notable {
-       border-bottom-color: #5c6773;
-}
-
-#titles > button.selected {
-       background-color: #141920 !important;
-       border-bottom: 1px solid #ffb44c !important;
-       border-top: none;
-}
-
-#titles > button:not(.selected) {
-       background-color: transparent !important;
-       border: none;
-}
-
-#titles > button:hover {
-       border-bottom: 1px solid rgba(242, 151, 24, 0.3);
-}
-
-#titles > button > div.count {
-       color: #888;
-}
-
-/* rules that this theme does not need to set, here to satisfy the rule checker */
-/* note that a lot of these are partially set in some way (meaning they are set
-individually rather than as a group) */
-/* FIXME: these rules should be at the bottom of the file but currently must be
-above the `@media (max-width: 700px)` rules due to a bug in the css checker */
-/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-.search-input:focus {}
-.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
-.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
-.content span.struct,.content a.struct,.block a.current.struct {}
-#titles>button:hover,#titles>button.selected {}
-.content span.type,.content a.type,.block a.current.type {}
-.content span.union,.content a.union,.block a.current.union {}
-pre.rust .lifetime {}
-.stab.unstable {}
-h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod) {}
-.content span.enum,.content a.enum,.block a.current.enum {}
-.content span.constant,.content a.constant,.block a.current.constant,.content span.static,
-.content a.static, .block a.current.static {}
-.content span.keyword,.content a.keyword,.block a.current.keyword {}
-pre.rust .comment {}
-.content span.traitalias,.content a.traitalias,.block a.current.traitalias {}
-.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,
-.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,
-.content .fnname {}
-pre.rust .kw {}
-pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,
-pre.rust .attribute .ident {}
-.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype {}
-pre.rust .doccomment {}
-.stab.deprecated {}
-.content a.attr,.content a.derive,.content a.macro {}
-.stab.portability {}
-.content span.primitive,.content a.primitive,.block a.current.primitive {}
-.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod {}
-pre.rust .kw-2,pre.rust .prelude-ty {}
-.content span.trait,.content a.trait,.block a.current.trait {}
-
-.search-results a:focus span {}
-a.result-trait:focus {}
-a.result-traitalias:focus {}
-a.result-mod:focus,
-a.result-externcrate:focus {}
-a.result-mod:focus {}
-a.result-externcrate:focus {}
-a.result-enum:focus {}
-a.result-struct:focus {}
-a.result-union:focus {}
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus {}
-a.result-type:focus {}
-a.result-foreigntype:focus {}
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus {}
-a.result-constant:focus,
-a.result-static:focus {}
-a.result-primitive:focus {}
-a.result-keyword:focus {}
-
-@media (max-width: 700px) {
-       .sidebar-menu {
-               background-color: #14191f;
-               border-bottom-color: #5c6773;
-               border-right-color: #5c6773;
-       }
-
-       .sidebar-elems {
-               background-color: #14191f;
-               border-right-color: #5c6773;
-       }
-
-       #sidebar-filler {
-               background-color: #14191f;
-               border-bottom-color: #5c6773;
-       }
-}
-
-kbd {
-       color: #c5c5c5;
-       background-color: #314559;
-       border-color: #5c6773;
-       border-bottom-color: #5c6773;
-       box-shadow-color: #c6cbd1;
-}
-
-#theme-picker, #settings-menu, #help-button {
-       border-color: #5c6773;
-       background-color: #0f1419;
-       color: #fff;
-}
-
-#theme-picker > img, #settings-menu > img {
-       filter: invert(100);
-}
-
-#copy-path {
-       color: #fff;
-}
-#copy-path > img {
-       filter: invert(70%);
-}
-#copy-path:hover > img {
-       filter: invert(100%);
-}
-
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
-#help-button:hover, #help-button:focus {
-       border-color: #e0e0e0;
-}
-
-#theme-choices {
-       border-color: #5c6773;
-       background-color: #0f1419;
-}
-
-#theme-choices > button:not(:first-child) {
-       border-top-color: #5c6773;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
-       background-color: rgba(110, 110, 110, 0.33);
-}
-
-@media (max-width: 700px) {
-       #theme-picker {
-               background: #0f1419;
-       }
-}
-
-#all-types {
-       background-color: #14191f;
-}
-#all-types:hover {
-       background-color: rgba(70, 70, 70, 0.33);
-}
-
-.search-results .result-name span.alias {
-       color: #c5c5c5;
-}
-.search-results .result-name span.grey {
-       color: #999;
-}
-
-#sidebar-toggle {
-       background-color: #14191f;
-}
-#sidebar-toggle:hover {
-       background-color: rgba(70, 70, 70, 0.33);
-}
-#source-sidebar {
-       background-color: #14191f;
-}
-#source-sidebar > .title {
-       color: #fff;
-       border-bottom-color: #5c6773;
-}
-div.files > a:hover, div.name:hover {
-       background-color: #14191f;
-       color: #ffb44c;
-}
-div.files > .selected {
-       background-color: #14191f;
-       color: #ffb44c;
-}
-.setting-line > .title {
-       border-bottom-color: #5c6773;
-}
-input:checked + .slider {
-       background-color: #ffb454 !important;
-}
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
deleted file mode 100644 (file)
index d9ea280..0000000
+++ /dev/null
@@ -1,479 +0,0 @@
-body {
-       background-color: #353535;
-       color: #ddd;
-}
-
-h1, h2, h3, h4 {
-       color: #ddd;
-}
-h1.fqn {
-       border-bottom-color: #d2d2d2;
-}
-h2, h3, h4 {
-       border-bottom-color: #d2d2d2;
-}
-
-.in-band {
-       background-color: #353535;
-}
-
-.invisible {
-       background: rgba(0, 0, 0, 0);
-}
-
-.docblock code, .docblock-short code {
-       background-color: #2A2A2A;
-}
-pre, .rustdoc.source .example-wrap {
-       background-color: #2A2A2A;
-}
-
-.sidebar {
-       background-color: #505050;
-}
-
-.logo-container.rust-logo > img {
-       filter: drop-shadow(1px 0 0px #fff)
-               drop-shadow(0 1px 0 #fff)
-               drop-shadow(-1px 0 0 #fff)
-               drop-shadow(0 -1px 0 #fff)
-}
-
-/* Improve the scrollbar display on firefox */
-* {
-       scrollbar-color: rgb(64, 65, 67) #717171;
-}
-.sidebar {
-       scrollbar-color: rgba(32,34,37,.6) transparent;
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar-track {
-       background-color: #717171;
-}
-::-webkit-scrollbar-thumb {
-       background-color: rgba(32, 34, 37, .6);
-}
-.sidebar::-webkit-scrollbar-track {
-       background-color: #717171;
-}
-.sidebar::-webkit-scrollbar-thumb {
-       background-color: rgba(32, 34, 37, .6);
-}
-
-.sidebar .current {
-       background-color: #333;
-}
-
-.source .sidebar {
-       background-color: #353535;
-}
-
-.sidebar .location {
-       border-color: #fff;
-       background: #575757;
-       color: #DDD;
-}
-
-.sidebar .version {
-       border-bottom-color: #DDD;
-}
-
-.sidebar-title {
-       border-top-color: #777;
-       border-bottom-color: #777;
-}
-
-.block a:hover {
-       background: #444;
-}
-
-.line-numbers span { color: #3B91E2; }
-.line-numbers .line-highlighted {
-       background-color: #0a042f !important;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
-       border-bottom-color: #DDD;
-}
-
-.docblock table, .docblock table td, .docblock table th {
-       border-color: #ddd;
-}
-
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
-       color: #ddd;
-}
-
-.search-results a:hover {
-       background-color: #777;
-}
-
-.search-results a:focus {
-       color: #eee !important;
-       background-color: #616161;
-}
-.search-results a:focus span { color: #eee !important; }
-a.result-trait:focus { background-color: #013191; }
-a.result-traitalias:focus { background-color: #013191; }
-a.result-mod:focus,
-a.result-externcrate:focus { background-color: #afc6e4; }
-a.result-mod:focus { background-color: #803a1b; }
-a.result-externcrate:focus { background-color: #396bac; }
-a.result-enum:focus { background-color: #5b4e68; }
-a.result-struct:focus { background-color: #194e9f; }
-a.result-union:focus { background-color: #b7bd49; }
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus { background-color: #4950ed; }
-a.result-type:focus { background-color: #38902c; }
-a.result-foreigntype:focus { background-color: #b200d6; }
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus { background-color: #217d1c; }
-a.result-constant:focus,
-a.result-static:focus { background-color: #0063cc; }
-a.result-primitive:focus { background-color: #00708a; }
-a.result-keyword:focus { background-color: #884719; }
-
-.content .item-info::before { color: #ccc; }
-
-.content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
-.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
-.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
-.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
-.content span.attr, .content a.attr, .block a.current.attr,
-.content span.derive, .content a.derive, .block a.current.derive,
-.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
-.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
-.content span.constant, .content a.constant, .block a.current.constant,
-.content span.static, .content a.static, .block a.current.static { color: #82a5c9; }
-.content span.primitive, .content a.primitive, .block a.current.primitive { color: #43aec7; }
-.content span.externcrate,
-.content span.mod, .content a.mod, .block a.current.mod { color: #bda000; }
-.content span.trait, .content a.trait, .block a.current.trait { color: #b78cf2; }
-.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #b397da; }
-.content span.fn, .content a.fn, .block a.current.fn,
-.content span.method, .content a.method, .block a.current.method,
-.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
-.content .fnname{ color: #2BAB63; }
-.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
-
-pre.rust .comment { color: #8d8d8b; }
-pre.rust .doccomment { color: #8ca375; }
-
-nav:not(.sidebar) {
-       border-bottom-color: #4e4e4e;
-}
-nav.main .current {
-       border-top-color: #eee;
-       border-bottom-color: #eee;
-}
-nav.main .separator {
-       border-color: #eee;
-}
-a {
-       color: #ddd;
-}
-
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
-.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
-#help a {
-       color: #D2991D;
-}
-
-a.test-arrow {
-       color: #dedede;
-}
-
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before {
-       color: #999;
-}
-
-#crate-search {
-       color: #111;
-       background-color: #f0f0f0;
-       border-color: #000;
-       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
-}
-
-.search-input {
-       color: #111;
-       background-color: #f0f0f0;
-       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
-}
-
-.search-input:focus {
-       border-color: #008dfd;
-}
-
-.search-input:disabled {
-       background-color: #c5c4c4;
-}
-
-#crate-search + .search-input:focus {
-       box-shadow: 0 0 8px 4px #078dd8;
-}
-
-.module-item .stab,
-.import-item .stab {
-       color: #ddd;
-}
-
-.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
-.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
-.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
-.stab.portability > code { background: none; }
-
-#help > div {
-       background: #4d4d4d;
-       border-color: #bfbfbf;
-}
-
-#help > div > span {
-       border-bottom-color: #bfbfbf;
-}
-
-#help dt {
-       border-color: #bfbfbf;
-       background: rgba(0,0,0,0);
-}
-
-.since {
-       color: grey;
-}
-
-tr.result span.primitive::after, tr.result span.keyword::after {
-       color: #ddd;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #ab8ac1; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; }
-pre.rust .number, pre.rust .string { color: #83a300; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute, pre.rust .attribute .ident { color: #ee6868; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #d97f26; }
-pre.rust .question-mark {
-       color: #ff9011;
-}
-
-.example-wrap > pre.line-number {
-       border-color: #4a4949;
-}
-
-a.test-arrow {
-       background-color: rgba(78, 139, 202, 0.2);
-}
-
-a.test-arrow:hover{
-       background-color: #4e8bca;
-}
-
-.toggle-label,
-.code-attribute {
-       color: #999;
-}
-
-:target, :target * {
-       background-color: #494a3d;
-}
-
-:target {
-       border-right: 3px solid #bb7410;
-}
-
-pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.8);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
-       border-left: 2px solid #f00;
-}
-
-pre.should_panic {
-       border-left: 2px solid rgba(255,0,0,.8);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
-       border-left: 2px solid #f00;
-}
-
-pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
-       border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
-       color: rgba(255,0,0,.8);
-}
-
-.information > .compile_fail:hover {
-       color: #f00;
-}
-
-.tooltip.should_panic {
-       color: rgba(255,0,0,.8);
-}
-
-.information > .should_panic:hover {
-       color: #f00;
-}
-
-.tooltip.ignore {
-       color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
-       color: #ff9200;
-}
-
-.search-failed a {
-       color: #0089ff;
-}
-
-.tooltip::after {
-       background-color: #000;
-       color: #fff;
-       border-color: #000;
-}
-
-.tooltip::before {
-       border-color: transparent black transparent transparent;
-}
-
-.notable-traits-tooltiptext {
-       background-color: #111;
-       border-color: #777;
-}
-
-.notable-traits-tooltiptext .notable {
-       border-bottom-color: #d2d2d2;
-}
-
-#titles > button:not(.selected) {
-       background-color: #252525;
-       border-top-color: #252525;
-}
-
-#titles > button:hover, #titles > button.selected {
-       border-top-color: #0089ff;
-       background-color: #353535;
-}
-
-#titles > button > div.count {
-       color: #888;
-}
-
-@media (max-width: 700px) {
-       .sidebar-menu {
-               background-color: #505050;
-               border-bottom-color: #e0e0e0;
-               border-right-color: #e0e0e0;
-       }
-
-       .sidebar-elems {
-               background-color: #505050;
-               border-right-color: #000;
-       }
-
-       #sidebar-filler {
-               background-color: #505050;
-               border-bottom-color: #e0e0e0;
-       }
-}
-
-kbd {
-       color: #000;
-       background-color: #fafbfc;
-       border-color: #d1d5da;
-       border-bottom-color: #c6cbd1;
-       box-shadow-color: #c6cbd1;
-}
-
-#theme-picker, #settings-menu, #help-button {
-       border-color: #e0e0e0;
-       background: #f0f0f0;
-       color: #000;
-}
-
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
-#help-button:hover, #help-button:focus {
-       border-color: #ffb900;
-}
-
-#copy-path {
-       color: #999;
-}
-#copy-path > img {
-       filter: invert(50%);
-}
-#copy-path:hover > img {
-       filter: invert(65%);
-}
-
-#theme-choices {
-       border-color: #e0e0e0;
-       background-color: #353535;
-}
-
-#theme-choices > button:not(:first-child) {
-       border-top-color: #e0e0e0;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
-       background-color: #4e4e4e;
-}
-
-@media (max-width: 700px) {
-       #theme-picker {
-               background: #f0f0f0;
-       }
-}
-
-#all-types {
-       background-color: #505050;
-}
-#all-types:hover {
-       background-color: #606060;
-}
-
-.search-results .result-name span.alias {
-       color: #fff;
-}
-.search-results .result-name span.grey {
-       color: #ccc;
-}
-
-#sidebar-toggle {
-       background-color: #565656;
-}
-#sidebar-toggle:hover {
-       background-color: #676767;
-}
-#source-sidebar {
-       background-color: #565656;
-}
-#source-sidebar > .title {
-       border-bottom-color: #ccc;
-}
-div.files > a:hover, div.name:hover {
-       background-color: #444;
-}
-div.files > .selected {
-       background-color: #333;
-}
-.setting-line > .title {
-       border-bottom-color: #ddd;
-}
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
deleted file mode 100644 (file)
index 6785b79..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/* General structure and fonts */
-
-body {
-       background-color: white;
-       color: black;
-}
-
-h1, h2, h3, h4 {
-       color: black;
-}
-h1.fqn {
-       border-bottom-color: #D5D5D5;
-}
-h2, h3, h4 {
-       border-bottom-color: #DDDDDD;
-}
-
-.in-band {
-       background-color: white;
-}
-
-.invisible {
-       background: rgba(0, 0, 0, 0);
-}
-
-.docblock code, .docblock-short code {
-       background-color: #F5F5F5;
-}
-pre, .rustdoc.source .example-wrap {
-       background-color: #F5F5F5;
-}
-
-.sidebar {
-       background-color: #F1F1F1;
-}
-
-/* Improve the scrollbar display on firefox */
-* {
-       scrollbar-color: rgba(36, 37, 39, 0.6) #e6e6e6;
-}
-
-.sidebar {
-       scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9;
-}
-
-.logo-container.rust-logo > img {
-       /* No need for a border in here! */
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar-track {
-       background-color: #ecebeb;
-}
-::-webkit-scrollbar-thumb {
-       background-color: rgba(36, 37, 39, 0.6);
-}
-.sidebar::-webkit-scrollbar-track {
-       background-color: #dcdcdc;
-}
-.sidebar::-webkit-scrollbar-thumb {
-       background-color: rgba(36, 37, 39, 0.6);
-}
-
-.sidebar .current {
-       background-color: #fff;
-}
-
-.source .sidebar {
-       background-color: #fff;
-}
-
-.sidebar .location {
-       border-color: #000;
-       background-color: #fff;
-       color: #333;
-}
-
-.sidebar .version {
-       border-bottom-color: #DDD;
-}
-
-.sidebar-title {
-       border-top-color: #777;
-       border-bottom-color: #777;
-}
-
-.block a:hover {
-       background: #F5F5F5;
-}
-
-.line-numbers span { color: #c67e2d; }
-.line-numbers .line-highlighted {
-       background-color: #f6fdb0 !important;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
-       border-bottom-color: #ddd;
-}
-
-.docblock table, .docblock table td, .docblock table th {
-       border-color: #ddd;
-}
-
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
-       color: #4E4C4C;
-}
-
-.search-results a:hover {
-       background-color: #ddd;
-}
-
-.search-results a:focus {
-       color: #000 !important;
-       background-color: #ccc;
-}
-.search-results a:focus span { color: #000 !important; }
-a.result-trait:focus { background-color: #c7b6ff; }
-a.result-traitalias:focus { background-color: #c7b6ff; }
-a.result-mod:focus,
-a.result-externcrate:focus { background-color: #afc6e4; }
-a.result-enum:focus { background-color: #b4d1b9; }
-a.result-struct:focus { background-color: #e7b1a0; }
-a.result-union:focus { background-color: #b7bd49; }
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus { background-color: #c6afb3; }
-a.result-type:focus { background-color: #ffc891; }
-a.result-foreigntype:focus { background-color: #f5c4ff; }
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus { background-color: #8ce488; }
-a.result-constant:focus,
-a.result-static:focus { background-color: #c3e0ff; }
-a.result-primitive:focus { background-color: #9aecff; }
-a.result-keyword:focus { background-color: #f99650; }
-
-.content .item-info::before { color: #ccc; }
-
-.content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
-.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
-.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
-.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
-.content span.attr, .content a.attr, .block a.current.attr,
-.content span.derive, .content a.derive, .block a.current.derive,
-.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
-.content span.union, .content a.union, .block a.current.union { color: #767b27; }
-.content span.constant, .content a.constant, .block a.current.constant,
-.content span.static, .content a.static, .block a.current.static { color: #546e8a; }
-.content span.primitive, .content a.primitive, .block a.current.primitive { color: #2c8093; }
-.content span.externcrate,
-.content span.mod, .content a.mod, .block a.current.mod { color: #4d76ae; }
-.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
-.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #6841f1; }
-.content span.fn, .content a.fn, .block a.current.fn,
-.content span.method, .content a.method, .block a.current.method,
-.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
-.content .fnname { color: #9a6e31; }
-.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
-
-nav:not(.sidebar) {
-       border-bottom-color: #e0e0e0;
-}
-nav.main .current {
-       border-top-color: #000;
-       border-bottom-color: #000;
-}
-nav.main .separator {
-       border: 1px solid #000;
-}
-a {
-       color: #000;
-}
-
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
-.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
-#help a {
-       color: #3873AD;
-}
-
-a.test-arrow {
-       color: #f5f5f5;
-}
-
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before {
-       color: #999;
-}
-
-#crate-search {
-       color: #555;
-       background-color: white;
-       border-color: #e0e0e0;
-       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
-}
-
-.search-input {
-       color: #555;
-       background-color: white;
-       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
-}
-
-.search-input:focus {
-       border-color: #66afe9;
-}
-
-.search-input:disabled {
-       background-color: #e6e6e6;
-}
-
-#crate-search + .search-input:focus {
-       box-shadow: 0 0 8px #078dd8;
-}
-
-.module-item .stab,
-.import-item .stab {
-       color: #000;
-}
-
-.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
-.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
-.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
-.stab.portability > code { background: none; }
-
-#help > div {
-       background: #e9e9e9;
-       border-color: #bfbfbf;
-}
-
-#help > div > span {
-       border-bottom-color: #bfbfbf;
-}
-
-.since {
-       color: grey;
-}
-
-tr.result span.primitive::after, tr.result span.keyword::after {
-       color: black;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #8959A8; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
-pre.rust .number, pre.rust .string { color: #718C00; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
-pre.rust .comment { color: #8E908C; }
-pre.rust .doccomment { color: #4D4D4C; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #B76514; }
-pre.rust .question-mark {
-       color: #ff9011;
-}
-
-.example-wrap > pre.line-number {
-       border-color: #c7c7c7;
-}
-
-a.test-arrow {
-       background-color: rgba(78, 139, 202, 0.2);
-}
-
-a.test-arrow:hover{
-       background-color: #4e8bca;
-}
-
-.toggle-label,
-.code-attribute {
-       color: #999;
-}
-
-:target, :target * {
-       background: #FDFFD3;
-}
-
-:target {
-       border-right: 3px solid #ffb44c;
-}
-
-pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.5);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
-       border-left: 2px solid #f00;
-}
-
-pre.should_panic {
-       border-left: 2px solid rgba(255,0,0,.5);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
-       border-left: 2px solid #f00;
-}
-
-pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
-       border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .compile_fail:hover {
-       color: #f00;
-}
-
-.tooltip.should_panic {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .should_panic:hover {
-       color: #f00;
-}
-
-.tooltip.ignore {
-       color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
-       color: #ff9200;
-}
-
-.search-failed a {
-       color: #0089ff;
-}
-
-.tooltip::after {
-       background-color: #000;
-       color: #fff;
-}
-
-.tooltip::before {
-       border-color: transparent black transparent transparent;
-}
-
-.notable-traits-tooltiptext {
-       background-color: #eee;
-       border-color: #999;
-}
-
-.notable-traits-tooltiptext .notable {
-       border-bottom-color: #DDDDDD;
-}
-
-#titles > button:not(.selected) {
-       background-color: #e6e6e6;
-       border-top-color: #e6e6e6;
-}
-
-#titles > button:hover, #titles > button.selected {
-       background-color: #ffffff;
-       border-top-color: #0089ff;
-}
-
-#titles > button > div.count {
-       color: #888;
-}
-
-@media (max-width: 700px) {
-       .sidebar-menu {
-               background-color: #F1F1F1;
-               border-bottom-color: #e0e0e0;
-               border-right-color: #e0e0e0;
-       }
-
-       .sidebar-elems {
-               background-color: #F1F1F1;
-               border-right-color: #000;
-       }
-
-       #sidebar-filler {
-               background-color: #F1F1F1;
-               border-bottom-color: #e0e0e0;
-       }
-}
-
-kbd {
-       color: #000;
-       background-color: #fafbfc;
-       border-color: #d1d5da;
-       border-bottom-color: #c6cbd1;
-       box-shadow-color: #c6cbd1;
-}
-
-#theme-picker, #settings-menu, #help-button {
-       border-color: #e0e0e0;
-       background-color: #fff;
-}
-
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
-#help-button:hover, #help-button:focus {
-       border-color: #717171;
-}
-
-#copy-path {
-       color: #999;
-}
-#copy-path > img {
-       filter: invert(50%);
-}
-#copy-path:hover > img {
-       filter: invert(35%);
-}
-
-#theme-choices {
-       border-color: #ccc;
-       background-color: #fff;
-}
-
-#theme-choices > button:not(:first-child) {
-       border-top-color: #e0e0e0;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
-       background-color: #eee;
-}
-
-@media (max-width: 700px) {
-       #theme-picker {
-               background: #fff;
-       }
-}
-
-#all-types {
-       background-color: #fff;
-}
-#all-types:hover {
-       background-color: #f9f9f9;
-}
-
-.search-results .result-name span.alias {
-       color: #000;
-}
-.search-results .result-name span.grey {
-       color: #999;
-}
-
-#sidebar-toggle {
-       background-color: #F1F1F1;
-}
-#sidebar-toggle:hover {
-       background-color: #E0E0E0;
-}
-#source-sidebar {
-       background-color: #F1F1F1;
-}
-#source-sidebar > .title {
-       border-bottom-color: #ccc;
-}
-div.files > a:hover, div.name:hover {
-       background-color: #E0E0E0;
-}
-div.files > .selected {
-       background-color: #fff;
-}
-.setting-line > .title {
-       border-bottom-color: #D5D5D5;
-}
diff --git a/src/librustdoc/html/static/wheel.svg b/src/librustdoc/html/static/wheel.svg
deleted file mode 100644 (file)
index 01da3b2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" version="1.1" viewBox="0 0 27.434 29.5" xml:space="preserve"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
\ No newline at end of file
index 4443c74834d04240729f90ec7530bf33442b0567..2ec7e66234ddd21061e8050b5ed6ca6bda77fc31 100644 (file)
@@ -8,44 +8,44 @@
 //! directly written to a `Write` handle.
 
 /// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
-crate static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css");
+crate static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css");
 
 /// The file contents of `settings.css`, responsible for the items on the settings page.
-crate static SETTINGS_CSS: &str = include_str!("static/settings.css");
+crate static SETTINGS_CSS: &str = include_str!("static/css/settings.css");
 
 /// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
-crate static NOSCRIPT_CSS: &str = include_str!("static/noscript.css");
+crate static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css");
 
 /// The file contents of `normalize.css`, included to even out standard elements between browser
 /// implementations.
-crate static NORMALIZE_CSS: &str = include_str!("static/normalize.css");
+crate static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css");
 
 /// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
 /// including search behavior and docblock folding, among others.
-crate static MAIN_JS: &str = include_str!("static/main.js");
+crate static MAIN_JS: &str = include_str!("static/js/main.js");
 
 /// The file contents of `search.js`, which contains the search behavior.
-crate static SEARCH_JS: &str = include_str!("static/search.js");
+crate static SEARCH_JS: &str = include_str!("static/js/search.js");
 
 /// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
 /// page.
-crate static SETTINGS_JS: &str = include_str!("static/settings.js");
+crate static SETTINGS_JS: &str = include_str!("static/js/settings.js");
 
 /// The file contents of `storage.js`, which contains functionality related to browser Local
 /// Storage, used to store documentation settings.
-crate static STORAGE_JS: &str = include_str!("static/storage.js");
+crate static STORAGE_JS: &str = include_str!("static/js/storage.js");
 
 /// The file contents of `brush.svg`, the icon used for the theme-switch button.
-crate static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg");
+crate static BRUSH_SVG: &[u8] = include_bytes!("static/images/brush.svg");
 
 /// The file contents of `wheel.svg`, the icon used for the settings button.
-crate static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg");
+crate static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg");
 
 /// The file contents of `clipboard.svg`, the icon used for the "copy path" button.
-crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/clipboard.svg");
+crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg");
 
 /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
-crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg");
+crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg");
 
 /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
 /// output.
 crate static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");
 
 /// The contents of `rust-logo.png`, the default icon of the documentation.
-crate static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png");
+crate static RUST_LOGO: &[u8] = include_bytes!("static/images/rust-logo.png");
 /// The default documentation favicons (SVG and PNG fallbacks)
-crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/favicon.svg");
-crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png");
-crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png");
+crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg");
+crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png");
+crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png");
 
 crate static PAGE: &str = include_str!("templates/page.html");
 
 crate mod themes {
     /// The "light" theme, selected by default when no setting is available. Used as the basis for
     /// the `--check-theme` functionality.
-    crate static LIGHT: &str = include_str!("static/themes/light.css");
+    crate static LIGHT: &str = include_str!("static/css/themes/light.css");
 
     /// The "dark" theme.
-    crate static DARK: &str = include_str!("static/themes/dark.css");
+    crate static DARK: &str = include_str!("static/css/themes/dark.css");
 
     /// The "ayu" theme.
-    crate static AYU: &str = include_str!("static/themes/ayu.css");
+    crate static AYU: &str = include_str!("static/css/themes/ayu.css");
 }
 
 /// Files related to the Fira Sans font.
 crate mod fira_sans {
     /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
-    crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");
+    crate static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff");
 
     /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
-    crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2");
+    crate static REGULAR2: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2");
 
     /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
-    crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");
+    crate static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff");
 
     /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
-    crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2");
+    crate static MEDIUM2: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2");
 
     /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
-    crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
+    crate static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt");
 }
 
 /// Files related to the Source Serif 4 font.
 crate mod source_serif_4 {
     /// The file `SourceSerif4-Regular.ttf.woff`, the Regular variant of the Source Serif 4 font.
-    crate static REGULAR: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff");
+    crate static REGULAR: &[u8] = include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff");
 
     /// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in
     /// woff2.
-    crate static REGULAR2: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff2");
+    crate static REGULAR2: &[u8] = include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2");
 
     /// The file `SourceSerif4-Bold.ttf.woff`, the Bold variant of the Source Serif 4 font.
-    crate static BOLD: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff");
+    crate static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff");
 
     /// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in
     /// woff2.
-    crate static BOLD2: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff2");
+    crate static BOLD2: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2");
 
     /// The file `SourceSerif4-It.ttf.woff`, the Italic variant of the Source Serif 4 font.
-    crate static ITALIC: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff");
+    crate static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff");
 
     /// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in
     /// woff2.
-    crate static ITALIC2: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff2");
+    crate static ITALIC2: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2");
 
     /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font.
-    crate static LICENSE: &[u8] = include_bytes!("static/SourceSerif4-LICENSE.md");
+    crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md");
 }
 
 /// Files related to the Source Code Pro font.
 crate mod source_code_pro {
     /// The file `SourceCodePro-Regular.ttf.woff`, the Regular variant of the Source Code Pro font.
-    crate static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff");
+    crate static REGULAR: &[u8] = include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff");
 
     /// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font
     /// in woff2.
-    crate static REGULAR2: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff2");
+    crate static REGULAR2: &[u8] = include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2");
 
     /// The file `SourceCodePro-Semibold.ttf.woff`, the Semibold variant of the Source Code Pro
     /// font.
-    crate static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff");
+    crate static SEMIBOLD: &[u8] = include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff");
 
     /// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro
     /// font in woff2.
-    crate static SEMIBOLD2: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff2");
+    crate static SEMIBOLD2: &[u8] = include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2");
 
     /// The file `SourceCodePro-It.ttf.woff`, the Italic variant of the Source Code Pro font.
-    crate static ITALIC: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff");
+    crate static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff");
 
     /// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in
     /// woff2.
-    crate static ITALIC2: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff2");
+    crate static ITALIC2: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2");
 
     /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
-    crate static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
+    crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt");
 }
 
 crate mod noto_sans_kr {
     /// The file `noto-sans-kr-v13-korean-regular.woff`, the Regular variant of the Noto Sans KR
     /// font.
-    crate static REGULAR: &[u8] = include_bytes!("static/noto-sans-kr-v13-korean-regular.woff");
+    crate static REGULAR: &[u8] =
+        include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular.woff");
 
     /// The file `noto-sans-kr-v13-korean-regular-LICENSE.txt`, the license text of the Noto Sans KR
     /// font.
     crate static LICENSE: &[u8] =
-        include_bytes!("static/noto-sans-kr-v13-korean-regular-LICENSE.txt");
+        include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt");
 }
 
 /// Files related to the sidebar in rustdoc sources.
 crate mod sidebar {
     /// File script to handle sidebar.
-    crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
+    crate static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js");
 }
index b89a266a695e99e752cca3bd0cfa123cd094fdbe..bf8db79416b342d92fb6e1108a7c06b0f456ab5c 100644 (file)
@@ -5,9 +5,10 @@
 #![allow(rustc::default_hash_types)]
 
 use std::convert::From;
+use std::fmt;
 
 use rustc_ast::ast;
-use rustc_hir::def::CtorKind;
+use rustc_hir::{def::CtorKind, def_id::DefId};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_span::Pos;
@@ -15,7 +16,7 @@
 use rustdoc_json_types::*;
 
 use crate::clean::utils::print_const_expr;
-use crate::clean::{self, FakeDefId};
+use crate::clean::{self, ItemId};
 use crate::formats::item_type::ItemType;
 use crate::json::JsonRenderer;
 use std::collections::HashSet;
@@ -30,7 +31,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
             .into_iter()
             .flatten()
             .filter_map(|clean::ItemLink { link, did, .. }| {
-                did.map(|did| (link.clone(), from_def_id(did.into())))
+                did.map(|did| (link.clone(), from_item_id(did.into())))
             })
             .collect();
         let docs = item.attrs.collapsed_doc_value();
@@ -47,7 +48,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
             _ => from_clean_item(item, self.tcx),
         };
         Some(Item {
-            id: from_def_id(def_id),
+            id: from_item_id(def_id),
             crate_id: def_id.krate().as_u32(),
             name: name.map(|sym| sym.to_string()),
             span: self.convert_span(span),
@@ -86,7 +87,7 @@ fn convert_visibility(&self, v: clean::Visibility) -> Visibility {
             Inherited => Visibility::Default,
             Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
             Restricted(did) => Visibility::Restricted {
-                parent: from_def_id(did.into()),
+                parent: from_item_id(did.into()),
                 path: self.tcx.def_path(did).to_string_no_crate_verbose(),
             },
         }
@@ -170,12 +171,24 @@ fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
     }
 }
 
-crate fn from_def_id(did: FakeDefId) -> Id {
+crate fn from_item_id(did: ItemId) -> Id {
+    struct DisplayDefId(DefId);
+
+    impl fmt::Display for DisplayDefId {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            write!(f, "{}:{}", self.0.krate.as_u32(), u32::from(self.0.index))
+        }
+    }
+
     match did {
-        FakeDefId::Real(did) => Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))),
-        // We need to differentiate real and fake ids, because the indices might overlap for fake
-        // and real DefId's, which would cause two different Id's treated as they were the same.
-        FakeDefId::Fake(idx, krate) => Id(format!("F{}:{}", krate.as_u32(), u32::from(idx))),
+        ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
+        ItemId::Blanket { for_, impl_id } => {
+            Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
+        }
+        ItemId::Auto { for_, trait_ } => {
+            Id(format!("a:{}-{}", DisplayDefId(trait_), DisplayDefId(for_)))
+        }
+        ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
     }
 }
 
@@ -375,7 +388,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
         match ty {
             ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath {
                 name: path.whole_name(),
-                id: from_def_id(did.into()),
+                id: from_item_id(did.into()),
                 args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
                 param_names: Vec::new(),
             },
@@ -387,7 +400,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
 
                 Type::ResolvedPath {
                     name: path.whole_name(),
-                    id: from_def_id(id.into()),
+                    id: from_item_id(id.into()),
                     args: path
                         .segments
                         .last()
@@ -568,13 +581,13 @@ fn from_tcx(import: clean::Import, _tcx: TyCtxt<'_>) -> Self {
             Simple(s) => Import {
                 source: import.source.path.whole_name(),
                 name: s.to_string(),
-                id: import.source.did.map(FakeDefId::from).map(from_def_id),
+                id: import.source.did.map(ItemId::from).map(from_item_id),
                 glob: false,
             },
             Glob => Import {
                 source: import.source.path.whole_name(),
                 name: import.source.path.last_name().to_string(),
-                id: import.source.did.map(FakeDefId::from).map(from_def_id),
+                id: import.source.did.map(ItemId::from).map(from_item_id),
                 glob: true,
             },
         }
@@ -668,5 +681,5 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
 }
 
 fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
-    items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect()
+    items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
 }
index 0d84bf250c9e3016705e26f6526e548b9ef9118e..8bdf1a598123043e08f7595f818b7633b920b5d3 100644 (file)
@@ -25,7 +25,7 @@
 use crate::formats::cache::Cache;
 use crate::formats::FormatRenderer;
 use crate::html::render::cache::ExternalLocation;
-use crate::json::conversions::{from_def_id, IntoWithTcx};
+use crate::json::conversions::{from_item_id, IntoWithTcx};
 
 #[derive(Clone)]
 crate struct JsonRenderer<'tcx> {
@@ -53,7 +53,7 @@ fn get_trait_implementors(&mut self, id: DefId) -> Vec<types::Id> {
                     .map(|i| {
                         let item = &i.impl_item;
                         self.item(item.clone()).unwrap();
-                        from_def_id(item.def_id)
+                        from_item_id(item.def_id)
                     })
                     .collect()
             })
@@ -71,7 +71,7 @@ fn get_impls(&mut self, id: DefId) -> Vec<types::Id> {
                         let item = &i.impl_item;
                         if item.def_id.is_local() {
                             self.item(item.clone()).unwrap();
-                            Some(from_def_id(item.def_id))
+                            Some(from_item_id(item.def_id))
                         } else {
                             None
                         }
@@ -91,9 +91,9 @@ fn get_trait_items(&mut self) -> Vec<(types::Id, types::Item)> {
                     let trait_item = &trait_item.trait_;
                     trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
                     Some((
-                        from_def_id(id.into()),
+                        from_item_id(id.into()),
                         types::Item {
-                            id: from_def_id(id.into()),
+                            id: from_item_id(id.into()),
                             crate_id: id.krate.as_u32(),
                             name: self
                                 .cache
@@ -164,13 +164,13 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
         let id = item.def_id;
         if let Some(mut new_item) = self.convert_item(item) {
             if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
-                t.implementors = self.get_trait_implementors(id.expect_real())
+                t.implementors = self.get_trait_implementors(id.expect_def_id())
             } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
-                s.impls = self.get_impls(id.expect_real())
+                s.impls = self.get_impls(id.expect_def_id())
             } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
-                e.impls = self.get_impls(id.expect_real())
+                e.impls = self.get_impls(id.expect_def_id())
             }
-            let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
+            let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone());
 
             // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
             // to make sure the items are unique. The main place this happens is when an item, is
@@ -207,7 +207,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
                 .chain(self.cache.external_paths.clone().into_iter())
                 .map(|(k, (path, kind))| {
                     (
-                        from_def_id(k.into()),
+                        from_item_id(k.into()),
                         types::ItemSummary {
                             crate_id: k.krate.as_u32(),
                             path,
index 64a9905b33f155406839e3ca9a640e9643a975fc..bc635190f4281047557df305da92ee074088509f 100644 (file)
@@ -269,9 +269,9 @@ fn opts() -> Vec<RustcOptGroup> {
     let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable;
     let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable;
     vec![
-        stable("h", |o| o.optflag("h", "help", "show this help message")),
-        stable("V", |o| o.optflag("V", "version", "print rustdoc's version")),
-        stable("v", |o| o.optflag("v", "verbose", "use verbose output")),
+        stable("h", |o| o.optflagmulti("h", "help", "show this help message")),
+        stable("V", |o| o.optflagmulti("V", "version", "print rustdoc's version")),
+        stable("v", |o| o.optflagmulti("v", "verbose", "use verbose output")),
         stable("r", |o| {
             o.optopt("r", "input-format", "the input type of the specified file", "[rust]")
         }),
@@ -309,14 +309,14 @@ fn opts() -> Vec<RustcOptGroup> {
             )
         }),
         stable("plugins", |o| o.optmulti("", "plugins", "removed", "PLUGINS")),
-        stable("no-default", |o| o.optflag("", "no-defaults", "don't run the default passes")),
+        stable("no-default", |o| o.optflagmulti("", "no-defaults", "don't run the default passes")),
         stable("document-private-items", |o| {
-            o.optflag("", "document-private-items", "document private items")
+            o.optflagmulti("", "document-private-items", "document private items")
         }),
         unstable("document-hidden-items", |o| {
-            o.optflag("", "document-hidden-items", "document items that have doc(hidden)")
+            o.optflagmulti("", "document-hidden-items", "document items that have doc(hidden)")
         }),
-        stable("test", |o| o.optflag("", "test", "run code examples as tests")),
+        stable("test", |o| o.optflagmulti("", "test", "run code examples as tests")),
         stable("test-args", |o| {
             o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS")
         }),
@@ -386,7 +386,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL")
         }),
         stable("markdown-no-toc", |o| {
-            o.optflag("", "markdown-no-toc", "don't include table of contents")
+            o.optflagmulti("", "markdown-no-toc", "don't include table of contents")
         }),
         stable("e", |o| {
             o.optopt(
@@ -412,13 +412,13 @@ fn opts() -> Vec<RustcOptGroup> {
             )
         }),
         unstable("display-warnings", |o| {
-            o.optflag("", "display-warnings", "to print code warnings when testing doc")
+            o.optflagmulti("", "display-warnings", "to print code warnings when testing doc")
         }),
         stable("crate-version", |o| {
             o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
         }),
         unstable("sort-modules-by-appearance", |o| {
-            o.optflag(
+            o.optflagmulti(
                 "",
                 "sort-modules-by-appearance",
                 "sort modules by where they appear in the program, rather than alphabetically",
@@ -495,7 +495,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG")
         }),
         unstable("disable-minification", |o| {
-            o.optflag("", "disable-minification", "Disable minification applied on JS files")
+            o.optflagmulti("", "disable-minification", "Disable minification applied on JS files")
         }),
         stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "OPT")),
         stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "OPT")),
@@ -523,7 +523,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
         }),
         unstable("enable-index-page", |o| {
-            o.optflag("", "enable-index-page", "To enable generation of the index page")
+            o.optflagmulti("", "enable-index-page", "To enable generation of the index page")
         }),
         unstable("static-root-path", |o| {
             o.optopt(
@@ -535,7 +535,7 @@ fn opts() -> Vec<RustcOptGroup> {
             )
         }),
         unstable("disable-per-crate-search", |o| {
-            o.optflag(
+            o.optflagmulti(
                 "",
                 "disable-per-crate-search",
                 "disables generating the crate selector on the search box",
@@ -550,14 +550,14 @@ fn opts() -> Vec<RustcOptGroup> {
             )
         }),
         unstable("show-coverage", |o| {
-            o.optflag(
+            o.optflagmulti(
                 "",
                 "show-coverage",
                 "calculate percentage of public items with documentation",
             )
         }),
         unstable("enable-per-target-ignores", |o| {
-            o.optflag(
+            o.optflagmulti(
                 "",
                 "enable-per-target-ignores",
                 "parse ignore-foo for ignoring doctests on a per-target basis",
@@ -582,9 +582,9 @@ fn opts() -> Vec<RustcOptGroup> {
         unstable("test-builder", |o| {
             o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH")
         }),
-        unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")),
+        unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")),
         unstable("generate-redirect-map", |o| {
-            o.optflag(
+            o.optflagmulti(
                 "",
                 "generate-redirect-map",
                 "Generate JSON file at the top level instead of generating HTML redirection files",
@@ -598,9 +598,11 @@ fn opts() -> Vec<RustcOptGroup> {
                 "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]",
             )
         }),
-        unstable("no-run", |o| o.optflag("", "no-run", "Compile doctests without running them")),
+        unstable("no-run", |o| {
+            o.optflagmulti("", "no-run", "Compile doctests without running them")
+        }),
         unstable("show-type-layout", |o| {
-            o.optflag("", "show-type-layout", "Include the memory layout of types in the docs")
+            o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs")
         }),
     ]
 }
index 26a22f5b304945ccb2d426538c43b855821ad799..92e678e4c024ba9f3f67b8f2f3bba8aa35715570 100644 (file)
@@ -213,13 +213,13 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
 
                 let filename = i.span(self.ctx.tcx).filename(self.ctx.sess());
                 let has_doc_example = tests.found_tests != 0;
-                // The `expect_real()` should be okay because `local_def_id_to_hir_id`
+                // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
                 // would presumably panic if a fake `DefIndex` were passed.
                 let hir_id = self
                     .ctx
                     .tcx
                     .hir()
-                    .local_def_id_to_hir_id(i.def_id.expect_real().expect_local());
+                    .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
                 let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
                 // `missing_docs` is allow-by-default, so don't treat this as ignoring the item
                 // unless the user had an explicit `allow`
index 7ccfdf29041d2e00d29c44074cf120e99074aeae..d961340f1f8d3993d0615d8b14d1fc095b430001 100644 (file)
@@ -53,7 +53,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
             return;
         }
 
-        let local_id = match item.def_id.as_real().and_then(|x| x.as_local()) {
+        let local_id = match item.def_id.as_def_id().and_then(|x| x.as_local()) {
             Some(id) => id,
             // We don't need to check the syntax for other crates so returning
             // without doing anything should not be a problem.
@@ -137,7 +137,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             let sp = item.attr_span(self.cx.tcx);
             let extra = crate::html::markdown::ExtraInfo::new_did(
                 self.cx.tcx,
-                item.def_id.expect_real(),
+                item.def_id.expect_def_id(),
                 sp,
             );
             for code_block in markdown::rust_code_blocks(&dox, &extra) {
index 1113d61012852637870290e45ca48f8f46ad2e28..44a3faf6f7be26317fdb6961d4f61ac14c942622 100644 (file)
@@ -830,49 +830,48 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
     fn fold_item(&mut self, item: Item) -> Option<Item> {
         use rustc_middle::ty::DefIdTree;
 
-        let parent_node = if item.is_fake() {
-            None
-        } else {
-            find_nearest_parent_module(self.cx.tcx, item.def_id.expect_real())
-        };
-
+        let parent_node =
+            item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
         if parent_node.is_some() {
             trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
         }
 
         // find item's parent to resolve `Self` in item's docs below
         debug!("looking for the `Self` type");
-        let self_id = if item.is_fake() {
-            None
-        // Checking if the item is a field in an enum variant
-        } else if (matches!(self.cx.tcx.def_kind(item.def_id.expect_real()), DefKind::Field)
-            && matches!(
-                self.cx.tcx.def_kind(self.cx.tcx.parent(item.def_id.expect_real()).unwrap()),
-                DefKind::Variant
-            ))
-        {
-            self.cx
-                .tcx
-                .parent(item.def_id.expect_real())
-                .and_then(|item_id| self.cx.tcx.parent(item_id))
-        } else if matches!(
-            self.cx.tcx.def_kind(item.def_id.expect_real()),
-            DefKind::AssocConst
-                | DefKind::AssocFn
-                | DefKind::AssocTy
-                | DefKind::Variant
-                | DefKind::Field
-        ) {
-            self.cx.tcx.parent(item.def_id.expect_real())
-        // HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
-        // Fixing this breaks `fn render_deref_methods`.
-        // As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
-        // regardless of what rustdoc wants to call it.
-        } else if let Some(parent) = self.cx.tcx.parent(item.def_id.expect_real()) {
-            let parent_kind = self.cx.tcx.def_kind(parent);
-            Some(if parent_kind == DefKind::Impl { parent } else { item.def_id.expect_real() })
-        } else {
-            Some(item.def_id.expect_real())
+        let self_id = match item.def_id.as_def_id() {
+            None => None,
+            Some(did)
+                if (matches!(self.cx.tcx.def_kind(did), DefKind::Field)
+                    && matches!(
+                        self.cx.tcx.def_kind(self.cx.tcx.parent(did).unwrap()),
+                        DefKind::Variant
+                    )) =>
+            {
+                self.cx.tcx.parent(did).and_then(|item_id| self.cx.tcx.parent(item_id))
+            }
+            Some(did)
+                if matches!(
+                    self.cx.tcx.def_kind(did),
+                    DefKind::AssocConst
+                        | DefKind::AssocFn
+                        | DefKind::AssocTy
+                        | DefKind::Variant
+                        | DefKind::Field
+                ) =>
+            {
+                self.cx.tcx.parent(did)
+            }
+            Some(did) => match self.cx.tcx.parent(did) {
+                // HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
+                // Fixing this breaks `fn render_deref_methods`.
+                // As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
+                // regardless of what rustdoc wants to call it.
+                Some(parent) => {
+                    let parent_kind = self.cx.tcx.def_kind(parent);
+                    Some(if parent_kind == DefKind::Impl { parent } else { did })
+                }
+                None => Some(did),
+            },
         };
 
         // FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
@@ -897,7 +896,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
         let inner_docs = item.inner_docs(self.cx.tcx);
 
         if item.is_mod() && inner_docs {
-            self.mod_ids.push(item.def_id.expect_real());
+            self.mod_ids.push(item.def_id.expect_def_id());
         }
 
         // We want to resolve in the lexical scope of the documentation.
@@ -924,7 +923,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
 
         Some(if item.is_mod() {
             if !inner_docs {
-                self.mod_ids.push(item.def_id.expect_real());
+                self.mod_ids.push(item.def_id.expect_def_id());
             }
 
             let ret = self.fold_item_recur(item);
@@ -1235,10 +1234,10 @@ fn resolve_link(
             // item can be non-local e.g. when using #[doc(primitive = "pointer")]
             if let Some((src_id, dst_id)) = id
                 .as_local()
-                // The `expect_real()` should be okay because `local_def_id_to_hir_id`
+                // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
                 // would presumably panic if a fake `DefIndex` were passed.
                 .and_then(|dst_id| {
-                    item.def_id.expect_real().as_local().map(|src_id| (src_id, dst_id))
+                    item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
                 })
             {
                 let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
index 8280bbf0858b7cf48cabf3506b89a0210b4be949..91c495a2bbc069d95cb1c898657bcc3dcdfd7cb1 100644 (file)
@@ -136,10 +136,15 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         if i.is_struct() || i.is_enum() || i.is_union() {
             // FIXME(eddyb) is this `doc(hidden)` check needed?
-            if !self.cx.tcx.get_attrs(i.def_id.expect_real()).lists(sym::doc).has_word(sym::hidden)
+            if !self
+                .cx
+                .tcx
+                .get_attrs(i.def_id.expect_def_id())
+                .lists(sym::doc)
+                .has_word(sym::hidden)
             {
                 self.impls
-                    .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_real()));
+                    .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id()));
             }
         }
 
@@ -149,7 +154,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
 #[derive(Default)]
 struct ItemCollector {
-    items: FxHashSet<FakeDefId>,
+    items: FxHashSet<ItemId>,
 }
 
 impl ItemCollector {
@@ -168,7 +173,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
 struct BadImplStripper {
     prims: FxHashSet<PrimitiveType>,
-    items: FxHashSet<FakeDefId>,
+    items: FxHashSet<ItemId>,
 }
 
 impl BadImplStripper {
@@ -185,7 +190,7 @@ fn keep_impl(&self, ty: &Type) -> bool {
         }
     }
 
-    fn keep_impl_with_def_id(&self, did: FakeDefId) -> bool {
+    fn keep_impl_with_def_id(&self, did: ItemId) -> bool {
         self.items.contains(&did)
     }
 }
index ba698474f16298386a2596b1890ffc90d65e3e44..03bc2b52f178f5336d9047485688691d91d4bb70 100644 (file)
@@ -53,7 +53,7 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
 }
 
 crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
-    if !cx.cache.access_levels.is_public(item.def_id.expect_real())
+    if !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
         || matches!(
             *item.kind,
             clean::StructFieldItem(_)
@@ -71,9 +71,9 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
     {
         return false;
     }
-    // The `expect_real()` should be okay because `local_def_id_to_hir_id`
+    // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
     // would presumably panic if a fake `DefIndex` were passed.
-    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_real().expect_local());
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
     if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
         || inherits_doc_hidden(cx.tcx, hir_id)
     {
@@ -107,7 +107,8 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
                 |lint| lint.build("missing code example in this documentation").emit(),
             );
         }
-    } else if tests.found_tests > 0 && !cx.cache.access_levels.is_public(item.def_id.expect_real())
+    } else if tests.found_tests > 0
+        && !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
     {
         cx.tcx.struct_span_lint_hir(
             crate::lint::PRIVATE_DOC_TESTS,
index 87573e8e037a96c22d546d48647b19c735d65727..0aedbda35e9a8ce26512c8d93056108d811ab4c9 100644 (file)
@@ -2,7 +2,7 @@
 use std::mem;
 
 use crate::clean;
-use crate::clean::{FakeDefIdSet, Item, NestedAttributesExt};
+use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
 use crate::core::DocContext;
 use crate::fold::{strip_item, DocFolder};
 use crate::passes::{ImplStripper, Pass};
@@ -15,7 +15,7 @@
 
 /// Strip items marked `#[doc(hidden)]`
 crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate {
-    let mut retained = FakeDefIdSet::default();
+    let mut retained = ItemIdSet::default();
 
     // strip all #[doc(hidden)] items
     let krate = {
@@ -29,7 +29,7 @@
 }
 
 struct Stripper<'a> {
-    retained: &'a mut FakeDefIdSet,
+    retained: &'a mut ItemIdSet,
     update_retained: bool,
 }
 
index 18abeb607a17f963bdfed6342ee0ac3d7570056a..dfdba2a4b36664712b11e9b9815e1b00c3c02f6f 100644 (file)
@@ -1,4 +1,4 @@
-use crate::clean::{self, FakeDefIdSet};
+use crate::clean::{self, ItemIdSet};
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::passes::{ImplStripper, ImportStripper, Pass, Stripper};
@@ -14,7 +14,7 @@
 /// crate, specified by the `xcrate` flag.
 crate fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
     // This stripper collects all *retained* nodes.
-    let mut retained = FakeDefIdSet::default();
+    let mut retained = ItemIdSet::default();
 
     // strip all private items
     {
index 528518410aa0680a7c0dc24cd7e2cfba1b891b22..4305268c9aab051991d6cff42ebff6ee46abf507 100644 (file)
@@ -2,11 +2,11 @@
 use rustc_middle::middle::privacy::AccessLevels;
 use std::mem;
 
-use crate::clean::{self, FakeDefIdSet, GetDefId, Item};
+use crate::clean::{self, GetDefId, Item, ItemIdSet};
 use crate::fold::{strip_item, DocFolder};
 
 crate struct Stripper<'a> {
-    crate retained: &'a mut FakeDefIdSet,
+    crate retained: &'a mut ItemIdSet,
     crate access_levels: &'a AccessLevels<DefId>,
     crate update_retained: bool,
 }
@@ -42,7 +42,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             | clean::TraitAliasItem(..)
             | clean::ForeignTypeItem => {
                 if i.def_id.is_local() {
-                    if !self.access_levels.is_exported(i.def_id.expect_real()) {
+                    if !self.access_levels.is_exported(i.def_id.expect_def_id()) {
                         debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
                         return None;
                     }
@@ -116,7 +116,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
 /// This stripper discards all impls which reference stripped items
 crate struct ImplStripper<'a> {
-    crate retained: &'a FakeDefIdSet,
+    crate retained: &'a ItemIdSet,
 }
 
 impl<'a> DocFolder for ImplStripper<'a> {
index 9c9924841b94889789a25d22b24a20361e272ccd..82d1afac5eceb96fd48f1088917c991ef1fc0106 100644 (file)
@@ -1,7 +1,7 @@
 use super::*;
+use rustc_span::create_default_session_globals_then;
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::Symbol;
-use rustc_span::with_default_session_globals;
 
 fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
     vec![DocFragment {
@@ -17,7 +17,7 @@ fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
 
 #[track_caller]
 fn run_test(input: &str, expected: &str) {
-    with_default_session_globals(|| {
+    create_default_session_globals_then(|| {
         let mut s = create_doc_fragment(input);
         unindent_fragments(&mut s);
         assert_eq!(&s.iter().collect::<String>(), expected);
index b924215733d5584b8fab86dd51ed0b2291fffb9c..4968ffd5a27a7b27a13a050f4784e8c5a589b575 100644 (file)
@@ -105,7 +105,7 @@ fn check_invalid_css() {
 
 #[test]
 fn test_with_minification() {
-    let text = include_str!("../html/static/themes/dark.css");
+    let text = include_str!("../html/static/css/themes/dark.css");
     let minified = minifier::css::minify(&text).expect("CSS minification failed");
 
     let against = load_css_paths(text.as_bytes());
diff --git a/src/test/codegen/array-equality.rs b/src/test/codegen/array-equality.rs
new file mode 100644 (file)
index 0000000..4b60fa4
--- /dev/null
@@ -0,0 +1,57 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @array_eq_value
+#[no_mangle]
+pub fn array_eq_value(a: [u16; 6], b: [u16; 6]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %2 = icmp eq i96 %0, %1
+    // CHECK-NEXT: ret i1 %2
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_ref
+#[no_mangle]
+pub fn array_eq_ref(a: &[u16; 6], b: &[u16; 6]) -> bool {
+    // CHECK: start:
+    // CHECK: load i96, i96* %{{.+}}, align 2
+    // CHECK: load i96, i96* %{{.+}}, align 2
+    // CHECK: icmp eq i96
+    // CHECK-NEXT: ret
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_value_still_passed_by_pointer
+#[no_mangle]
+pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: bitcast
+    // CHECK-NEXT: bitcast
+    // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(18) %{{.+}}, i8* nonnull dereferenceable(18) %{{.+}}, i64 18)
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_long
+#[no_mangle]
+pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: bitcast
+    // CHECK-NEXT: bitcast
+    // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(2468) %{{.+}}, i8* nonnull dereferenceable(2468) %{{.+}}, i64 2468)
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_zero(i128 %0)
+#[no_mangle]
+pub fn array_eq_zero(x: [u16; 8]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i128 %0, 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [0; 8]
+}
diff --git a/src/test/codegen/asm-clobbers.rs b/src/test/codegen/asm-clobbers.rs
new file mode 100644 (file)
index 0000000..9d7c8b5
--- /dev/null
@@ -0,0 +1,19 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm)]
+
+// CHECK-LABEL: @x87_clobber
+// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}
+#[no_mangle]
+pub unsafe fn x87_clobber() {
+    asm!("foo", out("st") _);
+}
+
+// CHECK-LABEL: @mmx_clobber
+// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}
+#[no_mangle]
+pub unsafe fn mmx_clobber() {
+    asm!("bar", out("mm0") _, out("mm1") _);
+}
index 8efa1b15b3fff17b1080641fc7ccad92e18ae9eb..0c16b9ad3ab510fa70fa22c4886d28bb922debdd 100644 (file)
@@ -43,11 +43,11 @@ async fn async_fn_test() {
 // CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
-// CHECK-SAME: flags: DIFlagArtificial
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]],
+// CHECK-NOT: flags: DIFlagArtificial
 
 fn main() {
     let _dummy = async_fn_test();
index e2ba4ad30894d151ac92c3c1354af26bb3bc9998..68d138f8df2f062536d188b464315011299539b2 100644 (file)
@@ -47,11 +47,11 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
-// CHECK-SAME: flags: DIFlagArtificial
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]],
+// CHECK-NOT: flags: DIFlagArtificial
 
 fn main() {
     let _dummy = generator_test();
index acc7879e7b18984474c02b39180032af7f26d5e8..1f99ac7342b39c5c77779a6a3080c783edc09a5f 100644 (file)
@@ -2,15 +2,30 @@
 
 #![crate_type = "lib"]
 
-// #71602: check that slice equality just generates a single bcmp
+// #71602 reported a simple array comparison just generating a loop.
+// This was originally fixed by ensuring it generates a single bcmp,
+// but we now generate it as a load instead. `is_zero_slice` was
+// tweaked to still test the case of comparison against a slice,
+// and `is_zero_array` tests the new array-specific behaviour.
 
 // CHECK-LABEL: @is_zero_slice
 #[no_mangle]
 pub fn is_zero_slice(data: &[u8; 4]) -> bool {
-    // CHECK: start:
+    // CHECK: :
     // CHECK-NEXT: %{{.+}} = getelementptr {{.+}}
     // CHECK-NEXT: %[[BCMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{.+}})
     // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[BCMP]], 0
     // CHECK-NEXT: ret i1 %[[EQ]]
+    &data[..] == [0; 4]
+}
+
+// CHECK-LABEL: @is_zero_array
+#[no_mangle]
+pub fn is_zero_array(data: &[u8; 4]) -> bool {
+    // CHECK: start:
+    // CHECK-NEXT: %[[PTR:.+]] = bitcast [4 x i8]* {{.+}} to i32*
+    // CHECK-NEXT: %[[LOAD:.+]] = load i32, i32* %[[PTR]], align 1
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
     *data == [0; 4]
 }
index ed804ca278d2de5e4120eae497a325668919d105..f1dff27ad67b25d1413423e67dd4b11d7c7710cd 100644 (file)
@@ -1,15 +1,14 @@
-// compile-flags: -C opt-level=0
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-// ignore-riscv64 stdcall isn't supported
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
 
 // Test that `nounwind` atributes are correctly applied to exported `stdcall` and `stdcall-unwind`
 // extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable
 // optimizations above to prevent LLVM from inferring the attribute.
 
-#![crate_type = "lib"]
-#![feature(c_unwind)]
-
 // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
 #[no_mangle]
 pub extern "stdcall" fn rust_item_that_cannot_unwind() {
index aaa63ae55c3acc756e0ecad00db8815128fac75c..d2cf041b72d2371efa2b994ce219d3b74cf3f227 100644 (file)
@@ -1,16 +1,14 @@
-// compile-flags: -C opt-level=0
-// ignore-arm thiscall isn't supported
-// ignore-aarch64 thiscall isn't supported
-// ignore-riscv64 thiscall isn't supported
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind, abi_thiscall)]
+#[lang="sized"]
+trait Sized { }
 
 // Test that `nounwind` atributes are correctly applied to exported `thiscall` and
 // `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We
 // disable optimizations above to prevent LLVM from inferring the attribute.
 
-#![crate_type = "lib"]
-#![feature(abi_thiscall)]
-#![feature(c_unwind)]
-
 // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
 #[no_mangle]
 pub extern "thiscall" fn rust_item_that_cannot_unwind() {
index cf3be2e71967402ea02991b82282ceb2e12ace23..f248fcd839122d4006df757e2c691932149bcbd1 100644 (file)
@@ -1,10 +1,14 @@
 // only-cdb
+// ignore-tidy-linelength
 // compile-flags:-g
 
 // cdb-command: g
 
 // Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
-//       so the best we can do is to make sure we are generating the right debuginfo
+//       so the best we can do is to make sure we are generating the right debuginfo.
+//       Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers)
+//       to disable the natvis for a given expression. We also provide the `-r2` flag
+//       to expand the expression 2 levels.
 
 // cdb-command: dx -r2 a,!
 // cdb-check:a,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
 // cdb-check:        [+0x000] __0              : 0x0 [Type: unsigned int *]
 // cdb-check:    [+0x000] discriminant     : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
 
+// cdb-command: dx -r2 h,!
+// cdb-check:h,!              : Some [Type: enum$<core::option::Option<u32> >]
+// cdb-check:    [+0x000] variant0         [Type: enum$<core::option::Option<u32> >::None]
+// cdb-check:    [+0x000] variant1         [Type: enum$<core::option::Option<u32> >::Some]
+// cdb-check:        [+0x004] __0              : 0xc [Type: unsigned int]
+// cdb-check:    [+0x000] discriminant     : Some (0x1) [Type: core::option::Option]
+
 // cdb-command: dx h
 // cdb-check:h                : Some [Type: enum$<core::option::Option<u32> >]
-// cdb-check:    [+0x000] variant$         : Some (0x1) [Type: core::option::Option]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<u32> >]
+// cdb-check:    [variant]        : Some
 // cdb-check:    [+0x004] __0              : 0xc [Type: unsigned int]
 
+// cdb-command: dx -r2 i,!
+// cdb-check:i,!              : None [Type: enum$<core::option::Option<u32> >]
+// cdb-check:    [+0x000] variant0         [Type: enum$<core::option::Option<u32> >::None]
+// cdb-check:    [+0x000] variant1         [Type: enum$<core::option::Option<u32> >::Some]
+// cdb-check:        [+0x004] __0              : 0x[...] [Type: unsigned int]
+// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: core::option::Option]
+
 // cdb-command: dx i
 // cdb-check:i                : None [Type: enum$<core::option::Option<u32> >]
-// cdb-check:    [+0x000] variant$         : None (0x0) [Type: core::option::Option]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<u32> >]
+// cdb-check:    [variant]        : None
 
 // cdb-command: dx j
 // cdb-check:j                : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
 // cdb-check:        [+0x000] __0              [Type: alloc::string::String]
 // cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$]
 
+// cdb-command: dx -r2 l,!
+// cdb-check:l,!              : $T2 [Type: enum$<core::result::Result<u32, enum$<msvc_pretty_enums::Empty> >, Ok>]
+// cdb-check:    [+0x000] Ok               [Type: enum$<core::result::Result<u32, enum$<msvc_pretty_enums::Empty> >, Ok>::Ok]
+// cdb-check:        [+0x000] __0              : 0x2a [Type: unsigned int]
+
 pub enum CStyleEnum {
     Low = 2,
     High = 16,
@@ -77,6 +102,8 @@ pub enum NicheLayoutEnum {
     Tag2,
 }
 
+pub enum Empty { }
+
 fn main() {
     let a = Some(CStyleEnum::Low);
     let b = Option::<CStyleEnum>::None;
@@ -89,6 +116,7 @@ fn main() {
     let i = Option::<u32>::None;
     let j = CStyleEnum::High;
     let k = Some("IAMA optional string!".to_string());
+    let l = Result::<u32, Empty>::Ok(42);
 
     zzz(); // #break
 }
index 67155b4e9f09ed5dde8761f70f627151061a3ae2..84f76ba4e6e060f47140eb75ecbd9b32a4922537 100644 (file)
@@ -13,7 +13,7 @@
 // gdb-check:$1 = Vec(size=1000000000) = {[...]...}
 
 // gdb-command: print slice
-// gdb-check:$2 = &[u8] {data_ptr: [...], length: 1000000000}
+// gdb-check:$2 = &[u8](size=1000000000) = {[...]...}
 
 #![allow(unused_variables)]
 
diff --git a/src/test/debuginfo/pretty-slices.rs b/src/test/debuginfo/pretty-slices.rs
new file mode 100644 (file)
index 0000000..6adc875
--- /dev/null
@@ -0,0 +1,46 @@
+// ignore-android: FIXME(#10381)
+// ignore-windows
+// compile-flags:-g
+
+// gdb-command: run
+
+// gdb-command: print slice
+// gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2}
+// gdbr-check: $1 = &[i32](size=3) = {0, 1, 2}
+
+// gdb-command: print mut_slice
+// gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7}
+// gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7}
+
+// gdb-command: print str_slice
+// gdb-check: $3 = "string slice"
+
+// gdb-command: print mut_str_slice
+// gdb-check: $4 = "mutable string slice"
+
+// lldb-command: run
+
+// lldb-command: print slice
+// lldb-check: (&[i32]) $0 = size=3 { [0] = 0 [1] = 1 [2] = 2 }
+
+// lldb-command: print mut_slice
+// lldb-check: (&mut [i32]) $1 = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 }
+
+// lldb-command: print str_slice
+// lldb-check: (&str) $2 = "string slice" { data_ptr = [...] length = 12 }
+
+// lldb-command: print mut_str_slice
+// lldb-check: (&mut str) $3 = "mutable string slice" { data_ptr = [...] length = 20 }
+
+fn b() {}
+
+fn main() {
+    let slice: &[i32] = &[0, 1, 2];
+    let mut_slice: &mut [i32] = &mut [2, 3, 5, 7];
+
+    let str_slice: &str = "string slice";
+    let mut mut_str_slice_buffer = String::from("mutable string slice");
+    let mut_str_slice: &mut str = mut_str_slice_buffer.as_mut_str();
+
+    b(); // #break
+}
index a7f384c05007d2556ab1197a5ec4a8007e25ba04..7ed76beb8c6d91b0717de2c37f8ba747a7e89ee2 100644 (file)
 
 // cdb-command: dx some
 // cdb-check:some             : Some [Type: enum$<core::option::Option<i16> >]
-// cdb-check:    [...] variant$         : Some (0x1) [Type: core::option::Option]
-// cdb-check:    [...] __0              : 8 [Type: short]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<i16> >]
+// cdb-check:    [variant]        : Some
+// cdb-check:    [+0x002] __0              : 8 [Type: short]
 
 // cdb-command: dx none
 // cdb-check:none             : None [Type: enum$<core::option::Option<i64> >]
-// cdb-check:    [...] variant$         : None (0x0) [Type: core::option::Option]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<i64> >]
+// cdb-check:    [variant]        : None
 
 // cdb-command: dx some_string
 // NOTE: cdb fails to interpret debug info of Option enums on i686.
diff --git a/src/test/incremental/issue-86753.rs b/src/test/incremental/issue-86753.rs
new file mode 100644 (file)
index 0000000..4d6c435
--- /dev/null
@@ -0,0 +1,50 @@
+// edition:2018
+// revisions: rpass1
+
+
+// Regression test for #86753. The `type_implements_trait` query (since moved to a method)
+// was encountering an ICE during incremental testing when hashing its arguments.
+#![warn(rust_2021_compatibility)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Poll, Context};
+
+struct LocalSet {}
+struct RunUntil<'a, F> {
+    _local_set: &'a LocalSet,
+    _future: F,
+}
+impl<'a, F> RunUntil<'a, F> {
+    fn project<'pin>(self: Pin<&'pin mut Self>) -> Projection<'pin, 'a, F> {
+        unimplemented!()
+    }
+}
+
+struct Projection<'pin, 'a, F>
+where
+    RunUntil<'a, F>: 'pin,
+{
+    pub local_set: &'pin mut &'a LocalSet,
+    pub future: Pin<&'pin mut F>,
+}
+
+impl LocalSet {
+    fn with<T>(&self, _f: impl FnOnce() -> T) -> T {
+        unimplemented!()
+    }
+}
+impl<T: Future> Future for RunUntil<'_, T> {
+    type Output = T::Output;
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let me = self.project();
+        me.local_set.with(|| {
+            let _ = cx.waker();
+            let f = me.future;
+            let _ = f.poll(cx);
+            Poll::Pending
+        })
+    }
+}
+
+fn main() {}
index 2566d745ecd060d128de11ea32f6fa3335caf9e0..8bb5dbc48feefa955bf205eafb431c4404bfaa17 100644 (file)
@@ -30,7 +30,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 +                                          // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
index 093e228a0ce44a57fc8d56f5441d2e16b8533edb..54f1200a21fe110c379d3bcc71996ce9da302e40 100644 (file)
@@ -32,7 +32,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 +                                          // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
index 0517e7fac40e26eb6a7dd42991b30f8b3c222be6..db6e1369161fb37d03a8fef90d6da5c5587b955c 100644 (file)
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
index 0517e7fac40e26eb6a7dd42991b30f8b3c222be6..db6e1369161fb37d03a8fef90d6da5c5587b955c 100644 (file)
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
index 28c80b346e76048b60ddf5a83a2dc34047b065a4..d7bc035e667afdb2ae7fba27c04147c02b33883d 100644 (file)
@@ -22,7 +22,7 @@
                                            // + val: Unevaluated(FOO, [], None)
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
           _1 = move _2 as usize (Misc);    // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
           StorageDead(_2);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
index ae77443e019d5fff416415cb8e7868133565a514..4e19465189c933ec742b116bc3ef9196ce8c66b5 100644 (file)
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref.rs:5:6: 5:10
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _2 = _4;                         // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 -         _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 +         _1 = const 4_i32;                // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
index 402a28f3f9f40d5241ea0ca7d9d6b69fb386ea0c..a58dabdaa4159cd9192750930507461858e7398e 100644 (file)
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
-+                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_4);                     // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
index b97d7d1be1596f381dbaab32ada65822a81df045..bb265b2af7d30150fe9245400ab6917af9941d6c 100644 (file)
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
           StorageDead(_2);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
index 48ede27112c9243df0935409ada9f6e99ce275d4..bb7570fabbba8e02c0ac6cc37472f13b60d346df 100644 (file)
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
index 27791852d6dac9fee00a810914597fc43663c732..d5a36182e35017536045d3efd24fc1c23081c8ca 100644 (file)
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
index 27791852d6dac9fee00a810914597fc43663c732..d5a36182e35017536045d3efd24fc1c23081c8ca 100644 (file)
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
index 1aabee83be6842dbb651797a2c773b8cf98870a3..5ceefce6114f0410a39fb9e0b2bbb24b8421fcfe 100644 (file)
@@ -38,7 +38,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[1]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:7: 12:9
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
         Retag(_10);                      // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         Retag(_4);                       // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
@@ -52,7 +52,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:11: 12:14
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_9);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         Retag(_7);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
index 95a8ef997fa49f405698ba7e439644fa2badb30f..e955feb7d1f41fcc9662be0f78863421ec2abe16 100644 (file)
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 95a8ef997fa49f405698ba7e439644fa2badb30f..e955feb7d1f41fcc9662be0f78863421ec2abe16 100644 (file)
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 261eb3b27eafd1982e3db0969577f20173cb0ee9..ff8c410a7268d4e1b289a6c96523d1c8aa5861cb 100644 (file)
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 261eb3b27eafd1982e3db0969577f20173cb0ee9..ff8c410a7268d4e1b289a6c96523d1c8aa5861cb 100644 (file)
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index a37df4da9ae40561396268af1f3c55597ab46f3a..acb8aca75904b1e9459531f0597c9832e03eb587 100644 (file)
@@ -50,7 +50,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[2]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:70:42: 70:44
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
 -         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
@@ -74,7 +74,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:71:42: 71:45
-                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
+                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
 -         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
@@ -98,7 +98,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:72:42: 72:47
-                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
 -         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
index 5af242376c9304066de78725f9c5cfb9acd0d119..c27ee528b80b7e457abd99aa28978ae2070cc49e 100644 (file)
@@ -57,7 +57,7 @@ fn full_tested_match() -> () {
                                          // + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:14: 16:15
-                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
index c6ef403c3c130297d3f4835d13512d09c880e5d4..787310d072a9b72c2439d14ebca60eea750f4d03 100644 (file)
@@ -127,7 +127,7 @@ fn array_casts() -> () {
                                          // + val: Unevaluated(array_casts, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[317d]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 4bab5a974881a6b4f05cd6f7490c26092bd19907..8abc6a3e4b515d7127e0f9306f180f893aff0b52 100644 (file)
@@ -113,7 +113,7 @@ fn main() -> () {
         StorageLive(_14);                // scope 1 at $DIR/retag.rs:40:31: 43:6
         _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:40:31: 43:6
                                          // closure
-                                         // + def_id: DefId(0:14 ~ retag[317d]::main::{closure#0})
+                                         // + def_id: DefId(0:14 ~ retag[13e7]::main::{closure#0})
                                          // + substs: [
                                          //     i8,
                                          //     for<'r> extern "rust-call" fn((&'r i32,)) -> &'r i32,
@@ -153,7 +153,7 @@ fn main() -> () {
                                          // + val: Unevaluated(main, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:21: 47:23
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:47:21: 47:23
         Retag(_23);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
index 443e2df357fb408fc30a30293718ffb2764ecff3..d3862309ce46f54c6f33aa493dc522bfd709e32c 100644 (file)
@@ -12,7 +12,6 @@
 extern crate rustc_symbol_mangling;
 extern crate rustc_target;
 
-use rustc_codegen_ssa::back::linker::LinkerInfo;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_codegen_ssa::{CodegenResults, CrateInfo};
 use rustc_data_structures::fx::FxHashMap;
@@ -38,8 +37,7 @@ fn codegen_crate<'a, 'tcx>(
             allocator_module: None,
             metadata_module: None,
             metadata,
-            linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()),
-            crate_info: CrateInfo::new(tcx),
+            crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()),
         })
     }
 
index f5a471e66e573fc66f14eb08630a2221349f3fa8..f3d07b25c47f84f309dc13d6ff724585f00d9ebc 100644 (file)
@@ -5,6 +5,6 @@
 OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes"
 
 all:
-       cp $(S)/src/librustdoc/html/static/themes/light.css $(TMPDIR)/test.css
+       cp $(S)/src/librustdoc/html/static/css/themes/light.css $(TMPDIR)/test.css
        $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css
        $(HTMLDOCCK) $(OUTPUT_DIR) foo.rs
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
new file mode 100644 (file)
index 0000000..0f87433
--- /dev/null
@@ -0,0 +1,18 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
+
+# only-i686-pc-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
+       $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll
+       $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
+       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/output.txt output.txt
+else
+       $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
new file mode 100644 (file)
index 0000000..3710507
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate raw_dylib_alt_calling_convention_test;
+
+fn main() {
+    raw_dylib_alt_calling_convention_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
new file mode 100644 (file)
index 0000000..8f64abf
--- /dev/null
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdint.h>
+
+struct S {
+    uint8_t x;
+    int32_t y;
+};
+
+struct S2 {
+    int32_t x;
+    uint8_t y;
+};
+
+struct S3 {
+    uint8_t x[5];
+};
+
+__declspec(dllexport) void __stdcall stdcall_fn_1(int i) {
+    printf("stdcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) {
+    printf("stdcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_3(double d) {
+    printf("stdcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) {
+    printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+// Test that stdcall support works correctly with the nullable pointer optimization.
+__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) {
+    if (s) {
+        printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("stdcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) {
+    printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+// Verify that we compute the correct amount of space in the argument list for a 5-byte struct.
+__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) {
+    printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+// test whether f64/double values are aligned on 4-byte or 8-byte boundaries.
+__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) {
+    printf("stdcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_1(int i) {
+    printf("fastcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) {
+    printf("fastcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_3(double d) {
+    printf("fastcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) {
+    printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) {
+    if (s) {
+        printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("fastcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) {
+    printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) {
+    printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) {
+    printf("fastcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
new file mode 100644 (file)
index 0000000..ba0f141
--- /dev/null
@@ -0,0 +1,71 @@
+#![feature(raw_dylib)]
+
+#[repr(C)]
+#[derive(Clone)]
+struct S {
+    x: u8,
+    y: i32,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S2 {
+    x: i32,
+    y: u8,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S3 {
+    x: [u8; 5],
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "stdcall" {
+    fn stdcall_fn_1(i: i32);
+    fn stdcall_fn_2(c: u8, f: f32);
+    fn stdcall_fn_3(d: f64);
+    fn stdcall_fn_4(i: u8, j: u8, f: f32);
+    fn stdcall_fn_5(a: S, b: i32);
+    fn stdcall_fn_6(a: Option<&S>);
+    fn stdcall_fn_7(a: S2, b: i32);
+    fn stdcall_fn_8(a: S3, b: S3);
+    fn stdcall_fn_9(x: u8, y: f64);
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "fastcall" {
+    fn fastcall_fn_1(i: i32);
+    fn fastcall_fn_2(c: u8, f: f32);
+    fn fastcall_fn_3(d: f64);
+    fn fastcall_fn_4(i: u8, j: u8, f: f32);
+    fn fastcall_fn_5(a: S, b: i32);
+    fn fastcall_fn_6(a: Option<&S>);
+    fn fastcall_fn_7(a: S2, b: i32);
+    fn fastcall_fn_8(a: S3, b: S3);
+    fn fastcall_fn_9(x: u8, y: f64);
+}
+
+pub fn library_function() {
+    unsafe {
+        stdcall_fn_1(14);
+        stdcall_fn_2(16, 3.5);
+        stdcall_fn_3(3.5);
+        stdcall_fn_4(1, 2, 3.0);
+        stdcall_fn_5(S { x: 1, y: 2 }, 16);
+        stdcall_fn_6(Some(&S { x: 10, y: 12 }));
+        stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
+        stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+        stdcall_fn_9(1, 3.0);
+
+        fastcall_fn_1(14);
+        fastcall_fn_2(16, 3.5);
+        fastcall_fn_3(3.5);
+        fastcall_fn_4(1, 2, 3.0);
+        fastcall_fn_5(S { x: 1, y: 2 }, 16);
+        fastcall_fn_6(Some(&S { x: 10, y: 12 }));
+        fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
+        fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+        fastcall_fn_9(1, 3.0);
+    }
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.txt
new file mode 100644 (file)
index 0000000..be598a2
--- /dev/null
@@ -0,0 +1,18 @@
+stdcall_fn_1(14)
+stdcall_fn_2(16, 3.5)
+stdcall_fn_3(3.5)
+stdcall_fn_4(1, 2, 3.0)
+stdcall_fn_5(S { x: 1, y: 2 }, 16)
+stdcall_fn_6(S { x: 10, y: 12 })
+stdcall_fn_7(S2 { x: 15, y: 16 }, 3)
+stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+stdcall_fn_9(1, 3.0)
+fastcall_fn_1(14)
+fastcall_fn_2(16, 3.5)
+fastcall_fn_3(3.5)
+fastcall_fn_4(1, 2, 3.0)
+fastcall_fn_5(S { x: 1, y: 2 }, 16)
+fastcall_fn_6(S { x: 10, y: 12 })
+fastcall_fn_7(S2 { x: 15, y: 16 }, 3)
+fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+fastcall_fn_9(1, 3.0)
diff --git a/src/test/run-make/raw-dylib-c/Makefile b/src/test/run-make/raw-dylib-c/Makefile
new file mode 100644 (file)
index 0000000..26ab4d3
--- /dev/null
@@ -0,0 +1,20 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+       $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
+       $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
+       $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/output.txt output.txt
+else
+       $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-c/driver.rs b/src/test/run-make/raw-dylib-c/driver.rs
new file mode 100644 (file)
index 0000000..4059ede
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-c/extern_1.c b/src/test/run-make/raw-dylib-c/extern_1.c
new file mode 100644 (file)
index 0000000..72737c0
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+    printf("extern_fn_1\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2; didn't get the rename\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+    printf("extern_fn_with_long_name; got the rename\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-c/extern_2.c b/src/test/run-make/raw-dylib-c/extern_2.c
new file mode 100644 (file)
index 0000000..ae87fc3
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+    printf("extern_fn_3\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-c/lib.rs b/src/test/run-make/raw-dylib-c/lib.rs
new file mode 100644 (file)
index 0000000..d8e6301
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+    fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+    fn extern_fn_3();
+}
+
+pub fn library_function() {
+    #[link(name = "extern_1", kind = "raw-dylib")]
+    extern { fn extern_fn_2(); }
+
+    unsafe {
+        extern_fn_1();
+        extern_fn_2();
+        extern_fn_3();
+    }
+}
diff --git a/src/test/run-make/raw-dylib-c/output.txt b/src/test/run-make/raw-dylib-c/output.txt
new file mode 100644 (file)
index 0000000..7800cba
--- /dev/null
@@ -0,0 +1,3 @@
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
diff --git a/src/test/run-make/raw-dylib/Makefile b/src/test/run-make/raw-dylib/Makefile
deleted file mode 100644 (file)
index 7ce46fd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
-
-# only-windows
-# only-msvc
-
--include ../../run-make-fulldeps/tools.mk
-
-all:
-       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
-       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
-       $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
-       $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
-       $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
-       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
-       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
-
-ifdef RUSTC_BLESS_TEST
-       cp "$(TMPDIR)"/output.txt output.txt
-else
-       $(DIFF) output.txt "$(TMPDIR)"/output.txt
-endif
diff --git a/src/test/run-make/raw-dylib/driver.rs b/src/test/run-make/raw-dylib/driver.rs
deleted file mode 100644 (file)
index 4059ede..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-extern crate raw_dylib_test;
-
-fn main() {
-    raw_dylib_test::library_function();
-}
diff --git a/src/test/run-make/raw-dylib/extern_1.c b/src/test/run-make/raw-dylib/extern_1.c
deleted file mode 100644 (file)
index 72737c0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-
-__declspec(dllexport) void extern_fn_1() {
-    printf("extern_fn_1\n");
-    fflush(stdout);
-}
-
-__declspec(dllexport) void extern_fn_2() {
-    printf("extern_fn_2; didn't get the rename\n");
-    fflush(stdout);
-}
-
-__declspec(dllexport) void extern_fn_with_long_name() {
-    printf("extern_fn_with_long_name; got the rename\n");
-    fflush(stdout);
-}
diff --git a/src/test/run-make/raw-dylib/extern_2.c b/src/test/run-make/raw-dylib/extern_2.c
deleted file mode 100644 (file)
index ae87fc3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-__declspec(dllexport) void extern_fn_3() {
-    printf("extern_fn_3\n");
-    fflush(stdout);
-}
diff --git a/src/test/run-make/raw-dylib/lib.rs b/src/test/run-make/raw-dylib/lib.rs
deleted file mode 100644 (file)
index d8e6301..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
-
-#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
-extern {
-    fn extern_fn_1();
-}
-
-#[link(name = "extern_2", kind = "raw-dylib")]
-extern {
-    fn extern_fn_3();
-}
-
-pub fn library_function() {
-    #[link(name = "extern_1", kind = "raw-dylib")]
-    extern { fn extern_fn_2(); }
-
-    unsafe {
-        extern_fn_1();
-        extern_fn_2();
-        extern_fn_3();
-    }
-}
diff --git a/src/test/run-make/raw-dylib/output.txt b/src/test/run-make/raw-dylib/output.txt
deleted file mode 100644 (file)
index 7800cba..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-extern_fn_1
-extern_fn_2; didn't get the rename
-extern_fn_3
diff --git a/src/test/rustdoc/auxiliary/reexports.rs b/src/test/rustdoc/auxiliary/reexports.rs
new file mode 100644 (file)
index 0000000..e04b786
--- /dev/null
@@ -0,0 +1,42 @@
+#![feature(decl_macro)]
+
+pub macro addr_of($place:expr) {
+    &raw const $place
+}
+
+pub macro addr_of_self($place:expr) {
+    &raw const $place
+}
+
+pub macro addr_of_crate($place:expr) {
+    &raw const $place
+}
+
+pub struct Foo;
+pub struct FooSelf;
+pub struct FooCrate;
+
+pub enum Bar { Foo, }
+pub enum BarSelf { Foo, }
+pub enum BarCrate { Foo, }
+
+pub fn foo() {}
+pub fn foo_self() {}
+pub fn foo_crate() {}
+
+pub type Type = i32;
+pub type TypeSelf = i32;
+pub type TypeCrate = i32;
+
+pub union Union {
+    a: i8,
+    b: i8,
+}
+pub union UnionSelf {
+    a: i8,
+    b: i8,
+}
+pub union UnionCrate {
+    a: i8,
+    b: i8,
+}
diff --git a/src/test/rustdoc/duplicate-flags.rs b/src/test/rustdoc/duplicate-flags.rs
new file mode 100644 (file)
index 0000000..dde36df
--- /dev/null
@@ -0,0 +1,4 @@
+// compile-flags: --document-private-items --document-private-items
+
+// @has duplicate_flags/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/reexports-priv.rs b/src/test/rustdoc/reexports-priv.rs
new file mode 100644 (file)
index 0000000..ff74240
--- /dev/null
@@ -0,0 +1,53 @@
+// aux-build: reexports.rs
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+extern crate reexports;
+
+// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {'
+pub use reexports::addr_of;
+// @has 'foo/macro.addr_of_crate.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {'
+pub(crate) use reexports::addr_of_crate;
+// @has 'foo/macro.addr_of_self.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_self($place : expr) {'
+pub(self) use reexports::addr_of_self;
+
+// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;'
+pub use reexports::Foo;
+// @has 'foo/struct.FooCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooCrate;'
+pub(crate) use reexports::FooCrate;
+// @has 'foo/struct.FooSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooSelf;'
+pub(self) use reexports::FooSelf;
+
+// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {'
+pub use reexports::Bar;
+// @has 'foo/enum.BarCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarCrate {'
+pub(crate) use reexports::BarCrate;
+// @has 'foo/enum.BarSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarSelf {'
+pub(self) use reexports::BarSelf;
+
+// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+pub use reexports::foo;
+// @has 'foo/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()'
+pub(crate) use reexports::foo_crate;
+// @has 'foo/fn.foo_self.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_self()'
+pub(self) use reexports::foo_self;
+
+// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type ='
+pub use reexports::Type;
+// @has 'foo/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate ='
+pub(crate) use reexports::TypeCrate;
+// @has 'foo/type.TypeSelf.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeSelf ='
+pub(self) use reexports::TypeSelf;
+
+// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {'
+pub use reexports::Union;
+// @has 'foo/union.UnionCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionCrate {'
+pub(crate) use reexports::UnionCrate;
+// @has 'foo/union.UnionSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionSelf {'
+pub(self) use reexports::UnionSelf;
+
+pub mod foo {
+    // @!has 'foo/foo/union.Union.html'
+    use crate::reexports::Union;
+}
diff --git a/src/test/rustdoc/reexports.rs b/src/test/rustdoc/reexports.rs
new file mode 100644 (file)
index 0000000..ab4c5bc
--- /dev/null
@@ -0,0 +1,47 @@
+// aux-build: reexports.rs
+
+#![crate_name = "foo"]
+
+extern crate reexports;
+
+// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {'
+pub use reexports::addr_of;
+// @!has 'foo/macro.addr_of_crate.html'
+pub(crate) use reexports::addr_of_crate;
+// @!has 'foo/macro.addr_of_self.html'
+pub(self) use reexports::addr_of_self;
+
+// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;'
+pub use reexports::Foo;
+// @!has 'foo/struct.FooCrate.html'
+pub(crate) use reexports::FooCrate;
+// @!has 'foo/struct.FooSelf.html'
+pub(self) use reexports::FooSelf;
+
+// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {'
+pub use reexports::Bar;
+// @!has 'foo/enum.BarCrate.html'
+pub(crate) use reexports::BarCrate;
+// @!has 'foo/enum.BarSelf.html'
+pub(self) use reexports::BarSelf;
+
+// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+pub use reexports::foo;
+// @!has 'foo/fn.foo_crate.html'
+pub(crate) use reexports::foo_crate;
+// @!has 'foo/fn.foo_self.html'
+pub(self) use reexports::foo_self;
+
+// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type ='
+pub use reexports::Type;
+// @!has 'foo/type.TypeCrate.html'
+pub(crate) use reexports::TypeCrate;
+// @!has 'foo/type.TypeSelf.html'
+pub(self) use reexports::TypeSelf;
+
+// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {'
+pub use reexports::Union;
+// @!has 'foo/union.UnionCrate.html'
+pub(crate) use reexports::UnionCrate;
+// @!has 'foo/union.UnionSelf.html'
+pub(self) use reexports::UnionSelf;
index 448c57da754a0c31d374ec146834913acae39f02..bb246de0e572dd4aa65f7a92f33ec63303ce9b19 100644 (file)
@@ -19,7 +19,7 @@
 mod gravy;
 
 pub fn main() {
-    rustc_span::with_default_session_globals(|| parse());
+    rustc_span::create_default_session_globals_then(|| parse());
 
     assert_eq!(gravy::foo(), 10);
 }
index 091c834eccf5f848826f26a4aa59e6e17db776a0..36ff8b01fd454dacaabc288843894dcc59b4124b 100644 (file)
@@ -202,7 +202,7 @@ fn visit_expr(&mut self, e: &mut P<Expr>) {
 }
 
 fn main() {
-    rustc_span::with_default_session_globals(|| run());
+    rustc_span::create_default_session_globals_then(|| run());
 }
 
 fn run() {
diff --git a/src/test/ui/abi/unsupported.aarch64.stderr b/src/test/ui/abi/unsupported.aarch64.stderr
new file mode 100644 (file)
index 0000000..8901745
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:24:1
+   |
+LL | extern "ptx-kernel" fn ptx() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:26:1
+   |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:28:1
+   |
+LL | extern "wasm" fn wasm() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:33:1
+   |
+LL | extern "msp430-interrupt" fn msp430() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:35:1
+   |
+LL | extern "avr-interrupt" fn avr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:37:1
+   |
+LL | extern "x86-interrupt" fn x86() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:39:1
+   |
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:44:1
+   |
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/src/test/ui/abi/unsupported.i686.stderr b/src/test/ui/abi/unsupported.i686.stderr
new file mode 100644 (file)
index 0000000..81b1265
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:24:1
+   |
+LL | extern "ptx-kernel" fn ptx() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:26:1
+   |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:28:1
+   |
+LL | extern "wasm" fn wasm() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:30:1
+   |
+LL | extern "aapcs" fn aapcs() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:33:1
+   |
+LL | extern "msp430-interrupt" fn msp430() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:35:1
+   |
+LL | extern "avr-interrupt" fn avr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/src/test/ui/abi/unsupported.rs b/src/test/ui/abi/unsupported.rs
new file mode 100644 (file)
index 0000000..f0debdc
--- /dev/null
@@ -0,0 +1,48 @@
+// revisions: x64 i686 aarch64
+//
+// [x64] needs-llvm-components: x86
+// [x64]compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
+// [i686] needs-llvm-components: x86
+// [i686]compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
+// [aarch64] needs-llvm-components: aarch64
+// [aarch64]compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
+#![no_core]
+#![feature(
+    no_core,
+    lang_items,
+    abi_ptx,
+    abi_msp430_interrupt,
+    abi_avr_interrupt,
+    abi_thiscall,
+    abi_amdgpu_kernel,
+    wasm_abi,
+    abi_x86_interrupt
+)]
+#[lang="sized"]
+trait Sized { }
+
+extern "ptx-kernel" fn ptx() {}
+//~^ ERROR is not a supported ABI
+extern "amdgpu-kernel" fn amdgpu() {}
+//~^ ERROR is not a supported ABI
+extern "wasm" fn wasm() {}
+//~^ ERROR is not a supported ABI
+extern "aapcs" fn aapcs() {}
+//[x64]~^ ERROR is not a supported ABI
+//[i686]~^^ ERROR is not a supported ABI
+extern "msp430-interrupt" fn msp430() {}
+//~^ ERROR is not a supported ABI
+extern "avr-interrupt" fn avr() {}
+//~^ ERROR is not a supported ABI
+extern "x86-interrupt" fn x86() {}
+//[aarch64]~^ ERROR is not a supported ABI
+extern "stdcall" fn stdcall() {}
+//[x64]~^ WARN use of calling convention not supported
+//[x64]~^^ WARN this was previously accepted
+//[aarch64]~^^^ WARN use of calling convention not supported
+//[aarch64]~^^^^ WARN this was previously accepted
+extern "thiscall" fn thiscall() {}
+//[x64]~^ WARN use of calling convention not supported
+//[x64]~^^ WARN this was previously accepted
+//[aarch64]~^^^ WARN use of calling convention not supported
+//[aarch64]~^^^^ WARN this was previously accepted
diff --git a/src/test/ui/abi/unsupported.x64.stderr b/src/test/ui/abi/unsupported.x64.stderr
new file mode 100644 (file)
index 0000000..5c68461
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:24:1
+   |
+LL | extern "ptx-kernel" fn ptx() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:26:1
+   |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:28:1
+   |
+LL | extern "wasm" fn wasm() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:30:1
+   |
+LL | extern "aapcs" fn aapcs() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:33:1
+   |
+LL | extern "msp430-interrupt" fn msp430() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:35:1
+   |
+LL | extern "avr-interrupt" fn avr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:39:1
+   |
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:44:1
+   |
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0570`.
index da302b248760fa18031eb1c1fedf5a4478526d43..06af08fab80f99afe98558b0cacca3e24cfec13c 100644 (file)
@@ -31,15 +31,26 @@ fn main() {
         //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
         asm!("", in("ip") foo);
         //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
-        asm!("", in("st(2)") foo);
-        //~^ ERROR invalid register `st(2)`: x87 registers are not currently supported as operands
-        asm!("", in("mm0") foo);
-        //~^ ERROR invalid register `mm0`: MMX registers are not currently supported as operands
         asm!("", in("k0") foo);
         //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
         asm!("", in("ah") foo);
         //~^ ERROR invalid register `ah`: high byte registers cannot be used as an operand
 
+        asm!("", in("st(2)") foo);
+        //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        asm!("", in("mm0") foo);
+        //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        asm!("", out("st(2)") _);
+        asm!("", out("mm0") _);
+        asm!("{}", in(x87_reg) foo);
+        //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        asm!("{}", in(mmx_reg) foo);
+        //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        asm!("{}", out(x87_reg) _);
+        //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        asm!("{}", out(mmx_reg) _);
+        //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+
         // Explicit register conflicts
         // (except in/lateout which don't conflict)
 
index 2bfb4854c344220f81ce12a78abe4fe2764cc6ca..14740bf62f8e54d133f8ebc758b263295cf90dd6 100644 (file)
@@ -76,32 +76,56 @@ error: invalid register `ip`: the instruction pointer cannot be used as an opera
 LL |         asm!("", in("ip") foo);
    |                  ^^^^^^^^^^^^
 
-error: invalid register `st(2)`: x87 registers are not currently supported as operands for inline asm
+error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
   --> $DIR/bad-reg.rs:34:18
    |
+LL |         asm!("", in("k0") foo);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
+  --> $DIR/bad-reg.rs:36:18
+   |
+LL |         asm!("", in("ah") foo);
+   |                  ^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:39:18
+   |
 LL |         asm!("", in("st(2)") foo);
    |                  ^^^^^^^^^^^^^^^
 
-error: invalid register `mm0`: MMX registers are not currently supported as operands for inline asm
-  --> $DIR/bad-reg.rs:36:18
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:41:18
    |
 LL |         asm!("", in("mm0") foo);
    |                  ^^^^^^^^^^^^^
 
-error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:38:18
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:45:20
    |
-LL |         asm!("", in("k0") foo);
-   |                  ^^^^^^^^^^^^
+LL |         asm!("{}", in(x87_reg) foo);
+   |                    ^^^^^^^^^^^^^^^
 
-error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
-  --> $DIR/bad-reg.rs:40:18
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:47:20
    |
-LL |         asm!("", in("ah") foo);
-   |                  ^^^^^^^^^^^^
+LL |         asm!("{}", in(mmx_reg) foo);
+   |                    ^^^^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:49:20
+   |
+LL |         asm!("{}", out(x87_reg) _);
+   |                    ^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:51:20
+   |
+LL |         asm!("{}", out(mmx_reg) _);
+   |                    ^^^^^^^^^^^^^^
 
 error: register `al` conflicts with register `ax`
-  --> $DIR/bad-reg.rs:46:33
+  --> $DIR/bad-reg.rs:57:33
    |
 LL |         asm!("", in("eax") foo, in("al") bar);
    |                  -------------  ^^^^^^^^^^^^ register `al`
@@ -109,7 +133,7 @@ LL |         asm!("", in("eax") foo, in("al") bar);
    |                  register `ax`
 
 error: register `ax` conflicts with register `ax`
-  --> $DIR/bad-reg.rs:48:33
+  --> $DIR/bad-reg.rs:59:33
    |
 LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  -------------  ^^^^^^^^^^^^^^ register `ax`
@@ -117,13 +141,13 @@ LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  register `ax`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:48:18
+  --> $DIR/bad-reg.rs:59:18
    |
 LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  ^^^^^^^^^^^^^
 
 error: register `ymm0` conflicts with register `xmm0`
-  --> $DIR/bad-reg.rs:51:34
+  --> $DIR/bad-reg.rs:62:34
    |
 LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
    |                  --------------  ^^^^^^^^^^^^^^ register `ymm0`
@@ -131,7 +155,7 @@ LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
    |                  register `xmm0`
 
 error: register `ymm0` conflicts with register `xmm0`
-  --> $DIR/bad-reg.rs:53:34
+  --> $DIR/bad-reg.rs:64:34
    |
 LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  --------------  ^^^^^^^^^^^^^^^ register `ymm0`
@@ -139,10 +163,10 @@ LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  register `xmm0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:53:18
+  --> $DIR/bad-reg.rs:64:18
    |
 LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  ^^^^^^^^^^^^^^
 
-error: aborting due to 19 previous errors
+error: aborting due to 23 previous errors
 
index d663431d6836fe1abca2206bc4633be09688264b..97bf225f0cc733b9803844bc583f8ea6134aaeb1 100644 (file)
@@ -2,7 +2,9 @@
 
 macro_rules! pass_nonterminal {
     ($n:expr) => {
-        #[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()`
+        #[repr(align($n))]
+        //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+        //~| ERROR incorrect `repr(align)` attribute format
         struct S;
     };
 }
index 4124f8cea8ebfe0a588114e5f446cfdb2596f387..9bf36f3c58e8120401905cd8cbce8131aefd22a2 100644 (file)
@@ -9,5 +9,17 @@ LL | pass_nonterminal!(n!());
    |
    = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/nonterminal-expansion.rs:5:16
+   |
+LL |         #[repr(align($n))]
+   |                ^^^^^^^^^
+...
+LL | pass_nonterminal!(n!());
+   | ------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0693`.
index d8ccf36852a512a206caf90411db783dad2a6e13..0475df447445df05067ce82fab23feb4ebe0b11e 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
+error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference
   --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5
    |
 LL | fn a(s: &S) {
@@ -6,7 +6,7 @@ LL | fn a(s: &S) {
 LL |     *s.pointer += 1;
    |     ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
+error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference
   --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5
    |
 LL | fn c(s: & &mut S) {
index 1fdeb812bf8bb8e4ca8f1ddd73141d425cd9e762..0866f54b9fab6237b1ab07ed15ba9860d5579868 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `**t1` which is behind a `&` reference
+error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
   --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
    |
 LL |     let t1 = t0;
index ae9167757a0ae756dd1df38adab93ded49a04ef6..4c0e46d453142eeb838bd463b2a857e981ae559f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `***p` which is behind a `&` reference
+error[E0594]: cannot assign to `***p`, which is behind a `&` reference
   --> $DIR/borrowck-issue-14498.rs:16:5
    |
 LL |     let p = &y;
index d2865ffd196a50f67d4dd910c772982a975504a2..369a8c61d2c99b73b3561db0881f17d1e8d36460 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*item` which is behind a `&` reference
+error[E0594]: cannot assign to `*item`, which is behind a `&` reference
   --> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9
    |
 LL |     for item in &mut std::iter::empty::<&'static ()>() {
index 6da88bed2c6ba0caf6a8e6da8b68c57fdc775a72..d301e7b3524b82f41a9b10def2647bc3c81ca6b5 100644 (file)
@@ -9,7 +9,7 @@ fn main() {
     for v in Query.iter_mut() {
         //~^ NOTE this iterator yields `&` references
         *v -= 1;
-        //~^ ERROR cannot assign to `*v` which is behind a `&` reference
+        //~^ ERROR cannot assign to `*v`, which is behind a `&` reference
         //~| NOTE `v` is a `&` reference, so the data it refers to cannot be written
     }
 }
index 143b74c39ba86b9a8bf7206e972ad9e033814ac2..26ce007dd346a33c503b190edad1c1100a3d1e2c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*v` which is behind a `&` reference
+error[E0594]: cannot assign to `*v`, which is behind a `&` reference
   --> $DIR/issue-83309-ice-immut-in-for-loop.rs:11:9
    |
 LL |     for v in Query.iter_mut() {
index b82e0298158aa7c0a22af435a46a5efcd00d930c..1a5f7434fe2bb2173d8183a060bfa7d8790033cd 100644 (file)
@@ -5,4 +5,11 @@ fn main() {
     rofl.push(Vec::new());
     //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
     //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+    let mut mutvar = 42;
+    let r = &mutvar;
+    //~^ HELP consider changing this to be a mutable reference
+    *r = 0;
+    //~^ ERROR cannot assign to `*r`, which is behind a `&` reference
+    //~| NOTE `r` is a `&` reference, so the data it refers to cannot be written
 }
index 863c2e8eccc8c65952cf31701ec247cb7c175e2f..4da4c8f59466666baa5f47b4094fd9296aea4abb 100644 (file)
@@ -7,6 +7,16 @@ LL |
 LL |     rofl.push(Vec::new());
    |     ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error: aborting due to previous error
+error[E0594]: cannot assign to `*r`, which is behind a `&` reference
+  --> $DIR/issue-85765.rs:12:5
+   |
+LL |     let r = &mutvar;
+   |             ------- help: consider changing this to be a mutable reference: `&mut mutvar`
+LL |
+LL |     *r = 0;
+   |     ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0596`.
+Some errors have detailed explanations: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
index 5361ebe3916d712d5170d6ff8a6899a2ce487dfc..edab22569b34f7e6aef5a290d2c333e6f8ac2b3b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
   --> $DIR/mutability-errors.rs:9:5
    |
 LL | fn named_ref(x: &(i32,)) {
@@ -6,7 +6,7 @@ LL | fn named_ref(x: &(i32,)) {
 LL |     *x = (1,);
    |     ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `x.0` which is behind a `&` reference
+error[E0594]: cannot assign to `x.0`, which is behind a `&` reference
   --> $DIR/mutability-errors.rs:10:5
    |
 LL | fn named_ref(x: &(i32,)) {
@@ -57,7 +57,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
 LL |     &mut f().0;
    |     ^^^^^^^^^^ cannot borrow as mutable
 
-error[E0594]: cannot assign to `*x` which is behind a `*const` pointer
+error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer
   --> $DIR/mutability-errors.rs:23:5
    |
 LL | unsafe fn named_ptr(x: *const (i32,)) {
@@ -65,7 +65,7 @@ LL | unsafe fn named_ptr(x: *const (i32,)) {
 LL |     *x = (1,);
    |     ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer
+error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer
   --> $DIR/mutability-errors.rs:24:5
    |
 LL | unsafe fn named_ptr(x: *const (i32,)) {
index 2c02a0d3081e274849f601b0522576e7f14cc5a6..a76efd9a205088efdbd729ca7bc77c46454399f7 100644 (file)
@@ -1,6 +1,9 @@
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-// ignore-riscv64 stdcall isn't supported
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
 
 extern "stdcall" {
     fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
index 6f2a6c359b537720954fca49d289cde8ba828b49..5b4e656d9dca147a55d638380c30ad360e02913f 100644 (file)
@@ -1,11 +1,11 @@
 error[E0045]: C-variadic function must have C or cdecl calling convention
-  --> $DIR/variadic-ffi-1.rs:6:5
+  --> $DIR/variadic-ffi-1.rs:9:5
    |
 LL |     fn printf(_: *const u8, ...);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
 
 error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
-  --> $DIR/variadic-ffi-1.rs:17:9
+  --> $DIR/variadic-ffi-1.rs:20:9
    |
 LL |         foo();
    |         ^^^-- supplied 0 arguments
@@ -13,13 +13,13 @@ LL |         foo();
    |         expected at least 2 arguments
    |
 note: function defined here
-  --> $DIR/variadic-ffi-1.rs:10:8
+  --> $DIR/variadic-ffi-1.rs:13:8
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |        ^^^
 
 error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
-  --> $DIR/variadic-ffi-1.rs:18:9
+  --> $DIR/variadic-ffi-1.rs:21:9
    |
 LL |         foo(1);
    |         ^^^ - supplied 1 argument
@@ -27,13 +27,13 @@ LL |         foo(1);
    |         expected at least 2 arguments
    |
 note: function defined here
-  --> $DIR/variadic-ffi-1.rs:10:8
+  --> $DIR/variadic-ffi-1.rs:13:8
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |        ^^^
 
 error[E0308]: mismatched types
-  --> $DIR/variadic-ffi-1.rs:20:56
+  --> $DIR/variadic-ffi-1.rs:23:56
    |
 LL |         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
    |                -------------------------------------   ^^^ expected non-variadic fn, found variadic function
@@ -44,7 +44,7 @@ LL |         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
                  found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
 
 error[E0308]: mismatched types
-  --> $DIR/variadic-ffi-1.rs:21:54
+  --> $DIR/variadic-ffi-1.rs:24:54
    |
 LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar;
    |                -----------------------------------   ^^^ expected variadic fn, found non-variadic function
@@ -55,37 +55,37 @@ LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar;
                  found fn item `extern "C" fn(_, _) {bar}`
 
 error[E0617]: can't pass `f32` to variadic function
-  --> $DIR/variadic-ffi-1.rs:23:19
+  --> $DIR/variadic-ffi-1.rs:26:19
    |
 LL |         foo(1, 2, 3f32);
    |                   ^^^^ help: cast the value to `c_double`: `3f32 as c_double`
 
 error[E0617]: can't pass `bool` to variadic function
-  --> $DIR/variadic-ffi-1.rs:24:19
+  --> $DIR/variadic-ffi-1.rs:27:19
    |
 LL |         foo(1, 2, true);
    |                   ^^^^ help: cast the value to `c_int`: `true as c_int`
 
 error[E0617]: can't pass `i8` to variadic function
-  --> $DIR/variadic-ffi-1.rs:25:19
+  --> $DIR/variadic-ffi-1.rs:28:19
    |
 LL |         foo(1, 2, 1i8);
    |                   ^^^ help: cast the value to `c_int`: `1i8 as c_int`
 
 error[E0617]: can't pass `u8` to variadic function
-  --> $DIR/variadic-ffi-1.rs:26:19
+  --> $DIR/variadic-ffi-1.rs:29:19
    |
 LL |         foo(1, 2, 1u8);
    |                   ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`
 
 error[E0617]: can't pass `i16` to variadic function
-  --> $DIR/variadic-ffi-1.rs:27:19
+  --> $DIR/variadic-ffi-1.rs:30:19
    |
 LL |         foo(1, 2, 1i16);
    |                   ^^^^ help: cast the value to `c_int`: `1i16 as c_int`
 
 error[E0617]: can't pass `u16` to variadic function
-  --> $DIR/variadic-ffi-1.rs:28:19
+  --> $DIR/variadic-ffi-1.rs:31:19
    |
 LL |         foo(1, 2, 1u16);
    |                   ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr b/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr
deleted file mode 100644 (file)
index dcc9a24..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:10:9
-   |
-LL |         &Y as *const u32 as usize
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:17:5
-   |
-LL |     &0 as *const i32 as usize
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs
deleted file mode 100644 (file)
index 01ea627..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
-    const Y: u32 = 0;
-    // Cast in `const` without `unsafe` block
-    const SAFE: usize = {
-        &Y as *const u32 as usize
-        //~^ ERROR cast of pointer to int is unsafe and requires unsafe
-    };
-}
-
-// Cast in `const fn` without `unsafe` block
-const fn test() -> usize {
-    &0 as *const i32 as usize
-    //~^ ERROR cast of pointer to int is unsafe and requires unsafe
-}
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr b/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr
deleted file mode 100644 (file)
index dcc9a24..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:10:9
-   |
-LL |         &Y as *const u32 as usize
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:17:5
-   |
-LL |     &0 as *const i32 as usize
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs b/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs
deleted file mode 100644 (file)
index 03e99eb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-fn main() {
-    const X: usize = unsafe {
-        main as usize //~ ERROR casting pointers to integers in constants is unstable
-    };
-    const Y: u32 = 0;
-    const Z: usize = unsafe {
-        &Y as *const u32 as usize //~ ERROR is unstable
-    };
-}
-
-const fn test() -> usize {
-    &0 as *const i32 as usize //~ ERROR is unstable
-}
diff --git a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr b/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr
deleted file mode 100644 (file)
index 4a0b424..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0658]: casting pointers to integers in constants is unstable
-  --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:3:9
-   |
-LL |         main as usize
-   |         ^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error[E0658]: casting pointers to integers in constants is unstable
-  --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:7:9
-   |
-LL |         &Y as *const u32 as usize
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error[E0658]: casting pointers to integers in constant functions is unstable
-  --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:12:5
-   |
-LL |     &0 as *const i32 as usize
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 02a243e05064659f62d28ff56a25d379b96d6f49..d8d3bbee200db67df8cb258fec03b2097f227601 100644 (file)
@@ -22,8 +22,7 @@ fn big_box() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         let p = t.0.0;
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Capturing t[(0, 0)] -> ByValue
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
         println!("{} {:?}", t.1, p);
         //~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow
index 7014ae6a5e6af8aaa61f27af249b859f28808993..097462253aae73f0d3d37ac1f03a6b86c5cc5b2b 100644 (file)
@@ -19,18 +19,13 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:24:17
-   |
-LL |         let p = t.0.0;
-   |                 ^^^^^
-note: Capturing t[(0, 0)] -> ByValue
+note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
   --> $DIR/by_value.rs:24:17
    |
 LL |         let p = t.0.0;
    |                 ^^^^^
 note: Capturing t[(1, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:28:29
+  --> $DIR/by_value.rs:27:29
    |
 LL |         println!("{} {:?}", t.1, p);
    |                             ^^^
@@ -53,7 +48,7 @@ note: Min Capture t[(0, 0)] -> ByValue
 LL |         let p = t.0.0;
    |                 ^^^^^
 note: Min Capture t[(1, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:28:29
+  --> $DIR/by_value.rs:27:29
    |
 LL |         println!("{} {:?}", t.1, p);
    |                             ^^^
index a5b4a19d8c3ff1d2972a9a5332244548531ac44a..77effcb006588f263df2c996d3763c3c2bb73ab5 100644 (file)
@@ -8,10 +8,10 @@ fn main() {
     let mut y = (&x, "Y");
     let z = (&mut y, "Z");
 
-    // `x.0` is mutable but we access `x` via `z.0.0`, which is an immutable reference and
+    // `x.0` is mutable but we access `x` via `*z.0.0`, which is an immutable reference and
     // therefore can't be mutated.
     let mut c = || {
-    //~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
+    //~^ ERROR: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference
         z.0.0.0 = format!("X1");
     };
 
index cfe531e17d3d74bafe107b223d58f0a20c108da8..38c530b809a624680626c6b52c608c2113777974 100644 (file)
@@ -1,11 +1,11 @@
-error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
+error[E0596]: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference
   --> $DIR/cant-mutate-imm-borrow.rs:13:17
    |
 LL |     let mut c = || {
    |                 ^^ cannot borrow as mutable
 LL |
 LL |         z.0.0.0 = format!("X1");
-   |         ------- mutable borrow occurs due to use of `z.0.0.0` in closure
+   |         ------- mutable borrow occurs due to use of `*z.0.0` in closure
 
 error: aborting due to previous error
 
index ee8dd4b4fc33d5bae55573bd9bf7f26f88add8b0..e2b7b8f0275204194965c83012005aba659739bd 100644 (file)
@@ -1,25 +1,29 @@
 // run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
 
 use std::thread;
 
 /* Test Send Trait Migration */
-struct SendPointer (*mut i32);
+struct SendPointer(*mut i32);
 unsafe impl Send for SendPointer {}
 
 fn test_send_trait() {
     let mut f = 10;
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || { let _ = &fptr; unsafe {
-        //~^ ERROR: `Send` trait implementation
+        //~^ ERROR: `Send` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
     } });
 }
 
 /* Test Sync Trait Migration */
-struct CustomInt (*mut i32);
-struct SyncPointer (CustomInt);
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
 unsafe impl Sync for SyncPointer {}
 unsafe impl Send for CustomInt {}
 
@@ -28,9 +32,12 @@ fn test_sync_trait() {
     let f = CustomInt(&mut f as *mut i32);
     let fptr = SyncPointer(f);
     thread::spawn(move || { let _ = &fptr; unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation
+        //~^ ERROR: `Sync`, `Send` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
     } });
 }
 
@@ -38,7 +45,7 @@ fn test_sync_trait() {
 struct S(String);
 struct T(i32);
 
-struct U(S,T);
+struct U(S, T);
 
 impl Clone for U {
     fn clone(&self) -> Self {
@@ -49,9 +56,12 @@ impl Clone for U {
 fn test_clone_trait() {
     let f = U(S(String::from("Hello World")), T(0));
     let c = || { let _ = &f; 
-        //~^ ERROR: `Clone` trait implementation, and drop order
+        //~^ ERROR: `Clone` trait implementation for closure and drop order
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
         println!("{:?}", f_1.0);
     };
 
@@ -59,6 +69,7 @@ fn test_clone_trait() {
 
     c_clone();
 }
+//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
 
 fn main() {
     test_send_trait();
index 7a6dcc55bbba664ab18fe30051d532ab31a334f8..6c56ca27475a3d177492a48885e29ea70989b66d 100644 (file)
@@ -1,25 +1,29 @@
 // run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
 
 use std::thread;
 
 /* Test Send Trait Migration */
-struct SendPointer (*mut i32);
+struct SendPointer(*mut i32);
 unsafe impl Send for SendPointer {}
 
 fn test_send_trait() {
     let mut f = 10;
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Send` trait implementation
+        //~^ ERROR: `Send` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
     });
 }
 
 /* Test Sync Trait Migration */
-struct CustomInt (*mut i32);
-struct SyncPointer (CustomInt);
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
 unsafe impl Sync for SyncPointer {}
 unsafe impl Send for CustomInt {}
 
@@ -28,9 +32,12 @@ fn test_sync_trait() {
     let f = CustomInt(&mut f as *mut i32);
     let fptr = SyncPointer(f);
     thread::spawn(move || unsafe {
-        //~^ ERROR: `Sync`, `Send` trait implementation
+        //~^ ERROR: `Sync`, `Send` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
     });
 }
 
@@ -38,7 +45,7 @@ fn test_sync_trait() {
 struct S(String);
 struct T(i32);
 
-struct U(S,T);
+struct U(S, T);
 
 impl Clone for U {
     fn clone(&self) -> Self {
@@ -49,9 +56,12 @@ fn clone(&self) -> Self {
 fn test_clone_trait() {
     let f = U(S(String::from("Hello World")), T(0));
     let c = || {
-        //~^ ERROR: `Clone` trait implementation, and drop order
+        //~^ ERROR: `Clone` trait implementation for closure and drop order
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
         println!("{:?}", f_1.0);
     };
 
@@ -59,6 +69,7 @@ fn test_clone_trait() {
 
     c_clone();
 }
+//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
 
 fn main() {
     test_send_trait();
index d8420f9652e32483f21ee44a337e37b13d302047..9c954b1465d837e5a3d8293382a76323d92eae2b 100644 (file)
@@ -1,39 +1,36 @@
-error: `Send` trait implementation will change in Rust 2021
-  --> $DIR/auto_traits.rs:13:19
+error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
+  --> $DIR/auto_traits.rs:14:19
    |
-LL |       thread::spawn(move || unsafe {
-   |  ___________________^
-LL | |
-LL | |
-LL | |         *fptr.0 = 20;
-LL | |     });
-   | |_____^
+LL |     thread::spawn(move || unsafe {
+   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+...
+LL |         *fptr.0 = 20;
+   |         ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
    |
 note: the lint level is defined here
   --> $DIR/auto_traits.rs:2:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `fptr` to be fully captured
    |
 LL |     thread::spawn(move || { let _ = &fptr; unsafe {
 LL |
 LL |
+LL |
+LL |
 LL |         *fptr.0 = 20;
-LL |     } });
-   |
+ ...
 
-error: `Sync`, `Send` trait implementation will change in Rust 2021
-  --> $DIR/auto_traits.rs:30:19
+error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+  --> $DIR/auto_traits.rs:34:19
    |
-LL |       thread::spawn(move || unsafe {
-   |  ___________________^
-LL | |
-LL | |
-LL | |         *fptr.0.0 = 20;
-LL | |     });
-   | |_____^
+LL |     thread::spawn(move || unsafe {
+   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+...
+LL |         *fptr.0.0 = 20;
+   |         --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `fptr` to be fully captured
@@ -41,21 +38,22 @@ help: add a dummy let to cause `fptr` to be fully captured
 LL |     thread::spawn(move || { let _ = &fptr; unsafe {
 LL |
 LL |
+LL |
+LL |
 LL |         *fptr.0.0 = 20;
-LL |     } });
-   |
+ ...
 
-error: `Clone` trait implementation, and drop order will change in Rust 2021
-  --> $DIR/auto_traits.rs:51:13
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
+  --> $DIR/auto_traits.rs:58:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |         let f_1 = f.1;
-LL | |         println!("{:?}", f_1.0);
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^ in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+...
+LL |         let f_1 = f.1;
+   |                   --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+...
+LL | }
+   | - in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f` to be fully captured
@@ -63,10 +61,10 @@ help: add a dummy let to cause `f` to be fully captured
 LL |     let c = || { let _ = &f; 
 LL |
 LL |
+LL |
+LL |
 LL |         let f_1 = f.1;
-LL |         println!("{:?}", f_1.0);
-LL |     };
-   |
+ ...
 
 error: aborting due to 3 previous errors
 
index 4bc9b19642f618ec8c46fab2d12dbfdf02485dd1..e836f27cd7af1ff1ae363ceceeb32bf8f33807b8 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
 // Test cases for types that implement a insignificant drop (stlib defined)
@@ -13,17 +13,23 @@ fn test1_all_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || { let _ = (&t, &t1, &t2); 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
 
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -33,16 +39,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || { let _ = (&t, &t1); 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
@@ -50,15 +60,17 @@ fn test3_only_by_value_need_migration() {
     let t = (String::new(), String::new());
     let t1 = (String::new(), String::new());
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         println!("{}", t1.1);
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Copy types get copied into the closure instead of move. Therefore we don't need to
 // migrate then as their drop order isn't tied to the closure.
@@ -69,15 +81,17 @@ fn test4_only_non_copy_types_need_migration() {
     let t1 = (0i32, 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn test5_only_drop_types_need_migration() {
     struct S(i32, i32);
@@ -88,15 +102,17 @@ fn test5_only_drop_types_need_migration() {
     let s = S(0i32, 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _s = s.0;
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -104,14 +120,18 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
     let t = (String::new(), String::new());
     let t1 = (String::new(), String::new());
     let c = move || { let _ = (&t1, &t); 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{} {}", t1.1, t.1);
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -120,14 +140,16 @@ fn test7_drop_non_drop_aggregate_need_migration() {
     let t = (String::new(), String::new(), 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn main() {
     test1_all_need_migration();
index 446ce43a469dea4f5a786c197e4ade024593cfa1..fbf9b983f07a265092cae5b2d56ed935b75db791 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
 // Test cases for types that implement a insignificant drop (stlib defined)
@@ -13,17 +13,23 @@ fn test1_all_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
 
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -33,16 +39,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (String::new(), String::new());
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
@@ -50,15 +60,17 @@ fn test3_only_by_value_need_migration() {
     let t = (String::new(), String::new());
     let t1 = (String::new(), String::new());
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         println!("{}", t1.1);
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Copy types get copied into the closure instead of move. Therefore we don't need to
 // migrate then as their drop order isn't tied to the closure.
@@ -69,15 +81,17 @@ fn test4_only_non_copy_types_need_migration() {
     let t1 = (0i32, 0i32);
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn test5_only_drop_types_need_migration() {
     struct S(i32, i32);
@@ -88,15 +102,17 @@ fn test5_only_drop_types_need_migration() {
     let s = S(0i32, 0i32);
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _s = s.0;
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -104,14 +120,18 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
     let t = (String::new(), String::new());
     let t1 = (String::new(), String::new());
     let c = move || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{} {}", t1.1, t.1);
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -120,14 +140,16 @@ fn test7_drop_non_drop_aggregate_need_migration() {
     let t = (String::new(), String::new(), 0i32);
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn main() {
     test1_all_need_migration();
index 0dfbcddc2795c6be07374b3ef41b41b1b3ebbf15..e9e4794cff5f797c76a2af945130ebf14ebc871a 100644 (file)
@@ -1,21 +1,30 @@
-error: drop order will change in Rust 2021
+error: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/insignificant_drop.rs:15:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         let _t2 = t2.0;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL |         let _t1 = t1.0;
+   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+LL |
+LL |         let _t2 = t2.0;
+   |                   ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+   | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
    |
 note: the lint level is defined here
   --> $DIR/insignificant_drop.rs:3:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
    |
@@ -27,18 +36,23 @@ LL |
 LL |         let _t = t.0;
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop.rs:35:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         let _t2 = t2;
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop.rs:41:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL |         let _t1 = t1.0;
+   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1` to be fully captured
@@ -48,21 +62,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop.rs:52:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         println!("{}", t1.1);
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop.rs:62:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -72,21 +85,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         println!("{}", t1.1);
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop.rs:71:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         let _t1 = t1.0;
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop.rs:83:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -96,21 +108,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop.rs:90:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         let _s = s.0;
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop.rs:104:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -120,20 +131,25 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         let _s = s.0;
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop.rs:106:13
-   |
-LL |       let c = move || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         println!("{} {}", t1.1, t.1);
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop.rs:122:13
+   |
+LL |     let c = move || {
+   |             ^^^^^^^
+...
+LL |         println!("{} {}", t1.1, t.1);
+   |                           ----  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+   |                           |
+   |                           in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t1`, `t` to be fully captured
@@ -143,20 +159,20 @@ LL |
 LL |
 LL |
 LL |         println!("{} {}", t1.1, t.1);
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop.rs:122:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop.rs:142:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -166,8 +182,8 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
 error: aborting due to 7 previous errors
 
index 5a781219a72e03d75602e0a349da02c6d629e1ae..4626c04e9ba6ea3a51b342b471f74aa6d5cd7cac 100644 (file)
@@ -1,8 +1,7 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
-
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
@@ -36,14 +35,16 @@ fn significant_drop_needs_migration() {
     let t = (SigDrop {}, SigDrop {});
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Even if a type implements an insignificant drop, if it's
 // elements have a significant drop then the overall type is
@@ -54,14 +55,16 @@ fn generic_struct_with_significant_drop_needs_migration() {
 
     // move is used to force i32 to be copied instead of being a ref
     let c = move || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
 
 fn main() {
     significant_drop_needs_migration();
index d57da3265565e66a1a7a8ecb2126d43c4d99c59c..ebcf1551bacf62d9547e53fbd5750c76fb47ab9f 100644 (file)
@@ -1,8 +1,7 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
-
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
@@ -36,14 +35,16 @@ fn significant_drop_needs_migration() {
     let t = (SigDrop {}, SigDrop {});
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Even if a type implements an insignificant drop, if it's
 // elements have a significant drop then the overall type is
@@ -54,14 +55,16 @@ fn generic_struct_with_significant_drop_needs_migration() {
 
     // move is used to force i32 to be copied instead of being a ref
     let c = move || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
 
 fn main() {
     significant_drop_needs_migration();
index d25f8f635be88f71d5ad5a03fc9ab130b4b0bed5..1e97ca34d162e3f3c58f4ac27514a3f9701ab15c 100644 (file)
@@ -1,20 +1,20 @@
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop_attr_migrations.rs:38:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop_attr_migrations.rs:37:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
 note: the lint level is defined here
   --> $DIR/insignificant_drop_attr_migrations.rs:3:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
@@ -23,20 +23,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/insignificant_drop_attr_migrations.rs:56:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/insignificant_drop_attr_migrations.rs:57:13
    |
-LL |       let c = move || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.1;
-LL | |     };
-   | |_____^
+LL |     let c = move || {
+   |             ^^^^^^^
+...
+LL |         let _t = t.1;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -46,8 +46,8 @@ LL |
 LL |
 LL |
 LL |         let _t = t.1;
-LL |     };
-   |
+LL |
+ ...
 
 error: aborting due to 2 previous errors
 
index a00377456ac8db33d95ffff43c9ee38111b5a54b..a527bf42e574a7b8ce1ccf6140980854ba9e8210 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
index ee3138ea69ee8ac6bb65080b7ad5a4c2e13589fc..ff5d284614bf1390d207e690b0c5bb0614ebb213 100644 (file)
@@ -1,10 +1,10 @@
 // run-pass
 
-#![warn(disjoint_capture_migration)]
+#![warn(rust_2021_incompatible_closure_captures)]
 
 fn main() {
     if let a = "" {
-    //~^ WARNING: irrefutable `if let` pattern
+        //~^ WARNING: irrefutable `if let` pattern
         drop(|_: ()| drop(a));
     }
 }
index 42b6ce54d3c0840b0eba1697018fd2d9920ac022..f3c15a2e6b676e08dc3966c66b644365f4912241 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
 // Test the two possible cases for automated migartion using rustfix
@@ -21,20 +21,24 @@ fn closure_contains_block() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn closure_doesnt_contain_block() {
     let t = (Foo(0), Foo(0));
     let c = || { let _ = &t; t.0 };
     //~^ ERROR: drop order
+    //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     //~| NOTE: for more information, see
     //~| HELP: add a dummy let to cause `t` to be fully captured
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn main() {
     closure_contains_block();
index ab0ed460fbaf43431fc6ff78de2a5ae01d06ff9a..50936d15302b7914e36f1abd1dd8a134c68912da 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
 // Test the two possible cases for automated migartion using rustfix
@@ -21,20 +21,24 @@ fn closure_contains_block() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn closure_doesnt_contain_block() {
     let t = (Foo(0), Foo(0));
     let c = || t.0;
     //~^ ERROR: drop order
+    //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     //~| NOTE: for more information, see
     //~| HELP: add a dummy let to cause `t` to be fully captured
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 fn main() {
     closure_contains_block();
index 7b654f480a37251b4fc308b14e264df9434e29c7..f8f72d1580ca9df798300436768020562789e41e 100644 (file)
@@ -1,20 +1,20 @@
-error: drop order will change in Rust 2021
+error: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/migrations_rustfix.rs:19:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
 note: the lint level is defined here
   --> $DIR/migrations_rustfix.rs:2:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
@@ -23,14 +23,19 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/migrations_rustfix.rs:31:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/migrations_rustfix.rs:33:13
    |
 LL |     let c = || t.0;
-   |             ^^^^^^
+   |             ^^^---
+   |                |
+   |                in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
index abff6802e958694551037b34dadacfcea9335014..f24804018cd85ca10427cb560f13c865089cfd43 100644 (file)
@@ -1,21 +1,29 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
 // ignore-wasm32-bare compiled with panic=abort by default
-
 #![feature(fn_traits)]
 #![feature(never_type)]
 
 use std::panic;
 
-fn foo_diverges() -> ! { panic!() }
+fn foo_diverges() -> ! {
+    panic!()
+}
 
-fn assert_panics<F>(f: F) where F: FnOnce() {
+fn assert_panics<F>(f: F)
+where
+    F: FnOnce(),
+{
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || { let _ = &f; 
-        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation
+        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
+        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
     });
     if let Ok(..) = result {
         panic!("diverging function returned");
@@ -23,7 +31,8 @@ fn assert_panics<F>(f: F) where F: FnOnce() {
 }
 
 fn test_fn_ptr_panic<T>(mut t: T)
-    where T: Fn() -> !
+where
+    T: Fn() -> !,
 {
     let as_fn = <T as Fn<()>>::call;
     assert_panics(|| as_fn(&t, ()));
index baa17e85b5217ccdc86671eb2d0eebb701abe826..6a6a51c51322d8a3c163eb0a49e8ab378153be06 100644 (file)
@@ -1,21 +1,29 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
 // ignore-wasm32-bare compiled with panic=abort by default
-
 #![feature(fn_traits)]
 #![feature(never_type)]
 
 use std::panic;
 
-fn foo_diverges() -> ! { panic!() }
+fn foo_diverges() -> ! {
+    panic!()
+}
 
-fn assert_panics<F>(f: F) where F: FnOnce() {
+fn assert_panics<F>(f: F)
+where
+    F: FnOnce(),
+{
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || {
-        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation
+        //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
+        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
     });
     if let Ok(..) = result {
         panic!("diverging function returned");
@@ -23,7 +31,8 @@ fn assert_panics<F>(f: F) where F: FnOnce() {
 }
 
 fn test_fn_ptr_panic<T>(mut t: T)
-    where T: Fn() -> !
+where
+    T: Fn() -> !,
 {
     let as_fn = <T as Fn<()>>::call;
     assert_panics(|| as_fn(&t, ()));
index 8dca06a836ca370f91409f93c9c11b3730b6aa3b..6ee0d0d252aba783b11a1747133ca92481651fbe 100644 (file)
@@ -1,28 +1,27 @@
-error: `UnwindSafe`, `RefUnwindSafe` trait implementation will change in Rust 2021
-  --> $DIR/mir_calls_to_shims.rs:15:38
+error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+  --> $DIR/mir_calls_to_shims.rs:20:38
    |
-LL |       let result = panic::catch_unwind(move || {
-   |  ______________________________________^
-LL | |
-LL | |
-LL | |         f.0()
-LL | |     });
-   | |_____^
+LL |     let result = panic::catch_unwind(move || {
+   |                                      ^^^^^^^ in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+...
+LL |         f.0()
+   |         --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
    |
 note: the lint level is defined here
   --> $DIR/mir_calls_to_shims.rs:3:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f` to be fully captured
    |
 LL |     let result = panic::catch_unwind(move || { let _ = &f; 
 LL |
 LL |
+LL |
+LL |
 LL |         f.0()
-LL |     });
-   |
+ ...
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
new file mode 100644 (file)
index 0000000..98f578a
--- /dev/null
@@ -0,0 +1,138 @@
+// run-rustfix
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+use std::thread;
+
+struct S(String);
+
+#[derive(Clone)]
+struct T(i32);
+
+struct U(S, T);
+
+impl Clone for U {
+    fn clone(&self) -> Self {
+        U(S(String::from("Hello World")), T(0))
+    }
+}
+
+fn test_multi_issues() {
+    let f1 = U(S(String::from("foo")), T(0));
+    let f2 = U(S(String::from("bar")), T(0));
+    let c = || { let _ = (&f1, &f2); 
+        //~^ ERROR: `Clone` trait implementation for closure and drop order
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
+        let _f_1 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_2 = f2.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+
+fn test_capturing_all_disjoint_fields_individually() {
+    let f1 = U(S(String::from("foo")), T(0));
+    let c = || { let _ = &f1; 
+        //~^ ERROR: `Clone` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1` to be fully captured
+        let _f_1 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_2 = f1.1;
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+
+struct U1(S, T, S);
+
+impl Clone for U1 {
+    fn clone(&self) -> Self {
+        U1(S(String::from("foo")), T(0), S(String::from("bar")))
+    }
+}
+
+fn test_capturing_several_disjoint_fields_individually_1() {
+    let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+    let c = || { let _ = &f1; 
+        //~^ ERROR: `Clone` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1` to be fully captured
+        let _f_0 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_2 = f1.2;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+
+fn test_capturing_several_disjoint_fields_individually_2() {
+    let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+    let c = || { let _ = &f1; 
+        //~^ ERROR: `Clone` trait implementation for closure and drop order
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1` to be fully captured
+        let _f_0 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_1 = f1.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+
+struct SendPointer(*mut i32);
+unsafe impl Send for SendPointer {}
+
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
+unsafe impl Sync for SyncPointer {}
+unsafe impl Send for CustomInt {}
+
+fn test_multi_traits_issues() {
+    let mut f1 = 10;
+    let f1 = CustomInt(&mut f1 as *mut i32);
+    let fptr1 = SyncPointer(f1);
+
+    let mut f2 = 10;
+    let fptr2 = SendPointer(&mut f2 as *mut i32);
+    thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
+        //~^ ERROR: `Sync`, `Send` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
+        *fptr1.0.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+        *fptr2.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+    } });
+}
+
+fn main() {
+    test_multi_issues();
+    test_capturing_all_disjoint_fields_individually();
+    test_capturing_several_disjoint_fields_individually_1();
+    test_capturing_several_disjoint_fields_individually_2();
+    test_multi_traits_issues();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
new file mode 100644 (file)
index 0000000..1577b91
--- /dev/null
@@ -0,0 +1,138 @@
+// run-rustfix
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+use std::thread;
+
+struct S(String);
+
+#[derive(Clone)]
+struct T(i32);
+
+struct U(S, T);
+
+impl Clone for U {
+    fn clone(&self) -> Self {
+        U(S(String::from("Hello World")), T(0))
+    }
+}
+
+fn test_multi_issues() {
+    let f1 = U(S(String::from("foo")), T(0));
+    let f2 = U(S(String::from("bar")), T(0));
+    let c = || {
+        //~^ ERROR: `Clone` trait implementation for closure and drop order
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
+        let _f_1 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_2 = f2.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+
+fn test_capturing_all_disjoint_fields_individually() {
+    let f1 = U(S(String::from("foo")), T(0));
+    let c = || {
+        //~^ ERROR: `Clone` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1` to be fully captured
+        let _f_1 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_2 = f1.1;
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+
+struct U1(S, T, S);
+
+impl Clone for U1 {
+    fn clone(&self) -> Self {
+        U1(S(String::from("foo")), T(0), S(String::from("bar")))
+    }
+}
+
+fn test_capturing_several_disjoint_fields_individually_1() {
+    let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+    let c = || {
+        //~^ ERROR: `Clone` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1` to be fully captured
+        let _f_0 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_2 = f1.2;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+
+fn test_capturing_several_disjoint_fields_individually_2() {
+    let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+    let c = || {
+        //~^ ERROR: `Clone` trait implementation for closure and drop order
+        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `f1` to be fully captured
+        let _f_0 = f1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        let _f_1 = f1.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+    };
+
+    let c_clone = c.clone();
+
+    c_clone();
+}
+//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+
+struct SendPointer(*mut i32);
+unsafe impl Send for SendPointer {}
+
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
+unsafe impl Sync for SyncPointer {}
+unsafe impl Send for CustomInt {}
+
+fn test_multi_traits_issues() {
+    let mut f1 = 10;
+    let f1 = CustomInt(&mut f1 as *mut i32);
+    let fptr1 = SyncPointer(f1);
+
+    let mut f2 = 10;
+    let fptr2 = SendPointer(&mut f2 as *mut i32);
+    thread::spawn(move || unsafe {
+        //~^ ERROR: `Sync`, `Send` trait implementation for closure
+        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
+        *fptr1.0.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+        *fptr2.0 = 20;
+        //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+    });
+}
+
+fn main() {
+    test_multi_issues();
+    test_capturing_all_disjoint_fields_individually();
+    test_capturing_several_disjoint_fields_individually_1();
+    test_capturing_several_disjoint_fields_individually_2();
+    test_multi_traits_issues();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
new file mode 100644 (file)
index 0000000..8a42683
--- /dev/null
@@ -0,0 +1,134 @@
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
+  --> $DIR/multi_diagnostics.rs:23:13
+   |
+LL |     let c = || {
+   |             ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+...
+LL |         let _f_1 = f1.0;
+   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+LL |
+LL |         let _f_2 = f2.1;
+   |                    ---- in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+...
+LL | }
+   | - in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+   |
+note: the lint level is defined here
+  --> $DIR/multi_diagnostics.rs:2:9
+   |
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1`, `f2` to be fully captured
+   |
+LL |     let c = || { let _ = (&f1, &f2); 
+LL |
+LL |
+LL |
+LL |
+LL |         let _f_1 = f1.0;
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
+  --> $DIR/multi_diagnostics.rs:42:13
+   |
+LL |     let c = || {
+   |             ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+...
+LL |         let _f_1 = f1.0;
+   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1` to be fully captured
+   |
+LL |     let c = || { let _ = &f1; 
+LL |
+LL |
+LL |
+LL |
+LL |         let _f_1 = f1.0;
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
+  --> $DIR/multi_diagnostics.rs:67:13
+   |
+LL |     let c = || {
+   |             ^^
+   |             |
+   |             in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+...
+LL |         let _f_0 = f1.0;
+   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+LL |
+LL |         let _f_2 = f1.2;
+   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1` to be fully captured
+   |
+LL |     let c = || { let _ = &f1; 
+LL |
+LL |
+LL |
+LL |
+LL |
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
+  --> $DIR/multi_diagnostics.rs:86:13
+   |
+LL |     let c = || {
+   |             ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+...
+LL |         let _f_0 = f1.0;
+   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+LL |
+LL |         let _f_1 = f1.1;
+   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+   | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1` to be fully captured
+   |
+LL |     let c = || { let _ = &f1; 
+LL |
+LL |
+LL |
+LL |
+LL |         let _f_0 = f1.0;
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+  --> $DIR/multi_diagnostics.rs:119:19
+   |
+LL |     thread::spawn(move || unsafe {
+   |                   ^^^^^^^^^^^^^^
+   |                   |
+   |                   in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+   |                   in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+...
+LL |         *fptr1.0.0 = 20;
+   |         ---------- in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+LL |
+LL |         *fptr2.0 = 20;
+   |         -------- in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
+   |
+LL |     thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
+LL |
+LL |
+LL |
+LL |
+LL |
+ ...
+
+error: aborting due to 5 previous errors
+
index 420d66fba5e306015460b1fa296755f1c98b71a8..8b75e226ab59bcf2ee64ca663b38d7913c570dac 100644 (file)
@@ -2,8 +2,7 @@
 
 // Set of test cases that don't need migrations
 
-#![deny(disjoint_capture_migration)]
-
+#![deny(rust_2021_incompatible_closure_captures)]
 
 // Copy types as copied by the closure instead of being moved into the closure
 // Therefore their drop order isn't tied to the closure and won't be requiring any
@@ -53,7 +52,6 @@ fn test4_insignificant_drop_non_drop_aggregate() {
     c();
 }
 
-
 struct Foo(i32);
 impl Drop for Foo {
     fn drop(&mut self) {
@@ -80,5 +78,4 @@ fn main() {
     test3_only_copy_types_move_closure();
     test4_insignificant_drop_non_drop_aggregate();
     test5_significant_drop_non_drop_aggregate();
-
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs b/src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs
new file mode 100644 (file)
index 0000000..16e3cca
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+
+// Ensure that the old name for `rust_2021_incompatible_closure_captures` is still
+// accepted by the compiler
+
+#![allow(disjoint_capture_migration)]
+//~^ WARN lint `disjoint_capture_migration` has been renamed
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr
new file mode 100644 (file)
index 0000000..47cb689
--- /dev/null
@@ -0,0 +1,10 @@
+warning: lint `disjoint_capture_migration` has been renamed to `rust_2021_incompatible_closure_captures`
+  --> $DIR/old_name.rs:6:10
+   |
+LL | #![allow(disjoint_capture_migration)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rust_2021_incompatible_closure_captures`
+   |
+   = note: `#[warn(renamed_and_removed_lints)]` on by default
+
+warning: 1 warning emitted
+
index 90ea1ed28836ddddd0eeebaabd7bfa367097cc28..226172fb93eb12575d2bdea6e081dafa66f68076 100644 (file)
@@ -1,6 +1,7 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
 
 #[derive(Debug)]
 struct Foo(i32);
@@ -17,19 +18,21 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() {
     let t = ConstainsDropField(Foo(10), Foo(20));
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t = &t.1;
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 struct S;
 impl Drop for S {
-    fn drop(&mut self) {
-    }
+    fn drop(&mut self) {}
 }
 
 struct T(S, S);
@@ -40,15 +43,23 @@ fn test_precise_analysis_long_path_missing() {
     let u = U(T(S, S), T(S, S));
 
     let c = || { let _ = &u; 
-    //~^ ERROR: drop order
-    //~| HELP: add a dummy let to cause `u` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `u` to be fully captured
         let _x = u.0.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
         let _x = u.0.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
         let _x = u.1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+
 
 fn main() {
     test_precise_analysis_drop_paths_not_captured_by_move();
index cb432304592620029d14f68e1475970d3bd428af..7035abe6de0a29ef3d37275431ddf7f318a12d8f 100644 (file)
@@ -1,6 +1,7 @@
 // run-rustfix
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
 
 #[derive(Debug)]
 struct Foo(i32);
@@ -17,19 +18,21 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() {
     let t = ConstainsDropField(Foo(10), Foo(20));
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t = &t.1;
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 struct S;
 impl Drop for S {
-    fn drop(&mut self) {
-    }
+    fn drop(&mut self) {}
 }
 
 struct T(S, S);
@@ -40,15 +43,23 @@ fn test_precise_analysis_long_path_missing() {
     let u = U(T(S, S), T(S, S));
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| HELP: add a dummy let to cause `u` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `u` to be fully captured
         let _x = u.0.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
         let _x = u.0.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
         let _x = u.1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+
 
 fn main() {
     test_precise_analysis_drop_paths_not_captured_by_move();
index f010c51f1361ecd3fe8501a51501d54b872e84c7..5bf73ccc55400edbdc5f1c2a98ab8735cd4608f5 100644 (file)
@@ -1,43 +1,52 @@
-error: drop order will change in Rust 2021
-  --> $DIR/precise.rs:19:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/precise.rs:20:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         let _t = &t.1;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
 note: the lint level is defined here
   --> $DIR/precise.rs:3:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
 LL |     let c = || { let _ = &t; 
 LL |
 LL |
+LL |
 LL |         let _t = t.0;
-LL |         let _t = &t.1;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/precise.rs:42:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/precise.rs:45:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |         let _x = u.0.0;
-LL | |         let _x = u.0.1;
-LL | |         let _x = u.1.0;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _x = u.0.0;
+   |                  ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+LL |
+LL |         let _x = u.0.1;
+   |                  ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+LL |
+LL |         let _x = u.1.0;
+   |                  ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
+   | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
+   | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `u` to be fully captured
@@ -45,9 +54,9 @@ help: add a dummy let to cause `u` to be fully captured
 LL |     let c = || { let _ = &u; 
 LL |
 LL |
+LL |
 LL |         let _x = u.0.0;
-LL |         let _x = u.0.1;
-LL |         let _x = u.1.0;
+LL |
  ...
 
 error: aborting due to 2 previous errors
index e3a7220bf09d239fe0e0555bee613fd7946a70f8..587d71c40fc6986d06364ae4ec36c3ddd0abd517 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 
 #[derive(Debug)]
 struct Foo(i32);
@@ -73,8 +73,7 @@ fn test_precise_analysis_parent_captured_2() {
 
 struct S;
 impl Drop for S {
-    fn drop(&mut self) {
-    }
+    fn drop(&mut self) {}
 }
 
 struct T(S, S);
index 1c970175d182d906d826d87a01a9396460045bb9..236fdb9e26ea2b3972400e0e992529c7f356b8e2 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
 // Test cases for types that implement a significant drop (user defined)
@@ -23,16 +23,22 @@ fn test1_all_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || { let _ = (&t, &t1, &t2); 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -42,16 +48,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || { let _ = (&t, &t1); 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
@@ -59,15 +69,17 @@ fn test3_only_by_value_need_migration() {
     let t = (Foo(0), Foo(0));
     let t1 = (Foo(0), Foo(0));
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         println!("{:?}", t1.1);
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // The root variable might not implement drop themselves but some path starting
 // at the root variable might implement Drop.
@@ -77,14 +89,16 @@ fn test4_type_contains_drop_need_migration() {
     let t = ConstainsDropField(Foo(0), Foo(0));
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -93,28 +107,32 @@ fn test5_drop_non_drop_aggregate_need_migration() {
     let t = (Foo(0), Foo(0), 0i32);
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Test migration analysis in case of Significant and Insignificant Drop aggregates.
 fn test6_significant_insignificant_drop_aggregate_need_migration() {
     let t = (Foo(0), String::new());
 
     let c = || { let _ = &t; 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -123,14 +141,57 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
     let t1 = (Foo(0), Foo(0), Foo(0));
 
     let c = move || { let _ = (&t1, &t); 
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{:?} {:?}", t1.1, t.1);
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+        //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+
+
+fn test8_drop_order_and_blocks() {
+    {
+        let tuple =
+          (String::from("foo"), String::from("bar"));
+        {
+            let c = || { let _ = &tuple; 
+                //~^ ERROR: drop order
+                //~| NOTE: for more information, see
+                //~| HELP: add a dummy let to cause `tuple` to be fully captured
+                tuple.0;
+                //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+            };
+
+            c();
+        }
+        //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+    }
+}
+
+fn test9_drop_order_and_nested_closures() {
+    let tuple =
+        (String::from("foo"), String::from("bar"));
+    let b = || {
+        let c = || { let _ = &tuple; 
+            //~^ ERROR: drop order
+            //~| NOTE: for more information, see
+            //~| HELP: add a dummy let to cause `tuple` to be fully captured
+            tuple.0;
+            //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+        };
+
+        c();
+    };
+    //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+
+    b();
+}
 
 fn main() {
     test1_all_need_migration();
@@ -140,4 +201,6 @@ fn main() {
     test5_drop_non_drop_aggregate_need_migration();
     test6_significant_insignificant_drop_aggregate_need_migration();
     test7_move_closures_non_copy_types_might_need_migration();
+    test8_drop_order_and_blocks();
+    test9_drop_order_and_nested_closures();
 }
index c479a6a54f09b47f62e623b9500e476b6232b41e..a57f7aa565e120788fd2994648d502bc7fc8125e 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
 // Test cases for types that implement a significant drop (user defined)
@@ -23,16 +23,22 @@ fn test1_all_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -42,16 +48,20 @@ fn test2_only_precise_paths_need_migration() {
     let t2 = (Foo(0), Foo(0));
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         let _t1 = t1.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
@@ -59,15 +69,17 @@ fn test3_only_by_value_need_migration() {
     let t = (Foo(0), Foo(0));
     let t1 = (Foo(0), Foo(0));
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
         println!("{:?}", t1.1);
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // The root variable might not implement drop themselves but some path starting
 // at the root variable might implement Drop.
@@ -77,14 +89,16 @@ fn test4_type_contains_drop_need_migration() {
     let t = ConstainsDropField(Foo(0), Foo(0));
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -93,28 +107,32 @@ fn test5_drop_non_drop_aggregate_need_migration() {
     let t = (Foo(0), Foo(0), 0i32);
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
 
 // Test migration analysis in case of Significant and Insignificant Drop aggregates.
 fn test6_significant_insignificant_drop_aggregate_need_migration() {
     let t = (Foo(0), String::new());
 
     let c = || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
+        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -123,14 +141,57 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
     let t1 = (Foo(0), Foo(0), Foo(0));
 
     let c = move || {
-    //~^ ERROR: drop order
-    //~| NOTE: for more information, see
-    //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+        //~^ ERROR: drop order
+        //~| NOTE: for more information, see
+        //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{:?} {:?}", t1.1, t.1);
+        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+        //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
     };
 
     c();
 }
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+
+
+fn test8_drop_order_and_blocks() {
+    {
+        let tuple =
+          (String::from("foo"), String::from("bar"));
+        {
+            let c = || {
+                //~^ ERROR: drop order
+                //~| NOTE: for more information, see
+                //~| HELP: add a dummy let to cause `tuple` to be fully captured
+                tuple.0;
+                //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+            };
+
+            c();
+        }
+        //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+    }
+}
+
+fn test9_drop_order_and_nested_closures() {
+    let tuple =
+        (String::from("foo"), String::from("bar"));
+    let b = || {
+        let c = || {
+            //~^ ERROR: drop order
+            //~| NOTE: for more information, see
+            //~| HELP: add a dummy let to cause `tuple` to be fully captured
+            tuple.0;
+            //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+        };
+
+        c();
+    };
+    //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+
+    b();
+}
 
 fn main() {
     test1_all_need_migration();
@@ -140,4 +201,6 @@ fn main() {
     test5_drop_non_drop_aggregate_need_migration();
     test6_significant_insignificant_drop_aggregate_need_migration();
     test7_move_closures_non_copy_types_might_need_migration();
+    test8_drop_order_and_blocks();
+    test9_drop_order_and_nested_closures();
 }
index 873a9100bee4b86a7e3bb926579cff7a27cc703c..b2b9ae8fd12f51b4274ea3b549821e2443d26b36 100644 (file)
@@ -1,21 +1,30 @@
-error: drop order will change in Rust 2021
+error: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/significant_drop.rs:25:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         let _t2 = t2.0;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL |         let _t1 = t1.0;
+   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+LL |
+LL |         let _t2 = t2.0;
+   |                   ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+   | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
    |
 note: the lint level is defined here
   --> $DIR/significant_drop.rs:2:9
    |
-LL | #![deny(disjoint_capture_migration)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
    |
@@ -24,21 +33,26 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/significant_drop.rs:44:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         let _t2 = t2;
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:50:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL |         let _t1 = t1.0;
+   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1` to be fully captured
@@ -48,21 +62,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         let _t1 = t1.0;
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/significant_drop.rs:61:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |         println!("{:?}", t1.1);
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:71:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -72,20 +85,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |         println!("{:?}", t1.1);
+LL |
  ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/significant_drop.rs:79:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:91:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -95,20 +108,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/significant_drop.rs:95:13
-   |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.0;
-LL | |     };
-   | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:109:13
+   |
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.0;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -118,20 +131,20 @@ LL |
 LL |
 LL |
 LL |         let _t = t.0;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/significant_drop.rs:109:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:125:13
    |
-LL |       let c = || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         let _t = t.1;
-LL | |     };
-   | |_____^
+LL |     let c = || {
+   |             ^^
+...
+LL |         let _t = t.1;
+   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+...
+LL | }
+   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
@@ -141,20 +154,25 @@ LL |
 LL |
 LL |
 LL |         let _t = t.1;
-LL |     };
-   |
+LL |
+ ...
 
-error: drop order will change in Rust 2021
-  --> $DIR/significant_drop.rs:125:13
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:143:13
    |
-LL |       let c = move || {
-   |  _____________^
-LL | |
-LL | |
-LL | |
-LL | |         println!("{:?} {:?}", t1.1, t.1);
-LL | |     };
-   | |_____^
+LL |     let c = move || {
+   |             ^^^^^^^
+...
+LL |         println!("{:?} {:?}", t1.1, t.1);
+   |                               ----  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+   |                               |
+   |                               in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+...
+LL | }
+   | -
+   | |
+   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t1`, `t` to be fully captured
@@ -164,8 +182,54 @@ LL |
 LL |
 LL |
 LL |         println!("{:?} {:?}", t1.1, t.1);
+LL |
+ ...
+
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:163:21
+   |
+LL |             let c = || {
+   |                     ^^
+...
+LL |                 tuple.0;
+   |                 ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+...
+LL |         }
+   |         - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `tuple` to be fully captured
+   |
+LL |             let c = || { let _ = &tuple; 
+LL |
+LL |
+LL |
+LL |                 tuple.0;
+LL |
+ ...
+
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/significant_drop.rs:181:17
+   |
+LL |         let c = || {
+   |                 ^^
+...
+LL |             tuple.0;
+   |             ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+...
 LL |     };
+   |     - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
    |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `tuple` to be fully captured
+   |
+LL |         let c = || { let _ = &tuple; 
+LL |
+LL |
+LL |
+LL |             tuple.0;
+LL |
+ ...
 
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs b/src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs
new file mode 100644 (file)
index 0000000..39cf820
--- /dev/null
@@ -0,0 +1,13 @@
+//run-pass
+#![deny(rust_2021_incompatible_closure_captures)]
+#![allow(unused_must_use)]
+
+fn filter_try_fold(
+    predicate: &mut impl FnMut() -> bool,
+) -> impl FnMut() -> bool + '_ {
+    move || predicate()
+}
+
+fn main() {
+    filter_try_fold(&mut || true);
+}
index 06db19974eb044b3fc12c88b84206269e3b0a890..3b284eadbd0e3a6ef1073d66481a45e9850b8bf6 100644 (file)
@@ -16,7 +16,7 @@ fn simple_move_closure() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         t.0.0 = "new S".into();
-        //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue
+        //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
         //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
     };
     c();
@@ -79,7 +79,7 @@ fn struct_contains_ref_to_another_struct_2() {
     //~| ERROR: Min Capture analysis includes:
         let _t = t.0.0;
         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+        //~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow
     };
 
     c();
@@ -100,8 +100,7 @@ fn struct_contains_ref_to_another_struct_3() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let _t = t.0.0;
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Capturing t[(0, 0)] -> ByValue
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
@@ -122,8 +121,7 @@ fn truncate_box_derefs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let _t = b.0;
-        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
-        //~| NOTE: Capturing b[] -> ByValue
+        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
         //~| NOTE: Min Capture b[] -> ByValue
     };
 
@@ -139,7 +137,7 @@ fn truncate_box_derefs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", b.0);
-        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
+        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
         //~| NOTE: Min Capture b[] -> ByValue
     };
 
@@ -156,11 +154,47 @@ fn truncate_box_derefs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", t.1.0);
-        //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
+        //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
         //~| NOTE: Min Capture t[(1, 0)] -> ByValue
     };
 }
 
+struct Foo { x: i32 }
+
+// Ensure that even in move closures, if the data is not owned by the root variable
+// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
+fn box_mut_1() {
+    let mut foo = Foo { x: 0 } ;
+
+    let p_foo = &mut foo;
+    let box_p_foo = Box::new(p_foo);
+
+    let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    //~| First Pass analysis includes:
+    //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+    //~| Min Capture analysis includes:
+    //~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+}
+
+// Ensure that even in move closures, if the data is not owned by the root variable
+// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
+fn box_mut_2() {
+    let foo = Foo { x: 0 } ;
+
+    let mut box_foo = Box::new(foo);
+    let p_foo = &mut box_foo;
+
+    let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    //~| First Pass analysis includes:
+    //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+    //~| Min Capture analysis includes:
+    //~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+}
+
 fn main() {
     simple_move_closure();
     simple_ref();
@@ -168,4 +202,6 @@ fn main() {
     struct_contains_ref_to_another_struct_2();
     struct_contains_ref_to_another_struct_3();
     truncate_box_derefs();
+    box_mut_2();
+    box_mut_1();
 }
index 013cacfb9f2a565eea499842c027c5e8a0f289dd..c8e2708feee314a3ef7f765ee1174c6604daaea6 100644 (file)
@@ -44,7 +44,7 @@ LL |     let mut c = #[rustc_capture_analysis]
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/move_closure.rs:118:13
+  --> $DIR/move_closure.rs:117:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL |     let c = #[rustc_capture_analysis]
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/move_closure.rs:135:13
+  --> $DIR/move_closure.rs:133:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL |     let c = #[rustc_capture_analysis]
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/move_closure.rs:152:13
+  --> $DIR/move_closure.rs:150:13
    |
 LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,6 +70,24 @@ LL |     let c = #[rustc_capture_analysis]
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
 
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/move_closure.rs:172:13
+   |
+LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/move_closure.rs:189:13
+   |
+LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
 error: First Pass analysis includes:
   --> $DIR/move_closure.rs:15:5
    |
@@ -82,7 +100,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),(0, 0)] -> ByValue
+note: Capturing t[(0, 0),(0, 0)] -> MutBorrow
   --> $DIR/move_closure.rs:18:9
    |
 LL |         t.0.0 = "new S".into();
@@ -208,7 +226,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+note: Min Capture t[(0, 0),Deref] -> ImmBorrow
   --> $DIR/move_closure.rs:80:18
    |
 LL |         let _t = t.0.0;
@@ -221,17 +239,12 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-...  |
+LL | |
 LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-  --> $DIR/move_closure.rs:102:18
-   |
-LL |         let _t = t.0.0;
-   |                  ^^^^^
-note: Capturing t[(0, 0)] -> ByValue
+note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
   --> $DIR/move_closure.rs:102:18
    |
 LL |         let _t = t.0.0;
@@ -244,7 +257,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-...  |
+LL | |
 LL | |
 LL | |     };
    | |_____^
@@ -256,48 +269,43 @@ LL |         let _t = t.0.0;
    |                  ^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:121:5
+  --> $DIR/move_closure.rs:120:5
    |
 LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = b.0;
-...  |
+LL | |
 LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing b[Deref,(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:124:18
-   |
-LL |         let _t = b.0;
-   |                  ^^^
-note: Capturing b[] -> ByValue
-  --> $DIR/move_closure.rs:124:18
+note: Capturing b[Deref,(0, 0)] -> ImmBorrow
+  --> $DIR/move_closure.rs:123:18
    |
 LL |         let _t = b.0;
    |                  ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:121:5
+  --> $DIR/move_closure.rs:120:5
    |
 LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = b.0;
-...  |
+LL | |
 LL | |
 LL | |     };
    | |_____^
    |
 note: Min Capture b[] -> ByValue
-  --> $DIR/move_closure.rs:124:18
+  --> $DIR/move_closure.rs:123:18
    |
 LL |         let _t = b.0;
    |                  ^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:138:5
+  --> $DIR/move_closure.rs:136:5
    |
 LL | /     move || {
 LL | |
@@ -308,14 +316,14 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing b[Deref,(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:141:24
+note: Capturing b[Deref,(0, 0)] -> ImmBorrow
+  --> $DIR/move_closure.rs:139:24
    |
 LL |         println!("{}", b.0);
    |                        ^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:138:5
+  --> $DIR/move_closure.rs:136:5
    |
 LL | /     move || {
 LL | |
@@ -327,13 +335,13 @@ LL | |     };
    | |_____^
    |
 note: Min Capture b[] -> ByValue
-  --> $DIR/move_closure.rs:141:24
+  --> $DIR/move_closure.rs:139:24
    |
 LL |         println!("{}", b.0);
    |                        ^^^
 
 error: First Pass analysis includes:
-  --> $DIR/move_closure.rs:155:5
+  --> $DIR/move_closure.rs:153:5
    |
 LL | /     move || {
 LL | |
@@ -344,14 +352,14 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
-  --> $DIR/move_closure.rs:158:24
+note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
+  --> $DIR/move_closure.rs:156:24
    |
 LL |         println!("{}", t.1.0);
    |                        ^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/move_closure.rs:155:5
+  --> $DIR/move_closure.rs:153:5
    |
 LL | /     move || {
 LL | |
@@ -363,11 +371,59 @@ LL | |     };
    | |_____^
    |
 note: Min Capture t[(1, 0)] -> ByValue
-  --> $DIR/move_closure.rs:158:24
+  --> $DIR/move_closure.rs:156:24
    |
 LL |         println!("{}", t.1.0);
    |                        ^^^^^
 
-error: aborting due to 24 previous errors
+error: First Pass analysis includes:
+  --> $DIR/move_closure.rs:172:39
+   |
+LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+  --> $DIR/move_closure.rs:172:47
+   |
+LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+   |                                               ^^^^^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/move_closure.rs:172:39
+   |
+LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+  --> $DIR/move_closure.rs:172:47
+   |
+LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+   |                                               ^^^^^^^^^^^
+
+error: First Pass analysis includes:
+  --> $DIR/move_closure.rs:189:39
+   |
+LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+  --> $DIR/move_closure.rs:189:47
+   |
+LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+   |                                               ^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/move_closure.rs:189:39
+   |
+LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+  --> $DIR/move_closure.rs:189:47
+   |
+LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+   |                                               ^^^^^^^
+
+error: aborting due to 30 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs
new file mode 100644 (file)
index 0000000..e7edc0b
--- /dev/null
@@ -0,0 +1,34 @@
+// edition:2021
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+#![allow(dead_code)]
+
+struct Int(i32);
+struct B<'a>(&'a i32);
+
+const I : Int = Int(0);
+const REF_I : &'static Int = &I;
+
+
+struct MyStruct<'a> {
+   a: &'static Int,
+   b: B<'a>,
+}
+
+fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
+    let c = #[rustc_capture_analysis] || drop(&m.a.0);
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    //~| ERROR: First Pass analysis includes:
+    //~| ERROR: Min Capture analysis includes:
+    //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
+    //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
+    c
+}
+
+fn main() {
+    let t = 0;
+    let s = MyStruct { a: REF_I, b: B(&t) };
+    let _ = foo(&s);
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr
new file mode 100644 (file)
index 0000000..87d5d5b
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/edge_case.rs:20:13
+   |
+LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+  --> $DIR/edge_case.rs:20:39
+   |
+LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
+   |                                       ^^^^^^^^^^^^^^^
+   |
+note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
+  --> $DIR/edge_case.rs:20:48
+   |
+LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
+   |                                                ^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/edge_case.rs:20:39
+   |
+LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
+   |                                       ^^^^^^^^^^^^^^^
+   |
+note: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
+  --> $DIR/edge_case.rs:20:48
+   |
+LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
+   |                                                ^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
new file mode 100644 (file)
index 0000000..033fd6f
--- /dev/null
@@ -0,0 +1,27 @@
+// edition:2021
+// run-pass
+
+#![allow(unused)]
+#![allow(dead_code)]
+
+struct Int(i32);
+struct B<'a>(&'a i32);
+
+const I : Int = Int(0);
+const REF_I : &'static Int = &I;
+
+struct MyStruct<'a> {
+   a: &'static Int,
+   b: B<'a>,
+}
+
+fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
+    let c = || drop(&m.a.0);
+    c
+}
+
+fn main() {
+    let t = 0;
+    let s = MyStruct { a: REF_I, b: B(&t) };
+    let _ = foo(&s);
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs
new file mode 100644 (file)
index 0000000..21f14f5
--- /dev/null
@@ -0,0 +1,6 @@
+// check-pass
+#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+struct Bar<const N: usize>(Foo<N, 3>);
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
deleted file mode 100644 (file)
index e0e2b6c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/complex-generic-default-expr.rs:6:34
-   |
-LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
-   |                                  ^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/complex-generic-default-expr.rs:10:21
-   |
-LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-   |                     ^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
index 58abd8db9f09fe3760d9168817a9a84b4f4186d5..44df2ac9f40fadb66034354973eb88cd1935ac74 100644 (file)
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-generic-default-expr.rs:6:47
+  --> $DIR/complex-generic-default-expr.rs:7:47
    |
 LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
    |                                               ^ cannot perform const operation using `N`
index a7b712f7b4b863652f1dd4d91a88d4090eb1075e..d3558007977e46a9f10df41015548eafe1ebc0e6 100644 (file)
@@ -1,14 +1,13 @@
 // revisions: full min
+//[full] check-pass
 #![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
 struct Foo<const N: usize, const M: usize = { N + 1 }>;
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
 struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
 fn main() {}
diff --git a/src/test/ui/const-ptr/ptr_to_usize_cast.rs b/src/test/ui/const-ptr/ptr_to_usize_cast.rs
deleted file mode 100644 (file)
index bf1e790..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
-    const OK: usize = unsafe { 0 as *const i32 as usize };
-
-    const _ERROR: usize = unsafe { &0 as *const i32 as usize };
-    //~^ ERROR [const_err]
-    //~| NOTE cannot cast pointer to integer because it was not created by cast from integer
-    //~| NOTE
-    //~| NOTE `#[deny(const_err)]` on by default
-    //~| WARN this was previously accepted by the compiler but is being phased out
-    //~| NOTE see issue #71800
-}
diff --git a/src/test/ui/const-ptr/ptr_to_usize_cast.stderr b/src/test/ui/const-ptr/ptr_to_usize_cast.stderr
deleted file mode 100644 (file)
index 4825586..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/ptr_to_usize_cast.rs:6:36
-   |
-LL |     const _ERROR: usize = unsafe { &0 as *const i32 as usize };
-   |     -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                    |
-   |                                    cannot cast pointer to integer because it was not created by cast from integer
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
index 5807c5659b6155fd12c7f6e9f17b9c62dcc1ece9..e4455d86a1440b7f183c7d96582f5557bcd6d5f2 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(const_panic)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 #![crate_type = "lib"]
 
 const MSG: &str = "hello";
diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.rs b/src/test/ui/consts/const-eval/const_panic_track_caller.rs
new file mode 100644 (file)
index 0000000..7c25326
--- /dev/null
@@ -0,0 +1,23 @@
+#![feature(const_panic)]
+#![allow(non_fmt_panics)]
+#![crate_type = "lib"]
+
+#[track_caller]
+const fn a() -> u32 {
+    panic!("hey")
+}
+
+#[track_caller]
+const fn b() -> u32 {
+    a()
+}
+
+const fn c() -> u32 {
+    b()
+    //~^ ERROR evaluation of constant value failed
+    //~| NOTE the evaluated program panicked
+    //~| NOTE inside
+}
+
+const X: u32 = c();
+//~^ NOTE inside
diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.stderr b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr
new file mode 100644 (file)
index 0000000..9a458db
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_panic_track_caller.rs:16:5
+   |
+LL |     b()
+   |     ^^^
+   |     |
+   |     the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:16:5
+   |     inside `c` at $DIR/const_panic_track_caller.rs:16:5
+...
+LL | const X: u32 = c();
+   |                --- inside `X` at $DIR/const_panic_track_caller.rs:22:16
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
index c6a623b29327699971454ae03676a2bf090e8e8d..a177ed6b3413eb9f7b26e099aa6934d3c931a291 100644 (file)
@@ -1,15 +1,11 @@
-#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
+#![feature(const_raw_ptr_deref)]
 
 fn main() {}
 
-// unconst and fine
-const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
-// unconst and bad, will thus error in miri
-const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
-//~| WARN this was previously accepted by the compiler but is being phased out
-// unconst and fine
+// fine
 const Z: i32 = unsafe { *(&1 as *const i32) };
-// unconst and bad, will thus error in miri
+
+// bad, will thus error in miri
 const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
 //~| WARN this was previously accepted by the compiler but is being phased out
 const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
index df8b33a0898f659deab953e1a3b9e7614a8a5dcd..de54ea3b9fbd0c7b6754b766a758c500a9dfaf6d 100644 (file)
@@ -1,28 +1,17 @@
 error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:8:28
-   |
-LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
-   | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
-   |                            |
-   |                            cannot cast pointer to integer because it was not created by cast from integer
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:13:26
+  --> $DIR/const_raw_ptr_ops2.rs:9:26
    |
 LL | const Z2: i32 = unsafe { *(42 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
    |                          |
    |                          unable to turn bytes into a pointer
    |
+   = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:15:26
+  --> $DIR/const_raw_ptr_ops2.rs:11:26
    |
 LL | const Z3: i32 = unsafe { *(44 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
@@ -32,5 +21,5 @@ LL | const Z3: i32 = unsafe { *(44 as *const i32) };
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs
deleted file mode 100644 (file)
index 159b48d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    [();  { &loop { break } as *const _ as usize } ];
-    //~^ ERROR casting pointers to integers in constants is unstable
-}
diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr
deleted file mode 100644 (file)
index 2a8f342..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: casting pointers to integers in constants is unstable
-  --> $DIR/issue-52442.rs:2:13
-   |
-LL |     [();  { &loop { break } as *const _ as usize } ];
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index d980eb92a243e87f47020b8c2997f676d40b3ed3..4af97b5487929ce0184a84d429edaf07a1c20b6f 100644 (file)
@@ -4,7 +4,7 @@ fn main() {
     // bytes.
     let _: [u8; 0] = [4; {
         match &1 as *const i32 as usize {
-            //~^ ERROR casting pointers to integers in constants
+            //~^ ERROR pointers cannot be cast to integers during const eval
             0 => 42,
             n => n,
         }
index 22d6bb16944b57427eb83560c90df86b09492b43..4e55b36da73929237f0f52a147fc5900975dd388 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/match-test-ptr-null.rs:6:15
    |
 LL |         match &1 as *const i32 as usize {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index d724fe3060b21b748998189dd2e68a9c14f30d75..c7d84303fe54ca6028248b792869357a0605c38e 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
+#![feature(const_raw_ptr_deref)]
 
 fn main() {
     let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
index 76380ebcb6599b13a671da959749f61249a6da13..46748673067cebb02e795c78449a413186722521 100644 (file)
@@ -7,7 +7,7 @@
 const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
 //~^ ERROR floating point arithmetic
 const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 
 
 fn main() {}
index 80d234b0e881eefe992f83eeb265b39f5ddec67c..2e52bae2b676cf1601d94ded482deb7bcb76489a 100644 (file)
@@ -25,14 +25,14 @@ LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
    = note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
    = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/const-extern-fn-min-const-fn.rs:9:48
    |
 LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
    |                                                ^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to 4 previous errors
 
index 6ed60ed87bf7690048f68452d5e8709ce3070a5e..729ae535ceff69a67b83477e2c0cf441ada945e2 100644 (file)
@@ -4,9 +4,8 @@
 
 const FOO: i32 = Some(42i32).unwrap();
 
-// This causes an error, but it is attributed to the `panic` *inside* `Option::unwrap` (maybe due
-// to `track_caller`?). A note points to the originating `const`.
-const BAR: i32 = Option::<i32>::None.unwrap(); //~ NOTE
+const BAR: i32 = Option::<i32>::None.unwrap();
+//~^ERROR: evaluation of constant value failed
 
 fn main() {
     println!("{}", FOO);
index 9a820ff72171921063c9a2fca4d9273d7476a78c..d2cbe4550f4bbd73d87de07cfb47297b6d80001c 100644 (file)
@@ -1,18 +1,8 @@
 error[E0080]: evaluation of constant value failed
-  --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |             None => panic!("called `Option::unwrap()` on a `None` value"),
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:9:38
-   |                     inside `Option::<i32>::unwrap` at $SRC_DIR/core/src/panic.rs:LL:COL
-   | 
-  ::: $DIR/const-unwrap.rs:9:18
+  --> $DIR/const-unwrap.rs:7:18
    |
 LL | const BAR: i32 = Option::<i32>::None.unwrap();
-   |                  ---------------------------- inside `BAR` at $DIR/const-unwrap.rs:9:18
-   |
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38
 
 error: aborting due to previous error
 
index d56ffebad7d5aeb339713ebdd6845c376702050d..44125a1c3df8d64302f9688a81883083c73873da 100644 (file)
@@ -1,5 +1,5 @@
 static X: usize = unsafe { core::ptr::null::<usize>() as usize };
-//~^ ERROR: casting pointers to integers in statics is unstable
+//~^ ERROR: pointers cannot be cast to integers during const eval
 
 fn main() {
     assert_eq!(X, 0);
index 68e86ea21bd963435501cf3df97b5083b236f530..aab7d798db2e7f663882befd9bbf10a7b0e4d34e 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in statics is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/issue-17458.rs:1:28
    |
 LL | static X: usize = unsafe { core::ptr::null::<usize>() as usize };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-51559.rs b/src/test/ui/consts/issue-51559.rs
deleted file mode 100644 (file)
index cc64440..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(const_raw_ptr_to_usize_cast)]
-
-const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut ();
-pub const FOO: usize = unsafe { BAR as usize };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-fn main() {}
diff --git a/src/test/ui/consts/issue-51559.stderr b/src/test/ui/consts/issue-51559.stderr
deleted file mode 100644 (file)
index d571eb5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/issue-51559.rs:4:33
-   |
-LL | pub const FOO: usize = unsafe { BAR as usize };
-   | --------------------------------^^^^^^^^^^^^---
-   |                                 |
-   |                                 cannot cast pointer to integer because it was not created by cast from integer
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
index cc756ce815f15c19af1038930ce2a002911d2fbb..2249d9879f5dc9243991ddcfb0b945ffdb152ee9 100644 (file)
@@ -1,3 +1,3 @@
 fn main() {
-    let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants
+    let _ = [0; (&0 as *const i32) as usize]; //~ ERROR pointers cannot be cast to integers during const eval
 }
index 68b5cbd9bd7c7a8be4174f1cef77b077887b3b7d..363c7b2c8e462d54281956911cebc8709b4c85b0 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
    |
 LL |     let _ = [0; (&0 as *const i32) as usize];
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs
deleted file mode 100644 (file)
index d719bf1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
-    [(); &(static |x| {}) as *const _ as usize];
-    //~^ ERROR: closures cannot be static
-    //~| ERROR: type annotations needed
-    [(); &(static || {}) as *const _ as usize];
-    //~^ ERROR: closures cannot be static
-    //~| ERROR evaluation of constant value failed
-}
diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr
deleted file mode 100644 (file)
index 2999895..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0697]: closures cannot be static
-  --> $DIR/issue-52432.rs:4:12
-   |
-LL |     [(); &(static |x| {}) as *const _ as usize];
-   |            ^^^^^^^^^^
-
-error[E0697]: closures cannot be static
-  --> $DIR/issue-52432.rs:7:12
-   |
-LL |     [(); &(static || {}) as *const _ as usize];
-   |            ^^^^^^^^^
-
-error[E0282]: type annotations needed
-  --> $DIR/issue-52432.rs:4:20
-   |
-LL |     [(); &(static |x| {}) as *const _ as usize];
-   |                    ^ consider giving this closure parameter a type
-
-error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-52432.rs:7:10
-   |
-LL |     [(); &(static || {}) as *const _ as usize];
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot cast pointer to integer because it was not created by cast from integer
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0080, E0282, E0697.
-For more information about an error, try `rustc --explain E0080`.
index b7904e6841b5d448a26b48b9916757fd99993bbd..bb525d57197789ad5b1ebfbd6a370b00e155e848 100644 (file)
@@ -90,13 +90,13 @@ const fn foo11_2<T: Send>(t: T) -> T { t }
 const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics
 const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot refer to statics
 const fn foo30(x: *const u32) -> usize { x as usize }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_2(x: *mut u32) -> usize { x as usize }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_6() -> bool { let x = true; x }
 const fn inc(x: &mut i32) { *x += 1 }
 //~^ ERROR mutable references
index d31d4121936981f3b0b991c7a8905ad419d00d10..fcbf39d38690b5861ddd04d8d04b3eb9a35d7905 100644 (file)
@@ -164,41 +164,41 @@ LL | const fn foo26() -> &'static u32 { &BAR }
    |
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:92:42
    |
 LL | const fn foo30(x: *const u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:94:63
    |
 LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
    |                                                               ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:96:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:98:63
    |
 LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
    |                                                               ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error[E0658]: mutable references are not allowed in constant functions
   --> $DIR/min_const_fn.rs:101:14
index 62e2dc71210978a882020eb1c8d8f40543b64d90..30309da499f644cdcfe7d3a05b794de66f508c14 100644 (file)
@@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/tls.rs:12:25
    |
 LL |     unsafe { let _val = A; }
-   |                         ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
+   |                         ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/tls.rs:19:26
    |
 LL |     unsafe { let _val = &A; }
-   |                          ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
+   |                          ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
 
 warning: skipping const checks
    |
diff --git a/src/test/ui/consts/rustc-const-stability-require-const.rs b/src/test/ui/consts/rustc-const-stability-require-const.rs
new file mode 100644 (file)
index 0000000..4fb259b
--- /dev/null
@@ -0,0 +1,47 @@
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![stable(feature = "foo", since = "1.0.0")]
+
+#[stable(feature = "foo", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_foo", issue = "none")]
+pub fn foo() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+#[stable(feature = "bar", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+pub fn bar() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+#[stable(feature = "potato", since = "1.0.0")]
+pub struct Potato;
+
+impl Potato {
+    #[stable(feature = "salad", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_salad", issue = "none")]
+    pub fn salad(&self) -> &'static str { "mmmmmm" }
+    //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+    #[stable(feature = "roasted", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
+    pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+    //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+}
+
+#[stable(feature = "bar", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+pub extern "C" fn bar_c() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+#[stable(feature = "foo", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_foo", issue = "none")]
+pub extern "C" fn foo_c() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+
+#[stable(feature = "foobar", since = "1.0.0")]
+#[rustc_const_unstable(feature = "foobar_const", issue = "none")]
+pub const fn foobar() {}
+
+#[stable(feature = "barfoo", since = "1.0.0")]
+#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
+pub const fn barfoo() {}
diff --git a/src/test/ui/consts/rustc-const-stability-require-const.stderr b/src/test/ui/consts/rustc-const-stability-require-const.stderr
new file mode 100644 (file)
index 0000000..1027b93
--- /dev/null
@@ -0,0 +1,86 @@
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:7:1
+   |
+LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
+   | -------------------------------------------------------------- attribute specified here
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:7:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:12:1
+   |
+LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+   | ------------------------------------------------------------- attribute specified here
+LL | pub fn bar() {}
+   | ^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:12:1
+   |
+LL | pub fn bar() {}
+   | ^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:21:5
+   |
+LL |     #[rustc_const_unstable(feature = "const_salad", issue = "none")]
+   |     ---------------------------------------------------------------- attribute specified here
+LL |     pub fn salad(&self) -> &'static str { "mmmmmm" }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:21:5
+   |
+LL |     pub fn salad(&self) -> &'static str { "mmmmmm" }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:26:5
+   |
+LL |     #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
+   |     ------------------------------------------------------------------ attribute specified here
+LL |     pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:26:5
+   |
+LL |     pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:32:1
+   |
+LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+   | ------------------------------------------------------------- attribute specified here
+LL | pub extern "C" fn bar_c() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:32:1
+   |
+LL | pub extern "C" fn bar_c() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:37:1
+   |
+LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
+   | -------------------------------------------------------------- attribute specified here
+LL | pub extern "C" fn foo_c() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:37:1
+   |
+LL | pub extern "C" fn foo_c() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/consts/rustc-impl-const-stability.rs b/src/test/ui/consts/rustc-impl-const-stability.rs
new file mode 100644 (file)
index 0000000..01daa1c
--- /dev/null
@@ -0,0 +1,21 @@
+// build-pass
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![stable(feature = "foo", since = "1.0.0")]
+
+
+#[stable(feature = "potato", since = "1.27.0")]
+pub struct Data {
+    _data: u128
+}
+
+#[stable(feature = "potato", since = "1.27.0")]
+impl const Default for Data {
+    #[rustc_const_unstable(feature = "data_foo", issue = "none")]
+    fn default() -> Data {
+        Data { _data: 42 }
+    }
+}
diff --git a/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr
deleted file mode 100644 (file)
index 7f6a432..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:7:9
-   |
-LL |         1.0 => {}
-   |         ^^^
-   |
-   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:11:9
-   |
-LL |         2.0 => {}
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:7:9
-   |
-LL |         1.0 => {}
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: 3 warnings emitted
-
diff --git a/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr
deleted file mode 100644 (file)
index f2315bc..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:7:9
-   |
-LL |         1.0 => {}
-   |         ^^^
-   |
-   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:11:9
-   |
-LL |         2.0 => {}
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:7:9
-   |
-LL |         1.0 => {}
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
-  --> $DIR/deduplicate-diagnostics-2.rs:11:9
-   |
-LL |         2.0 => {}
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: 4 warnings emitted
-
diff --git a/src/test/ui/deduplicate-diagnostics-2.rs b/src/test/ui/deduplicate-diagnostics-2.rs
deleted file mode 100644 (file)
index f46a7c0..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// build-pass
-// revisions: duplicate deduplicate
-//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes
-
-fn main() {
-    match 0.0 {
-        1.0 => {} //~ WARNING floating-point types cannot be used in patterns
-                  //~| WARNING this was previously accepted
-                  //~| WARNING floating-point types cannot be used in patterns
-                  //~| WARNING this was previously accepted
-        2.0 => {} //~ WARNING floating-point types cannot be used in patterns
-                  //~| WARNING this was previously accepted
-                  //[duplicate]~| WARNING floating-point types cannot be used in patterns
-                  //[duplicate]~| WARNING this was previously accepted
-        _ => {}
-    }
-}
index c33ad1519bcc5ca4f6465682b9e7f9eb693574da..f499ff85e5da8dad7fb48d72df07d4b93b00e3d0 100644 (file)
@@ -1,15 +1,14 @@
 error: use of deprecated function `deprecation_lint::deprecated_text`: text
-  --> $DIR/deprecation-lint-3.rs:13:5
+  --> $DIR/deprecation-lint-3.rs:13:28
    |
 LL |     macro_test_arg_nested!(deprecated_text);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/deprecation-lint-3.rs:4:9
    |
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
-   = note: this error originates in the macro `macro_test_arg_nested` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 3699a939e27882e21e5a0a5363b9461f21cff183..20af4f62e6502cc78af28a3b2bf97afcd8878bd6 100644 (file)
@@ -11,16 +11,16 @@ LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:21:9
+  --> $DIR/deprecation-lint.rs:21:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:23:9
+  --> $DIR/deprecation-lint.rs:23:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:25:9
@@ -29,16 +29,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:30:9
+  --> $DIR/deprecation-lint.rs:30:16
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:32:9
+  --> $DIR/deprecation-lint.rs:32:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text
   --> $DIR/deprecation-lint.rs:34:17
@@ -53,10 +53,10 @@ LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:40:17
+  --> $DIR/deprecation-lint.rs:40:23
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:42:17
@@ -65,28 +65,28 @@ LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text
-  --> $DIR/deprecation-lint.rs:44:17
+  --> $DIR/deprecation-lint.rs:44:25
    |
 LL |         let _ = nested::DeprecatedStruct {
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:48:17
+  --> $DIR/deprecation-lint.rs:48:25
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:50:17
+  --> $DIR/deprecation-lint.rs:50:31
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:52:17
+  --> $DIR/deprecation-lint.rs:52:25
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:59:25
@@ -101,28 +101,28 @@ LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:65:9
+  --> $DIR/deprecation-lint.rs:65:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:67:9
+  --> $DIR/deprecation-lint.rs:67:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:69:9
+  --> $DIR/deprecation-lint.rs:69:16
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:71:9
+  --> $DIR/deprecation-lint.rs:71:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
   --> $DIR/deprecation-lint.rs:81:10
@@ -173,10 +173,10 @@ LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
 error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text
-  --> $DIR/deprecation-lint.rs:162:9
+  --> $DIR/deprecation-lint.rs:162:25
    |
 LL |         deprecated_mod::deprecated();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^
 
 error: use of deprecated function `this_crate::deprecated`: text
   --> $DIR/deprecation-lint.rs:245:9
@@ -185,16 +185,16 @@ LL |         deprecated();
    |         ^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:250:9
+  --> $DIR/deprecation-lint.rs:250:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:252:9
+  --> $DIR/deprecation-lint.rs:252:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:254:9
@@ -203,16 +203,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:259:9
+  --> $DIR/deprecation-lint.rs:259:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:261:9
+  --> $DIR/deprecation-lint.rs:261:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::deprecated_future`: text
   --> $DIR/deprecation-lint.rs:264:9
@@ -239,10 +239,10 @@ LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:274:17
+  --> $DIR/deprecation-lint.rs:274:23
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:276:17
@@ -251,52 +251,52 @@ LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
-  --> $DIR/deprecation-lint.rs:278:17
+  --> $DIR/deprecation-lint.rs:278:25
    |
 LL |         let _ = nested::DeprecatedStruct {
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:283:17
+  --> $DIR/deprecation-lint.rs:283:25
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:285:17
+  --> $DIR/deprecation-lint.rs:285:31
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:287:17
+  --> $DIR/deprecation-lint.rs:287:25
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:292:9
+  --> $DIR/deprecation-lint.rs:292:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:294:9
+  --> $DIR/deprecation-lint.rs:294:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:296:9
+  --> $DIR/deprecation-lint.rs:296:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:298:9
+  --> $DIR/deprecation-lint.rs:298:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
   --> $DIR/deprecation-lint.rs:316:13
index eba72f88a89115cefd1c018221477a124d41d7f4..7d662227881ace5d0af3631968b9f4b1d2627add 100644 (file)
@@ -21,8 +21,22 @@ impl Foo {
     fn replacement(&self) {}
 }
 
+mod bar {
+    #[rustc_deprecated(
+    since = "1.0.0",
+    reason = "replaced by `replacement`",
+    suggestion = "replacement",
+    )]
+    #[stable(since = "1.0.0", feature = "test")]
+    pub fn deprecated() {}
+
+    pub fn replacement() {}
+}
+
 fn main() {
     let foo = Foo;
 
     foo.replacement(); //~ ERROR use of deprecated
+
+    bar::replacement(); //~ ERROR use of deprecated
 }
index 8f9791c13e8563651988f115e89a17c5fdc3ff16..b34dc0eb83a206264a30eda1c5279fb03651f372 100644 (file)
@@ -21,8 +21,22 @@ fn deprecated(&self) {}
     fn replacement(&self) {}
 }
 
+mod bar {
+    #[rustc_deprecated(
+    since = "1.0.0",
+    reason = "replaced by `replacement`",
+    suggestion = "replacement",
+    )]
+    #[stable(since = "1.0.0", feature = "test")]
+    pub fn deprecated() {}
+
+    pub fn replacement() {}
+}
+
 fn main() {
     let foo = Foo;
 
     foo.deprecated(); //~ ERROR use of deprecated
+
+    bar::deprecated(); //~ ERROR use of deprecated
 }
index 8a7cb1def909e3a818d6d2ca588e3dc018456dc9..7d78b2222444f1b769827ebe4f034d7633555d09 100644 (file)
@@ -1,8 +1,8 @@
-error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
-  --> $DIR/suggestion.rs:27:9
+error: use of deprecated function `bar::deprecated`: replaced by `replacement`
+  --> $DIR/suggestion.rs:41:10
    |
-LL |     foo.deprecated();
-   |         ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
+LL |     bar::deprecated();
+   |          ^^^^^^^^^^ help: replace the use of the deprecated function: `replacement`
    |
 note: the lint level is defined here
   --> $DIR/suggestion.rs:7:9
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
-error: aborting due to previous error
+error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
+  --> $DIR/suggestion.rs:39:9
+   |
+LL |     foo.deprecated();
+   |         ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
+
+error: aborting due to 2 previous errors
 
index 3c86f29a89c3068d7c920b1ce606a0d2463bde2c..a19d3f7047cea0ca9155f9e287422e31d49445ac 100644 (file)
@@ -46,5 +46,5 @@ pub fn with_tuple() {
     let mut y = 0;
     let x = (&y,);
     *x.0 = 1;
-    //~^ ERROR cannot assign to `*x.0` which is behind a `&` reference
+    //~^ ERROR cannot assign to `*x.0`, which is behind a `&` reference
 }
index ce0d697238c6b6c85338ac280b94bf47eee2965c..68180eaee036c41f1fa7d80fa88fead6bb498250 100644 (file)
@@ -90,7 +90,7 @@ LL |     let _ = &mut z.x;
 LL |     let _ = &mut w.x;
    |             ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0594]: cannot assign to `*x.0` which is behind a `&` reference
+error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference
   --> $DIR/issue-39544.rs:48:5
    |
 LL |     *x.0 = 1;
index 9dab2c3092434d6645b3dbfe4d43957379df0c4f..41172b362f495b296ce790ec1539dd36d63447f8 100644 (file)
@@ -5,6 +5,6 @@ struct FancyNum {
 fn main() {
     let mut fancy = FancyNum{ num: 5 };
     let fancy_ref = &(&mut fancy);
-    fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num` which is behind a `&` reference
+    fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num`, which is behind a `&` reference
     println!("{}", fancy_ref.num);
 }
index c47750b6f4e69cc72dda552ed86444396b7a7f7d..3d615bd932f436fe42e5c529664424ded3959616 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference
   --> $DIR/E0389.rs:8:5
    |
 LL |     let fancy_ref = &(&mut fancy);
index 97559a68442199d4fd1e73a7689304356d50c406..3909b5301ade5ab672919e9d373c6692200b9d87 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
-// ignore-arm
-// ignore-aarch64
-// ignore-riscv64 fastcall isn't supported
+// only-i686
 
 trait A {
     extern "fastcall" fn test1(i: i32);
index c6ff8a43204de69f99cb12ae4849fe04c5a9ecf3..8ce94aa71aae6e9172fc0fbfd7be185e49a22e75 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
-// ignore-arm
-// ignore-aarch64
-// ignore-riscv64 thiscall isn't supported
+// only-i686
 
 #![feature(abi_thiscall)]
 
index da50c3fb927a4e885a85ed9e57382f34fc15f9d4..f625eb0890f05dc5efbd4b400f904b3038be6a0c 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
-// ignore-arm
-// ignore-aarch64
-// ignore-riscv64 vectorcall isn't supported
+// revisions: x64 x32
+// [x64]only-x86_64
+// [x32]only-i686
 
 #![feature(abi_vectorcall)]
 
index 0d7df8182c45819ab34fd211dc26cfbba2d2d022..05461297afd025b83d122883d341675e8fcd185d 100644 (file)
@@ -1,9 +1,51 @@
+// needs-llvm-components: avr
+// compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
 // Test that the AVR interrupt ABI cannot be used when avr_interrupt
 // feature gate is not used.
 
-extern "avr-interrupt" fn foo() {}
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+extern "avr-non-blocking-interrupt" fn fu() {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+extern "avr-interrupt" fn f() {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+
+trait T {
+    extern "avr-interrupt" fn m();
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    extern "avr-non-blocking-interrupt" fn mu();
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+
+    extern "avr-interrupt" fn dm() {}
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    extern "avr-non-blocking-interrupt" fn dmu() {}
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+}
+
+struct S;
+impl T for S {
+    extern "avr-interrupt" fn m() {}
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    extern "avr-non-blocking-interrupt" fn mu() {}
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+}
 
-fn main() {
-    foo();
+impl S {
+    extern "avr-interrupt" fn im() {}
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    extern "avr-non-blocking-interrupt" fn imu() {}
+    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
 }
+
+type TA = extern "avr-interrupt" fn();
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+type TAU = extern "avr-non-blocking-interrupt" fn();
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+
+extern "avr-interrupt" {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+extern "avr-non-blocking-interrupt" {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
index be7040e1491feba9eba13407a72a539be2c82f73..d017d03a3853ac4952b4ce9593202dfc52b68570 100644 (file)
 error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi-avr-interrupt.rs:4:8
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:11:8
    |
-LL | extern "avr-interrupt" fn foo() {}
+LL | extern "avr-non-blocking-interrupt" fn fu() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:13:8
+   |
+LL | extern "avr-interrupt" fn f() {}
    |        ^^^^^^^^^^^^^^^
    |
    = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:17:12
+   |
+LL |     extern "avr-interrupt" fn m();
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:19:12
+   |
+LL |     extern "avr-non-blocking-interrupt" fn mu();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:22:12
+   |
+LL |     extern "avr-interrupt" fn dm() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:24:12
+   |
+LL |     extern "avr-non-blocking-interrupt" fn dmu() {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:30:12
+   |
+LL |     extern "avr-interrupt" fn m() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:32:12
+   |
+LL |     extern "avr-non-blocking-interrupt" fn mu() {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:37:12
+   |
+LL |     extern "avr-interrupt" fn im() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:39:12
+   |
+LL |     extern "avr-non-blocking-interrupt" fn imu() {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:43:18
+   |
+LL | type TA = extern "avr-interrupt" fn();
+   |                  ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:45:19
+   |
+LL | type TAU = extern "avr-non-blocking-interrupt" fn();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:48:8
+   |
+LL | extern "avr-interrupt" {}
+   |        ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:50:8
+   |
+LL | extern "avr-non-blocking-interrupt" {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 440570c54943a2c7c0423c7ac0015b55fe2b257d..8b7d8066aa67434b6a790f58342c5527acdcdec9 100644 (file)
@@ -1,11 +1,34 @@
-// Test that the MSP430 interrupt ABI cannot be used when msp430_interrupt
-// feature gate is not used.
+// needs-llvm-components: msp430
+// compile-flags: --target=msp430-none-elf --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
 
-// ignore-riscv64 msp430 is not supported
+extern "msp430-interrupt" fn f() {}
+//~^ ERROR msp430-interrupt ABI is experimental
 
-extern "msp430-interrupt" fn foo() {}
-//~^ ERROR msp430-interrupt ABI is experimental and subject to change
+trait T {
+    extern "msp430-interrupt" fn m();
+    //~^ ERROR msp430-interrupt ABI is experimental
 
-fn main() {
-    foo();
+    extern "msp430-interrupt" fn dm() {}
+    //~^ ERROR msp430-interrupt ABI is experimental
 }
+
+struct S;
+impl T for S {
+    extern "msp430-interrupt" fn m() {}
+    //~^ ERROR msp430-interrupt ABI is experimental
+}
+
+impl S {
+    extern "msp430-interrupt" fn im() {}
+    //~^ ERROR msp430-interrupt ABI is experimental
+}
+
+type TA = extern "msp430-interrupt" fn();
+//~^ ERROR msp430-interrupt ABI is experimental
+
+extern "msp430-interrupt" {}
+//~^ ERROR msp430-interrupt ABI is experimental
index 554226bd2b962e272d7dfec1fbec7d3daf9dc44f..c19ec97896ba3a953664bb942151b2cd91f7d275 100644 (file)
@@ -1,12 +1,66 @@
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi-msp430-interrupt.rs:6:8
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:8:8
    |
-LL | extern "msp430-interrupt" fn foo() {}
+LL | extern "msp430-interrupt" fn f() {}
    |        ^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:12:12
+   |
+LL |     extern "msp430-interrupt" fn m();
+   |            ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:15:12
+   |
+LL |     extern "msp430-interrupt" fn dm() {}
+   |            ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:21:12
+   |
+LL |     extern "msp430-interrupt" fn m() {}
+   |            ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:26:12
+   |
+LL |     extern "msp430-interrupt" fn im() {}
+   |            ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:30:18
+   |
+LL | type TA = extern "msp430-interrupt" fn();
+   |                  ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:33:8
+   |
+LL | extern "msp430-interrupt" {}
+   |        ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
new file mode 100644 (file)
index 0000000..7c3e4d1
--- /dev/null
@@ -0,0 +1,28 @@
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
+trait Tr {
+    extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
+    extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
+}
+
+struct S;
+
+// Methods in trait impl
+impl Tr for S {
+    extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
+}
+
+// Methods in inherent impl
+impl S {
+    extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
+}
+
+type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
+
+extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
diff --git a/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
new file mode 100644 (file)
index 0000000..3b727a7
--- /dev/null
@@ -0,0 +1,66 @@
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:8:8
+   |
+LL | extern "x86-interrupt" fn f7() {}
+   |        ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:10:12
+   |
+LL |     extern "x86-interrupt" fn m7();
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:11:12
+   |
+LL |     extern "x86-interrupt" fn dm7() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:18:12
+   |
+LL |     extern "x86-interrupt" fn m7() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:23:12
+   |
+LL |     extern "x86-interrupt" fn im7() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:26:18
+   |
+LL | type A7 = extern "x86-interrupt" fn();
+   |                  ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-x86-interrupt.rs:28:8
+   |
+LL | extern "x86-interrupt" {}
+   |        ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 49cf2e158edfc099b814c4a7a98e7b1efb2dccc3..855263595d0ba5672b187e5df29b83e0516cf4bb 100644 (file)
@@ -1,27 +1,21 @@
-// only-x86_64
 // gate-test-intrinsics
 // gate-test-platform_intrinsics
-// gate-test-abi_vectorcall
-// gate-test-abi_thiscall
-// gate-test-abi_ptx
-// gate-test-abi_x86_interrupt
-// gate-test-abi_amdgpu_kernel
 // gate-test-abi_efiapi
+// compile-flags: --crate-type=rlib
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
 
 // Functions
 extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
                                    //~^ ERROR intrinsic must be in
 extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
                                        //~^ ERROR intrinsic must be in
-extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
 extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
-extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
-extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
-extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
-extern "amdgpu-kernel" fn f9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
 extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change
-extern "wasm" fn f11() {} //~ ERROR wasm ABI is experimental and subject to change
 
 // Methods in trait definition
 trait Tr {
@@ -29,25 +23,11 @@ trait Tr {
                                      //~^ ERROR intrinsic must be in
     extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
                                          //~^ ERROR intrinsic must be in
-    extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change
-    extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
-    extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
-    extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
-    extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
-    extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
     extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change
-    extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change
 
-    extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-    extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
-    extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
-    extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
-    extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
-    extern "amdgpu-kernel" fn dm9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
     extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change
-    extern "wasm" fn dm11() {} //~ ERROR wasm ABI is experimental and subject to change
 }
 
 struct S;
@@ -58,15 +38,8 @@ extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
                                        //~^ ERROR intrinsic must be in
     extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
                                            //~^ ERROR intrinsic must be in
-    extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-    extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
-    extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
-    extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
-    extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
-    extern "amdgpu-kernel" fn m9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
     extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change
-    extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change
 }
 
 // Methods in inherent impl
@@ -75,41 +48,18 @@ extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
                                         //~^ ERROR intrinsic must be in
     extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
                                             //~^ ERROR intrinsic must be in
-    extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-    extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
-    extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
-    extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
-    extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
-    extern "amdgpu-kernel" fn im9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
     extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change
-    extern "wasm" fn im11() {} //~ ERROR wasm ABI is experimental and subject to change
 }
 
 // Function pointer types
 type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
 type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
-type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
 type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change
-type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
-type A6 = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental and subject to change
-type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
-type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
-type A9 = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
 type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change
-type A11 = extern "wasm" fn(); //~ ERROR wasm ABI is experimental and subject to change
 
 // Foreign modules
 extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
 extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
-extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
 extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
-extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
-extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
-extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
-extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
-extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
 extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change
-extern "wasm" {} //~ ERROR wasm ABI is experimental and subject to change
-
-fn main() {}
index 078d21ad36f90f1a9cb6a630fb630e8f253e3eb0..bcca39c8fb808c63b73a7cbba084d6dcb85216ef 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:12:8
+  --> $DIR/feature-gate-abi.rs:13:8
    |
 LL | extern "rust-intrinsic" fn f1() {}
    |        ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:14:8
+  --> $DIR/feature-gate-abi.rs:15:8
    |
 LL | extern "platform-intrinsic" fn f2() {}
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -15,14 +15,6 @@ LL | extern "platform-intrinsic" fn f2() {}
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:16:8
-   |
-LL | extern "vectorcall" fn f3() {}
-   |        ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:17:8
    |
@@ -32,52 +24,8 @@ LL | extern "rust-call" fn f4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:18:8
-   |
-LL | extern "msp430-interrupt" fn f5() {}
-   |        ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:19:8
-   |
-LL | extern "ptx-kernel" fn f6() {}
-   |        ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:20:8
-   |
-LL | extern "x86-interrupt" fn f7() {}
-   |        ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:21:8
-   |
-LL | extern "thiscall" fn f8() {}
-   |        ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:22:8
-   |
-LL | extern "amdgpu-kernel" fn f9() {}
-   |        ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:23:8
+  --> $DIR/feature-gate-abi.rs:18:8
    |
 LL | extern "efiapi" fn f10() {}
    |        ^^^^^^^^
@@ -85,17 +33,8 @@ LL | extern "efiapi" fn f10() {}
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:24:8
-   |
-LL | extern "wasm" fn f11() {}
-   |        ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:28:12
+  --> $DIR/feature-gate-abi.rs:22:12
    |
 LL |     extern "rust-intrinsic" fn m1();
    |            ^^^^^^^^^^^^^^^^
@@ -103,7 +42,7 @@ LL |     extern "rust-intrinsic" fn m1();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:30:12
+  --> $DIR/feature-gate-abi.rs:24:12
    |
 LL |     extern "platform-intrinsic" fn m2();
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -111,16 +50,8 @@ LL |     extern "platform-intrinsic" fn m2();
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:32:12
-   |
-LL |     extern "vectorcall" fn m3();
-   |            ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:33:12
+  --> $DIR/feature-gate-abi.rs:26:12
    |
 LL |     extern "rust-call" fn m4(_: ());
    |            ^^^^^^^^^^^
@@ -128,52 +59,8 @@ LL |     extern "rust-call" fn m4(_: ());
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:34:12
-   |
-LL |     extern "msp430-interrupt" fn m5();
-   |            ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:35:12
-   |
-LL |     extern "ptx-kernel" fn m6();
-   |            ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:36:12
-   |
-LL |     extern "x86-interrupt" fn m7();
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:37:12
-   |
-LL |     extern "thiscall" fn m8();
-   |            ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:38:12
-   |
-LL |     extern "amdgpu-kernel" fn m9();
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:39:12
+  --> $DIR/feature-gate-abi.rs:27:12
    |
 LL |     extern "efiapi" fn m10();
    |            ^^^^^^^^
@@ -181,25 +68,8 @@ LL |     extern "efiapi" fn m10();
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:40:12
-   |
-LL |     extern "wasm" fn m11() {}
-   |            ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:42:12
-   |
-LL |     extern "vectorcall" fn dm3() {}
-   |            ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:43:12
+  --> $DIR/feature-gate-abi.rs:29:12
    |
 LL |     extern "rust-call" fn dm4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -207,52 +77,8 @@ LL |     extern "rust-call" fn dm4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:44:12
-   |
-LL |     extern "msp430-interrupt" fn dm5() {}
-   |            ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:45:12
-   |
-LL |     extern "ptx-kernel" fn dm6() {}
-   |            ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:46:12
-   |
-LL |     extern "x86-interrupt" fn dm7() {}
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:47:12
-   |
-LL |     extern "thiscall" fn dm8() {}
-   |            ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:48:12
-   |
-LL |     extern "amdgpu-kernel" fn dm9() {}
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:49:12
+  --> $DIR/feature-gate-abi.rs:30:12
    |
 LL |     extern "efiapi" fn dm10() {}
    |            ^^^^^^^^
@@ -260,17 +86,8 @@ LL |     extern "efiapi" fn dm10() {}
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:50:12
-   |
-LL |     extern "wasm" fn dm11() {}
-   |            ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:57:12
+  --> $DIR/feature-gate-abi.rs:37:12
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -278,7 +95,7 @@ LL |     extern "rust-intrinsic" fn m1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:59:12
+  --> $DIR/feature-gate-abi.rs:39:12
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -286,16 +103,8 @@ LL |     extern "platform-intrinsic" fn m2() {}
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:61:12
-   |
-LL |     extern "vectorcall" fn m3() {}
-   |            ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:62:12
+  --> $DIR/feature-gate-abi.rs:41:12
    |
 LL |     extern "rust-call" fn m4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -303,52 +112,8 @@ LL |     extern "rust-call" fn m4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:63:12
-   |
-LL |     extern "msp430-interrupt" fn m5() {}
-   |            ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:64:12
-   |
-LL |     extern "ptx-kernel" fn m6() {}
-   |            ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:65:12
-   |
-LL |     extern "x86-interrupt" fn m7() {}
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:66:12
-   |
-LL |     extern "thiscall" fn m8() {}
-   |            ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:67:12
-   |
-LL |     extern "amdgpu-kernel" fn m9() {}
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:68:12
+  --> $DIR/feature-gate-abi.rs:42:12
    |
 LL |     extern "efiapi" fn m10() {}
    |            ^^^^^^^^
@@ -356,17 +121,8 @@ LL |     extern "efiapi" fn m10() {}
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:69:12
-   |
-LL |     extern "wasm" fn m11() {}
-   |            ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:74:12
+  --> $DIR/feature-gate-abi.rs:47:12
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -374,7 +130,7 @@ LL |     extern "rust-intrinsic" fn im1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:76:12
+  --> $DIR/feature-gate-abi.rs:49:12
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -382,16 +138,8 @@ LL |     extern "platform-intrinsic" fn im2() {}
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:78:12
-   |
-LL |     extern "vectorcall" fn im3() {}
-   |            ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:79:12
+  --> $DIR/feature-gate-abi.rs:51:12
    |
 LL |     extern "rust-call" fn im4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -399,52 +147,8 @@ LL |     extern "rust-call" fn im4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:80:12
-   |
-LL |     extern "msp430-interrupt" fn im5() {}
-   |            ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:81:12
-   |
-LL |     extern "ptx-kernel" fn im6() {}
-   |            ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:82:12
-   |
-LL |     extern "x86-interrupt" fn im7() {}
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:83:12
-   |
-LL |     extern "thiscall" fn im8() {}
-   |            ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:84:12
-   |
-LL |     extern "amdgpu-kernel" fn im9() {}
-   |            ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:85:12
+  --> $DIR/feature-gate-abi.rs:52:12
    |
 LL |     extern "efiapi" fn im10() {}
    |            ^^^^^^^^
@@ -452,17 +156,8 @@ LL |     extern "efiapi" fn im10() {}
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:86:12
-   |
-LL |     extern "wasm" fn im11() {}
-   |            ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:90:18
+  --> $DIR/feature-gate-abi.rs:56:18
    |
 LL | type A1 = extern "rust-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^
@@ -470,7 +165,7 @@ LL | type A1 = extern "rust-intrinsic" fn();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:91:18
+  --> $DIR/feature-gate-abi.rs:57:18
    |
 LL | type A2 = extern "platform-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^^^^^
@@ -478,16 +173,8 @@ LL | type A2 = extern "platform-intrinsic" fn();
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:92:18
-   |
-LL | type A3 = extern "vectorcall" fn();
-   |                  ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:93:18
+  --> $DIR/feature-gate-abi.rs:58:18
    |
 LL | type A4 = extern "rust-call" fn(_: ());
    |                  ^^^^^^^^^^^
@@ -495,52 +182,8 @@ LL | type A4 = extern "rust-call" fn(_: ());
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:94:18
-   |
-LL | type A5 = extern "msp430-interrupt" fn();
-   |                  ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:95:18
-   |
-LL | type A6 = extern "ptx-kernel" fn();
-   |                  ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:96:18
-   |
-LL | type A7 = extern "x86-interrupt" fn();
-   |                  ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:97:18
-   |
-LL | type A8 = extern "thiscall" fn();
-   |                  ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:98:18
-   |
-LL | type A9 = extern "amdgpu-kernel" fn();
-   |                  ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:99:19
+  --> $DIR/feature-gate-abi.rs:59:19
    |
 LL | type A10 = extern "efiapi" fn();
    |                   ^^^^^^^^
@@ -548,17 +191,8 @@ LL | type A10 = extern "efiapi" fn();
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:100:19
-   |
-LL | type A11 = extern "wasm" fn();
-   |                   ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:103:8
+  --> $DIR/feature-gate-abi.rs:62:8
    |
 LL | extern "rust-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^
@@ -566,7 +200,7 @@ LL | extern "rust-intrinsic" {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:104:8
+  --> $DIR/feature-gate-abi.rs:63:8
    |
 LL | extern "platform-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -574,16 +208,8 @@ LL | extern "platform-intrinsic" {}
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
-error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:105:8
-   |
-LL | extern "vectorcall" {}
-   |        ^^^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:106:8
+  --> $DIR/feature-gate-abi.rs:64:8
    |
 LL | extern "rust-call" {}
    |        ^^^^^^^^^^^
@@ -591,52 +217,8 @@ LL | extern "rust-call" {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:107:8
-   |
-LL | extern "msp430-interrupt" {}
-   |        ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
-   = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:108:8
-   |
-LL | extern "ptx-kernel" {}
-   |        ^^^^^^^^^^^^
-   |
-   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
-   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:109:8
-   |
-LL | extern "x86-interrupt" {}
-   |        ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
-   = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:110:8
-   |
-LL | extern "thiscall" {}
-   |        ^^^^^^^^^^
-   |
-   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:111:8
-   |
-LL | extern "amdgpu-kernel" {}
-   |        ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
-   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
 error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:112:8
+  --> $DIR/feature-gate-abi.rs:65:8
    |
 LL | extern "efiapi" {}
    |        ^^^^^^^^
@@ -644,63 +226,54 @@ LL | extern "efiapi" {}
    = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
    = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
 
-error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:113:8
-   |
-LL | extern "wasm" {}
-   |        ^^^^^^
-   |
-   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
-   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:28:32
+  --> $DIR/feature-gate-abi.rs:22:32
    |
 LL |     extern "rust-intrinsic" fn m1();
    |                                ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:30:36
+  --> $DIR/feature-gate-abi.rs:24:36
    |
 LL |     extern "platform-intrinsic" fn m2();
    |                                    ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:12:33
+  --> $DIR/feature-gate-abi.rs:13:33
    |
 LL | extern "rust-intrinsic" fn f1() {}
    |                                 ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:14:37
+  --> $DIR/feature-gate-abi.rs:15:37
    |
 LL | extern "platform-intrinsic" fn f2() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:57:37
+  --> $DIR/feature-gate-abi.rs:37:37
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:59:41
+  --> $DIR/feature-gate-abi.rs:39:41
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |                                         ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:74:38
+  --> $DIR/feature-gate-abi.rs:47:38
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |                                      ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:76:42
+  --> $DIR/feature-gate-abi.rs:49:42
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |                                          ^^
 
-error: aborting due to 83 previous errors
+error: aborting due to 34 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs b/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs
new file mode 100644 (file)
index 0000000..465b81d
--- /dev/null
@@ -0,0 +1,30 @@
+// compile-flags: --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "amdgpu-kernel" fn fu() {} //~ ERROR amdgpu-kernel ABI is experimental
+//~^ ERROR is not a supported ABI
+
+trait T {
+    extern "amdgpu-kernel" fn mu(); //~ ERROR amdgpu-kernel ABI is experimental
+    extern "amdgpu-kernel" fn dmu() {} //~ ERROR amdgpu-kernel ABI is experimental
+    //~^ ERROR is not a supported ABI
+}
+
+struct S;
+impl T for S {
+    extern "amdgpu-kernel" fn mu() {} //~ ERROR amdgpu-kernel ABI is experimental
+    //~^ ERROR is not a supported ABI
+}
+
+impl S {
+    extern "amdgpu-kernel" fn imu() {} //~ ERROR amdgpu-kernel ABI is experimental
+    //~^ ERROR is not a supported ABI
+}
+
+type TAU = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental
+
+extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental
+//~^ ERROR is not a supported ABI
diff --git a/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr b/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr
new file mode 100644 (file)
index 0000000..c89ab7b
--- /dev/null
@@ -0,0 +1,97 @@
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:8
+   |
+LL | extern "amdgpu-kernel" fn fu() {}
+   |        ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:11:12
+   |
+LL |     extern "amdgpu-kernel" fn mu();
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:12
+   |
+LL |     extern "amdgpu-kernel" fn dmu() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:12
+   |
+LL |     extern "amdgpu-kernel" fn mu() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:12
+   |
+LL |     extern "amdgpu-kernel" fn imu() {}
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:27:19
+   |
+LL | type TAU = extern "amdgpu-kernel" fn();
+   |                   ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:8
+   |
+LL | extern "amdgpu-kernel" {}
+   |        ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+   = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:1
+   |
+LL | extern "amdgpu-kernel" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:1
+   |
+LL | extern "amdgpu-kernel" fn fu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:5
+   |
+LL |     extern "amdgpu-kernel" fn dmu() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:5
+   |
+LL |     extern "amdgpu-kernel" fn mu() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:5
+   |
+LL |     extern "amdgpu-kernel" fn imu() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0570, E0658.
+For more information about an error, try `rustc --explain E0570`.
diff --git a/src/test/ui/feature-gates/feature-gate-abi_ptx.rs b/src/test/ui/feature-gates/feature-gate-abi_ptx.rs
new file mode 100644 (file)
index 0000000..e340564
--- /dev/null
@@ -0,0 +1,26 @@
+// needs-llvm-components: nvptx
+// compile-flags: --target=nvptx64-nvidia-cuda --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "ptx-kernel" fn fu() {} //~ ERROR PTX ABIs are experimental
+
+trait T {
+    extern "ptx-kernel" fn mu(); //~ ERROR PTX ABIs are experimental
+    extern "ptx-kernel" fn dmu() {} //~ ERROR PTX ABIs are experimental
+}
+
+struct S;
+impl T for S {
+    extern "ptx-kernel" fn mu() {} //~ ERROR PTX ABIs are experimental
+}
+
+impl S {
+    extern "ptx-kernel" fn imu() {} //~ ERROR PTX ABIs are experimental
+}
+
+type TAU = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental
+
+extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental
diff --git a/src/test/ui/feature-gates/feature-gate-abi_ptx.stderr b/src/test/ui/feature-gates/feature-gate-abi_ptx.stderr
new file mode 100644 (file)
index 0000000..40782d3
--- /dev/null
@@ -0,0 +1,66 @@
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:8:8
+   |
+LL | extern "ptx-kernel" fn fu() {}
+   |        ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:11:12
+   |
+LL |     extern "ptx-kernel" fn mu();
+   |            ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:12:12
+   |
+LL |     extern "ptx-kernel" fn dmu() {}
+   |            ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:17:12
+   |
+LL |     extern "ptx-kernel" fn mu() {}
+   |            ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:21:12
+   |
+LL |     extern "ptx-kernel" fn imu() {}
+   |            ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:24:19
+   |
+LL | type TAU = extern "ptx-kernel" fn();
+   |                   ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi_ptx.rs:26:8
+   |
+LL | extern "ptx-kernel" {}
+   |        ^^^^^^^^^^^^
+   |
+   = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+   = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index b49cc40800f03660cd5ca2e0ff2d1636ac0a53af..80ebcabcf8df8d4f86e6669999b6a68e80ce3aa7 100644 (file)
@@ -4,7 +4,7 @@ error[E0658]: usage of qualified paths in this context is experimental
 LL |     let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
    |         ^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+   = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
    = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
 
 error[E0658]: usage of qualified paths in this context is experimental
@@ -13,7 +13,7 @@ error[E0658]: usage of qualified paths in this context is experimental
 LL |     let _ = <Foo as A>::Assoc { br: 2 };
    |             ^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+   = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
    = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
 
 error[E0658]: usage of qualified paths in this context is experimental
@@ -22,7 +22,7 @@ error[E0658]: usage of qualified paths in this context is experimental
 LL |     let <E>::V(..) = E::V(0);
    |         ^^^^^^
    |
-   = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+   = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
    = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-vectorcall.rs b/src/test/ui/feature-gates/feature-gate-vectorcall.rs
new file mode 100644 (file)
index 0000000..5a6c6d2
--- /dev/null
@@ -0,0 +1,31 @@
+// gate-test-abi_vectorcall
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that the "vectorcall-unwind" ABI is feature-gated, and cannot be used when
+// the `c_unwind` feature gate is not used.
+
+extern "vectorcall" fn f() {} //~ ERROR vectorcall is experimental
+
+trait T {
+    extern "vectorcall" fn m(); //~ ERROR vectorcall is experimental
+
+    extern "vectorcall" fn dm() {} //~ ERROR vectorcall is experimental
+}
+
+struct S;
+impl T for S {
+    extern "vectorcall" fn m() {} //~ ERROR vectorcall is experimental
+}
+
+impl S {
+    extern "vectorcall" fn im() {} //~ ERROR vectorcall is experimental
+}
+
+type TA = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental
+
+extern "vectorcall" {} //~ ERROR vectorcall is experimental
diff --git a/src/test/ui/feature-gates/feature-gate-vectorcall.stderr b/src/test/ui/feature-gates/feature-gate-vectorcall.stderr
new file mode 100644 (file)
index 0000000..55ee76e
--- /dev/null
@@ -0,0 +1,59 @@
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:12:8
+   |
+LL | extern "vectorcall" fn f() {}
+   |        ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:15:12
+   |
+LL |     extern "vectorcall" fn m();
+   |            ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:17:12
+   |
+LL |     extern "vectorcall" fn dm() {}
+   |            ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:22:12
+   |
+LL |     extern "vectorcall" fn m() {}
+   |            ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:26:12
+   |
+LL |     extern "vectorcall" fn im() {}
+   |            ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:29:18
+   |
+LL | type TA = extern "vectorcall" fn();
+   |                  ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-vectorcall.rs:31:8
+   |
+LL | extern "vectorcall" {}
+   |        ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 8c8de0763658e21274262f7ab3660ea08fadd309..222c88daf94843d060563ce33e46cc4046848c8f 100644 (file)
@@ -1,7 +1,26 @@
-extern "wasm" fn foo() {
-    //~^ ERROR: wasm ABI is experimental and subject to change
+// needs-llvm-components: webassembly
+// compile-flags: --target=wasm32-unknown-unknown --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "wasm" fn fu() {} //~ ERROR wasm ABI is experimental
+
+trait T {
+    extern "wasm" fn mu(); //~ ERROR wasm ABI is experimental
+    extern "wasm" fn dmu() {} //~ ERROR wasm ABI is experimental
+}
+
+struct S;
+impl T for S {
+    extern "wasm" fn mu() {} //~ ERROR wasm ABI is experimental
 }
 
-fn main() {
-    foo();
+impl S {
+    extern "wasm" fn imu() {} //~ ERROR wasm ABI is experimental
 }
+
+type TAU = extern "wasm" fn(); //~ ERROR wasm ABI is experimental
+
+extern "wasm" {} //~ ERROR wasm ABI is experimental
index c4113fd6af979c138ede020105e50d779a6e98f5..0140002e350a36e345608b61922b3ac7a726f6a5 100644 (file)
@@ -1,12 +1,66 @@
 error[E0658]: wasm ABI is experimental and subject to change
-  --> $DIR/feature-gate-wasm_abi.rs:1:8
+  --> $DIR/feature-gate-wasm_abi.rs:8:8
    |
-LL | extern "wasm" fn foo() {
+LL | extern "wasm" fn fu() {}
    |        ^^^^^^
    |
    = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
    = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: wasm ABI is experimental and subject to change
+  --> $DIR/feature-gate-wasm_abi.rs:11:12
+   |
+LL |     extern "wasm" fn mu();
+   |            ^^^^^^
+   |
+   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+  --> $DIR/feature-gate-wasm_abi.rs:12:12
+   |
+LL |     extern "wasm" fn dmu() {}
+   |            ^^^^^^
+   |
+   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+  --> $DIR/feature-gate-wasm_abi.rs:17:12
+   |
+LL |     extern "wasm" fn mu() {}
+   |            ^^^^^^
+   |
+   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+  --> $DIR/feature-gate-wasm_abi.rs:21:12
+   |
+LL |     extern "wasm" fn imu() {}
+   |            ^^^^^^
+   |
+   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+  --> $DIR/feature-gate-wasm_abi.rs:24:19
+   |
+LL | type TAU = extern "wasm" fn();
+   |                   ^^^^^^
+   |
+   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+  --> $DIR/feature-gate-wasm_abi.rs:26:8
+   |
+LL | extern "wasm" {}
+   |        ^^^^^^
+   |
+   = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+   = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 6c97a807b052b34890f0e3ff43d303c8aedc1063..b30e9a47a13e8bc4a76d13ae3208fd458cad0445 100644 (file)
@@ -16,13 +16,13 @@ fn main() {
 
 fn named_argument_takes_precedence_to_captured() {
     let foo = "captured";
-    let s = format!("{foo}", foo="named");
+    let s = format!("{foo}", foo = "named");
     assert_eq!(&s, "named");
 
-    let s = format!("{foo}-{foo}-{foo}", foo="named");
+    let s = format!("{foo}-{foo}-{foo}", foo = "named");
     assert_eq!(&s, "named-named-named");
 
-    let s = format!("{}-{bar}-{foo}", "positional", bar="named");
+    let s = format!("{}-{bar}-{foo}", "positional", bar = "named");
     assert_eq!(&s, "positional-named-captured");
 }
 
@@ -42,10 +42,11 @@ fn panic_with_single_argument_does_not_get_formatted() {
     // RFC #2795 suggests that this may need to change so that captured arguments are formatted.
     // For stability reasons this will need to part of an edition change.
 
-    #[allow(non_fmt_panic)]
+    #[allow(non_fmt_panics)]
     let msg = std::panic::catch_unwind(|| {
         panic!("{foo}");
-    }).unwrap_err();
+    })
+    .unwrap_err();
 
     assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}"))
 }
@@ -55,8 +56,9 @@ fn panic_with_multiple_arguments_is_formatted() {
     let foo = "captured";
 
     let msg = std::panic::catch_unwind(|| {
-        panic!("{}-{bar}-{foo}", "positional", bar="named");
-    }).unwrap_err();
+        panic!("{}-{bar}-{foo}", "positional", bar = "named");
+    })
+    .unwrap_err();
 
     assert_eq!(msg.downcast_ref::<String>(), Some(&"positional-named-captured".to_string()))
 }
index 78100318dc33ad1fdf640f0bd8b04e9d53448fda..bd0d27ff3e9ac50c2a6a9b1bbc9e05f0d27b9ac4 100644 (file)
@@ -12,7 +12,7 @@ note: generator is not `Send` as this value is used across a yield
   --> $DIR/generator-print-verbose-1.rs:35:9
    |
 LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[70c9]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
 LL |     };
@@ -30,10 +30,10 @@ LL |     require_send(send_gen);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
    = note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
-   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
-   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])`
-   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}`
-   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]`
+   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[70c9]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), [])`
+   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}`
+   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}]`
 
 error: aborting due to 2 previous errors
 
index 1733012b9c54fb12283dcae2986fb0c82b1def0f..9281dda678ddd51ab73bac4675bcce4860065881 100644 (file)
@@ -11,12 +11,8 @@ fn foo() {
     //~| ERROR range-to patterns with `...` are not allowed
     if let ..5 = 0 {}
     //~^ ERROR half-open range patterns are unstable
-    if let 5.. = 0 {}
-    //~^ ERROR half-open range patterns are unstable
     if let 5..= = 0 {}
-    //~^ ERROR half-open range patterns are unstable
-    //~| ERROR inclusive range with no end
+    //~^ ERROR inclusive range with no end
     if let 5... = 0 {}
-    //~^ ERROR half-open range patterns are unstable
-    //~| ERROR inclusive range with no end
+    //~^ ERROR inclusive range with no end
 }
index 62d54463a433ce95f11aa28fa88182d57aca57e8..a04883ae147644643eeee677d5c71606b4312667 100644 (file)
@@ -5,7 +5,7 @@ LL |     if let ...5 = 0 {}
    |            ^^^ help: use `..=` instead
 
 error[E0586]: inclusive range with no end
-  --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
+  --> $DIR/feature-gate-half-open-range-patterns.rs:14:13
    |
 LL |     if let 5..= = 0 {}
    |             ^^^ help: use `..` instead
@@ -13,7 +13,7 @@ LL |     if let 5..= = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/feature-gate-half-open-range-patterns.rs:19:13
+  --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
    |
 LL |     if let 5... = 0 {}
    |             ^^^ help: use `..` instead
@@ -47,34 +47,7 @@ LL |     if let ..5 = 0 {}
    = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
    = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
 
-error[E0658]: half-open range patterns are unstable
-  --> $DIR/feature-gate-half-open-range-patterns.rs:14:12
-   |
-LL |     if let 5.. = 0 {}
-   |            ^^^
-   |
-   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
-   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error[E0658]: half-open range patterns are unstable
-  --> $DIR/feature-gate-half-open-range-patterns.rs:16:12
-   |
-LL |     if let 5..= = 0 {}
-   |            ^^^^
-   |
-   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
-   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error[E0658]: half-open range patterns are unstable
-  --> $DIR/feature-gate-half-open-range-patterns.rs:19:12
-   |
-LL |     if let 5... = 0 {}
-   |            ^^^^
-   |
-   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
-   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error: aborting due to 9 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0586, E0658.
 For more information about an error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs
new file mode 100644 (file)
index 0000000..4f478a6
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+#![allow(incomplete_features)]
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+#![feature(inline_const)]
+
+fn main() {
+    let mut if_lettable = vec![];
+    let mut first_or = vec![];
+    let mut or_two = vec![];
+    let mut range_from = vec![];
+    let mut bottom = vec![];
+
+    for x in -9 + 1..=(9 - 2) {
+        if let -1..=0 | 2..3 | 4 = x {
+            if_lettable.push(x)
+        }
+        match x {
+            1 | -3..0 => first_or.push(x),
+            y @ (0..5 | 6) => or_two.push(y),
+            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+            y @ -5.. => range_from.push(y),
+            y @ ..-7 => assert_eq!(y, -8),
+            y => bottom.push(y),
+        }
+    }
+    assert_eq!(if_lettable, [-1, 0, 2, 4]);
+    assert_eq!(first_or, [-3, -2, -1, 1]);
+    assert_eq!(or_two, [0, 2, 3, 4, 6]);
+    assert_eq!(range_from, [-5, -4, 7]);
+    assert_eq!(bottom, [-7, -6]);
+}
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs
new file mode 100644 (file)
index 0000000..5535399
--- /dev/null
@@ -0,0 +1,29 @@
+fn main() {
+    let mut if_lettable = Vec::<i32>::new();
+    let mut first_or = Vec::<i32>::new();
+    let mut or_two = Vec::<i32>::new();
+    let mut range_from = Vec::<i32>::new();
+    let mut bottom = Vec::<i32>::new();
+    let mut errors_only = Vec::<i32>::new();
+
+    for x in -9 + 1..=(9 - 2) {
+        if let n @ 2..3|4 = x {
+            //~^ error: variable `n` is not bound in all patterns
+            //~| exclusive range pattern syntax is experimental
+            errors_only.push(x);
+        } else if let 2..3 | 4 = x {
+            //~^ exclusive range pattern syntax is experimental
+            if_lettable.push(x);
+        }
+        match x as i32 {
+            0..5+1 => errors_only.push(x),
+            //~^ error: expected one of `=>`, `if`, or `|`, found `+`
+            1 | -3..0 => first_or.push(x),
+            y @ (0..5 | 6) => or_two.push(y),
+            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+            y @ -5.. => range_from.push(y),
+            y @ ..-7 => assert_eq!(y, -8),
+            y => bottom.push(y),
+        }
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr
new file mode 100644 (file)
index 0000000..19ebcaf
--- /dev/null
@@ -0,0 +1,36 @@
+error: expected one of `=>`, `if`, or `|`, found `+`
+  --> $DIR/range_pat_interactions1.rs:19:17
+   |
+LL |             0..5+1 => errors_only.push(x),
+   |                 ^ expected one of `=>`, `if`, or `|`
+
+error[E0408]: variable `n` is not bound in all patterns
+  --> $DIR/range_pat_interactions1.rs:10:25
+   |
+LL |         if let n @ 2..3|4 = x {
+   |                -        ^ pattern doesn't bind `n`
+   |                |
+   |                variable not in all patterns
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:10:20
+   |
+LL |         if let n @ 2..3|4 = x {
+   |                    ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:14:23
+   |
+LL |         } else if let 2..3 | 4 = x {
+   |                       ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0408, E0658.
+For more information about an error, try `rustc --explain E0408`.
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs
new file mode 100644 (file)
index 0000000..4615ebd
--- /dev/null
@@ -0,0 +1,21 @@
+fn main() {
+    let mut first_or = Vec::<i32>::new();
+    let mut or_two = Vec::<i32>::new();
+    let mut range_from = Vec::<i32>::new();
+    let mut bottom = Vec::<i32>::new();
+    let mut errors_only = Vec::<i32>::new();
+
+    for x in -9 + 1..=(9 - 2) {
+        match x as i32 {
+            0..=(5+1) => errors_only.push(x),
+            //~^ error: inclusive range with no end
+            //~| error: expected one of `=>`, `if`, or `|`, found `(`
+            1 | -3..0 => first_or.push(x),
+            y @ (0..5 | 6) => or_two.push(y),
+            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+            y @ -5.. => range_from.push(y),
+            y @ ..-7 => assert_eq!(y, -8),
+            y => bottom.push(y),
+        }
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr
new file mode 100644 (file)
index 0000000..13a5542
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/range_pat_interactions2.rs:10:14
+   |
+LL |             0..=(5+1) => errors_only.push(x),
+   |              ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: expected one of `=>`, `if`, or `|`, found `(`
+  --> $DIR/range_pat_interactions2.rs:10:17
+   |
+LL |             0..=(5+1) => errors_only.push(x),
+   |                 ^ expected one of `=>`, `if`, or `|`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs
new file mode 100644 (file)
index 0000000..0afb512
--- /dev/null
@@ -0,0 +1,24 @@
+fn main() {
+    let mut first_or = Vec::<i32>::new();
+    let mut or_two = Vec::<i32>::new();
+    let mut range_from = Vec::<i32>::new();
+    let mut bottom = Vec::<i32>::new();
+
+    for x in -9 + 1..=(9 - 2) {
+        match x as i32 {
+            8.. => bottom.push(x),
+            1 | -3..0 => first_or.push(x),
+            //~^ exclusive range pattern syntax is experimental
+            y @ (0..5 | 6) => or_two.push(y),
+            //~^ exclusive range pattern syntax is experimental
+            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+            //~^ inline-const is experimental
+            //~| exclusive range pattern syntax is experimental
+            y @ -5.. => range_from.push(y),
+            y @ ..-7 => assert_eq!(y, -8),
+            //~^ half-open range patterns are unstable
+            //~| exclusive range pattern syntax is experimental
+            y => bottom.push(y),
+        }
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr
new file mode 100644 (file)
index 0000000..8278e7c
--- /dev/null
@@ -0,0 +1,57 @@
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/range_pat_interactions3.rs:18:17
+   |
+LL |             y @ ..-7 => assert_eq!(y, -8),
+   |                 ^^^^
+   |
+   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: inline-const is experimental
+  --> $DIR/range_pat_interactions3.rs:14:20
+   |
+LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+   |                    ^^^^^
+   |
+   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
+   = help: add `#![feature(inline_const)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions3.rs:10:17
+   |
+LL |             1 | -3..0 => first_or.push(x),
+   |                 ^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions3.rs:12:18
+   |
+LL |             y @ (0..5 | 6) => or_two.push(y),
+   |                  ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions3.rs:14:17
+   |
+LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+   |                 ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions3.rs:18:17
+   |
+LL |             y @ ..-7 => assert_eq!(y, -8),
+   |                 ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
new file mode 100644 (file)
index 0000000..2884a27
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+    let [a, b, c, rest @ ..] = xs;
+    // Consider the following example:
+    assert!(a == 13 && b == 1 && c == 5 && rest.len() == 5);
+
+    // What if we wanted to pull this apart without individually binding a, b, and c?
+    let [first_three @ ..3, rest @ 2..] = xs;
+    //~^ pattern requires 2 elements but array has 8
+    // This is somewhat unintuitive and makes slice patterns exceedingly verbose.
+    // We want to stabilize half-open RangeFrom (`X..`) patterns
+    // but without banning us from using them for a more efficient slice pattern syntax.
+}
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr
new file mode 100644 (file)
index 0000000..ec3472a
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0527]: pattern requires 2 elements but array has 8
+  --> $DIR/slice_pattern_syntax_problem0.rs:11:9
+   |
+LL |     let [first_three @ ..3, rest @ 2..] = xs;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0527`.
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
new file mode 100644 (file)
index 0000000..9e289b5
--- /dev/null
@@ -0,0 +1,9 @@
+// Instead of allowing the previous case, maintain the feature gate for slice patterns for now.
+fn main() {
+    let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+    let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+    //~^ `X..` patterns in slices are experimental
+    //~| half-open range patterns are unstable
+    //~| exclusive range pattern syntax is experimental
+    //~| exclusive range pattern syntax is experimental
+}
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
new file mode 100644 (file)
index 0000000..eadaf87
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/slice_pattern_syntax_problem1.rs:4:23
+   |
+LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+   |                       ^^^
+   |
+   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: `X..` patterns in slices are experimental
+  --> $DIR/slice_pattern_syntax_problem1.rs:4:10
+   |
+LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+   |          ^^^^^^^
+   |
+   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/slice_pattern_syntax_problem1.rs:4:23
+   |
+LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+   |                       ^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/slice_pattern_syntax_problem1.rs:4:32
+   |
+LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+   |                                ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs
new file mode 100644 (file)
index 0000000..6e7df30
--- /dev/null
@@ -0,0 +1,10 @@
+// run-pass
+
+fn main() {
+    let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+    if let [3..=14, ..] = xs {
+        /* this variant must pass for now, unfortunately.
+         * This test is included here to help inform a future plan for these.
+         */
+    };
+}
index ae2857d505e6028c29cefad9abf6e87cae4f4c92..84ca046212dc556395a75a1070cc2143b192836f 100644 (file)
@@ -20,7 +20,7 @@ fn y /* 0#0 */() { }
 /*
 Expansions:
 0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
-1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "foo", proc_macro: false }
+1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo")
 
 SyntaxContexts:
 #0: parent: #0, outer_mark: (ExpnId(0), Opaque)
diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs
new file mode 100644 (file)
index 0000000..a205a87
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(core_intrinsics)]
+#![feature(const_intrinsic_raw_eq)]
+#![deny(const_err)]
+
+const BAD_RAW_EQ_CALL: bool = unsafe {
+    std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
+//~^ ERROR evaluation of constant value failed
+};
+
+pub fn main() {
+}
diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr
new file mode 100644 (file)
index 0000000..3a1b090
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/intrinsic-raw_eq-const-padding.rs:6:5
+   |
+LL |     std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading 4 bytes of memory starting at alloc2, but 1 byte is uninitialized starting at alloc2+0x1, and this operation requires initialized memory
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs b/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs
new file mode 100644 (file)
index 0000000..8ea9546
--- /dev/null
@@ -0,0 +1,27 @@
+// run-pass
+
+#![feature(core_intrinsics)]
+#![feature(const_intrinsic_raw_eq)]
+#![deny(const_err)]
+
+pub fn main() {
+    use std::intrinsics::raw_eq;
+
+    const RAW_EQ_I32_TRUE: bool = unsafe { raw_eq(&42_i32, &42) };
+    assert!(RAW_EQ_I32_TRUE);
+
+    const RAW_EQ_I32_FALSE: bool = unsafe { raw_eq(&4_i32, &2) };
+    assert!(!RAW_EQ_I32_FALSE);
+
+    const RAW_EQ_CHAR_TRUE: bool = unsafe { raw_eq(&'a', &'a') };
+    assert!(RAW_EQ_CHAR_TRUE);
+
+    const RAW_EQ_CHAR_FALSE: bool = unsafe { raw_eq(&'a', &'A') };
+    assert!(!RAW_EQ_CHAR_FALSE);
+
+    const RAW_EQ_ARRAY_TRUE: bool = unsafe { raw_eq(&[13_u8, 42], &[13, 42]) };
+    assert!(RAW_EQ_ARRAY_TRUE);
+
+    const RAW_EQ_ARRAY_FALSE: bool = unsafe { raw_eq(&[13_u8, 42], &[42, 13]) };
+    assert!(!RAW_EQ_ARRAY_FALSE);
+}
index 1c2229fb9eae4f9258ff8505ba305130a2138ba5..77355f0d7c994423a142ceeb4cf87963def7cbcd 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
     const X: u32 = 1;
-    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
     println!("{}", Y);
 }
index 52df558bfce5e7c85628da8d428064524c581144..432e9a6518765d1e2848f8bc1003405d634a234b 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/issue-18294.rs:3:31
    |
 LL |     const Y: usize = unsafe { &X as *const u32 as usize };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index 5b95a7379135556a855c37a4d8033f45abc17b96..9d7072f1665d1520985eabbfbde2df995efa76e6 100644 (file)
@@ -10,47 +10,27 @@ fn main() {
     match x {
         5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
                    //~| WARNING hard error
-                   //~| ERROR floating-point types cannot be used in patterns
-                   //~| WARNING this was previously accepted by the compiler but is being
         5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
-                      //~| ERROR floating-point types cannot be used in patterns
-                      //~| WARNING hard error
                       //~| WARNING hard error
         -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                    //~| ERROR floating-point types cannot be used in patterns
-                    //~| WARNING hard error
                     //~| WARNING hard error
         1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
                            //~| WARNING hard error
                            //~| ERROR floating-point types cannot be used in patterns
                            //~| WARNING hard error
-                           //~| ERROR floating-point types cannot be used in patterns
-                           //~| WARNING hard error
-                           //~| ERROR floating-point types cannot be used in patterns
-                           //~| WARNING hard error
         39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                             //~| ERROR floating-point types cannot be used in patterns
-                             //~| WARNING hard error
-                             //~| ERROR floating-point types cannot be used in patterns
                              //~| ERROR floating-point types cannot be used in patterns
                              //~| WARNING hard error
                              //~| WARNING hard error
-                             //~| WARNING hard error
 
         ..71.0 => {}
         //~^ ERROR floating-point types cannot be used in patterns
-        //~| ERROR floating-point types cannot be used in patterns
-        //~| WARNING hard error
         //~| WARNING this was previously accepted by the compiler
         ..=72.0 => {}
         //~^ ERROR floating-point types cannot be used in patterns
-        //~| ERROR floating-point types cannot be used in patterns
-        //~| WARNING hard error
         //~| WARNING this was previously accepted by the compiler
         71.0.. => {}
         //~^ ERROR floating-point types cannot be used in patterns
-        //~| ERROR floating-point types cannot be used in patterns
-        //~| WARNING hard error
         //~| WARNING this was previously accepted by the compiler
         _ => {},
     };
@@ -58,8 +38,6 @@ fn main() {
     // Same for tuples
     match (x, 5) {
         (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
-                         //~| ERROR floating-point types cannot be used
-                         //~| WARNING hard error
                          //~| WARNING hard error
         _ => {},
     }
@@ -67,8 +45,6 @@ fn main() {
     struct Foo { x: f32 };
     match (Foo { x }) {
         Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
-                              //~| ERROR floating-point types cannot be used
-                              //~| WARNING hard error
                               //~| WARNING hard error
         _ => {},
     }
index b6e57afcd1292c92495ba25df382477fa0d4371c..bf81c8d371c0b985fda0901b87964e78e242023f 100644 (file)
@@ -13,7 +13,7 @@ LL | #![forbid(illegal_floating_point_literal_pattern)]
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:15:9
+  --> $DIR/issue-41255.rs:13:9
    |
 LL |         5.0f32 => {},
    |         ^^^^^^
@@ -22,7 +22,7 @@ LL |         5.0f32 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:19:10
+  --> $DIR/issue-41255.rs:15:10
    |
 LL |         -5.0 => {},
    |          ^^^
@@ -31,7 +31,7 @@ LL |         -5.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:23:9
+  --> $DIR/issue-41255.rs:17:9
    |
 LL |         1.0 .. 33.0 => {},
    |         ^^^
@@ -40,7 +40,7 @@ LL |         1.0 .. 33.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:23:16
+  --> $DIR/issue-41255.rs:17:16
    |
 LL |         1.0 .. 33.0 => {},
    |                ^^^^
@@ -49,7 +49,7 @@ LL |         1.0 .. 33.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:31:9
+  --> $DIR/issue-41255.rs:21:9
    |
 LL |         39.0 ..= 70.0 => {},
    |         ^^^^
@@ -58,7 +58,7 @@ LL |         39.0 ..= 70.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:31:18
+  --> $DIR/issue-41255.rs:21:18
    |
 LL |         39.0 ..= 70.0 => {},
    |                  ^^^^
@@ -67,7 +67,7 @@ LL |         39.0 ..= 70.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:40:11
+  --> $DIR/issue-41255.rs:26:11
    |
 LL |         ..71.0 => {}
    |           ^^^^
@@ -76,7 +76,7 @@ LL |         ..71.0 => {}
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:45:12
+  --> $DIR/issue-41255.rs:29:12
    |
 LL |         ..=72.0 => {}
    |            ^^^^
@@ -85,7 +85,7 @@ LL |         ..=72.0 => {}
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:50:9
+  --> $DIR/issue-41255.rs:32:9
    |
 LL |         71.0.. => {}
    |         ^^^^
@@ -94,7 +94,7 @@ LL |         71.0.. => {}
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:60:10
+  --> $DIR/issue-41255.rs:40:10
    |
 LL |         (3.14, 1) => {},
    |          ^^^^
@@ -103,7 +103,7 @@ LL |         (3.14, 1) => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:69:18
+  --> $DIR/issue-41255.rs:47:18
    |
 LL |         Foo { x: 2.0 } => {},
    |                  ^^^
@@ -111,113 +111,5 @@ LL |         Foo { x: 2.0 } => {},
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:11:9
-   |
-LL |         5.0 => {},
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:15:9
-   |
-LL |         5.0f32 => {},
-   |         ^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:19:10
-   |
-LL |         -5.0 => {},
-   |          ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:23:9
-   |
-LL |         1.0 .. 33.0 => {},
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:23:16
-   |
-LL |         1.0 .. 33.0 => {},
-   |                ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:31:9
-   |
-LL |         39.0 ..= 70.0 => {},
-   |         ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:31:18
-   |
-LL |         39.0 ..= 70.0 => {},
-   |                  ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:40:11
-   |
-LL |         ..71.0 => {}
-   |           ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:45:12
-   |
-LL |         ..=72.0 => {}
-   |            ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:50:9
-   |
-LL |         71.0.. => {}
-   |         ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:60:10
-   |
-LL |         (3.14, 1) => {},
-   |          ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:69:18
-   |
-LL |         Foo { x: 2.0 } => {},
-   |                  ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 24 previous errors
+error: aborting due to 12 previous errors
 
index 96e50ba67991c62a91423fce16d9172b47d203a9..305f482e8c21def2ee306dbe25e310e2bb2d53ad 100644 (file)
@@ -7,7 +7,7 @@ LL |     match u.void {}
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-47412.rs:21:11
+  --> $DIR/issue-47412.rs:20:11
    |
 LL |     match *ptr {}
    |           ^^^^ dereference of raw pointer
index d395285eee0a03cf01a1c0a79b6e1e951874f8a1..df6d6e4222e8201b4054a4229bafb42281217ab1 100644 (file)
@@ -12,8 +12,7 @@ fn union_field() {
     union Union { unit: (), void: Void }
     let u = Union { unit: () };
     match u.void {}
-    //[mir]~^ ERROR access to union field is unsafe
-    // FIXME(thir-unsafeck): AccessToUnionField unimplemented
+    //~^ ERROR access to union field is unsafe
 }
 
 fn raw_ptr_deref() {
index 66a0cfcd710f034eb2ae7f88522af088583f802f..305f482e8c21def2ee306dbe25e310e2bb2d53ad 100644 (file)
@@ -1,11 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-47412.rs:14:11
+   |
+LL |     match u.void {}
+   |           ^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-47412.rs:21:11
+  --> $DIR/issue-47412.rs:20:11
    |
 LL |     match *ptr {}
    |           ^^^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
index 509060e1ad81bbed5acee50f2555f81b93ace98a..d634b8bf80079ce8f885c5ffea40b9455f52847e 100644 (file)
@@ -1,4 +1,4 @@
 fn main() {
     let ref my_ref @ _ = 0;
-    *my_ref = 0; //~ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
+    *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
 }
index c91083955b8205b30678ec9c4abc18d370113a8f..19f0223a357a53e1fee7727c77516654b4e3a158 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
   --> $DIR/issue-51244.rs:3:5
    |
 LL |     let ref my_ref @ _ = 0;
index 8eab7b2fa3ae9b215555e4633a4203d6619bee1b..54fd176de75f033f20935e787431d6a88d3be638 100644 (file)
@@ -3,10 +3,10 @@ fn main() {
     //~^ HELP consider changing this to be a mutable reference
     //~| SUGGESTION &mut 16
     *foo = 32;
-    //~^ ERROR cannot assign to `*foo` which is behind a `&` reference
+    //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
     let bar = foo;
     //~^ HELP consider changing this to be a mutable reference
     //~| SUGGESTION &mut i32
     *bar = 64;
-    //~^ ERROR cannot assign to `*bar` which is behind a `&` reference
+    //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
 }
index 3c208935f31f6ddeaebebc86d3d1b38633110a58..62bb462faa208b8ae61890000cdb7c0b2b159d33 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
   --> $DIR/issue-51515.rs:5:5
    |
 LL |     let foo = &16;
@@ -7,7 +7,7 @@ LL |     let foo = &16;
 LL |     *foo = 32;
    |     ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
   --> $DIR/issue-51515.rs:10:5
    |
 LL |     let bar = foo;
index 6d950c424e38178b605ffe099c35f453d7950482..0260caa82cb1d33a1cb0f17f9ed68e73b2b57ff3 100644 (file)
@@ -9,16 +9,12 @@ fn main() {
     let x = NAN;
     match x {
         NAN => {}, //~ ERROR floating-point types cannot be used
-        //~^ WARN this was previously accepted by the compiler but is being phased out
-        //~| ERROR floating-point types cannot be used in patterns
         //~| WARN this was previously accepted by the compiler but is being phased out
         _ => {},
     };
 
     match [x, 1.0] {
         [NAN, _] => {}, //~ ERROR floating-point types cannot be used
-                        //~| ERROR floating-point types cannot be used
-        //~| WARN this was previously accepted by the compiler but is being phased out
         //~| WARN this was previously accepted by the compiler but is being phased out
         _ => {},
     };
index c7411e27c255aca47014b1d3ed2e66546f31ba17..4e2961e5e23be4a15dba1e58a8f6e69ee769ddc3 100644 (file)
@@ -13,7 +13,7 @@ LL | #![deny(illegal_floating_point_literal_pattern)]
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:19:10
+  --> $DIR/issue-6804.rs:17:10
    |
 LL |         [NAN, _] => {},
    |          ^^^
@@ -21,23 +21,5 @@ LL |         [NAN, _] => {},
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:11:9
-   |
-LL |         NAN => {},
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:19:10
-   |
-LL |         [NAN, _] => {},
-   |          ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
index 31f642ea66418499040dc290581d1b1e4ce6f181..a6f8ba65ab51af649f9d25d7361470825f3904f1 100644 (file)
@@ -8,7 +8,9 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
   --> $DIR/issue-73886.rs:4:13
    |
 LL |     let _ = 7u32 as Option<_>;
-   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |             ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
+   |
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lang-items/issue-86238.rs b/src/test/ui/lang-items/issue-86238.rs
new file mode 100644 (file)
index 0000000..509f94f
--- /dev/null
@@ -0,0 +1,16 @@
+// Regression test for the ICE described in issue #86238.
+
+#![feature(lang_items)]
+#![feature(no_core)]
+
+#![no_core]
+fn main() {
+    let one = || {};
+    one()
+    //~^ ERROR: failed to find an overloaded call trait for closure call
+    //~| HELP: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined
+}
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
diff --git a/src/test/ui/lang-items/issue-86238.stderr b/src/test/ui/lang-items/issue-86238.stderr
new file mode 100644 (file)
index 0000000..767e6de
--- /dev/null
@@ -0,0 +1,10 @@
+error: failed to find an overloaded call trait for closure call
+  --> $DIR/issue-86238.rs:9:5
+   |
+LL |     one()
+   |     ^^^^^
+   |
+   = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have associated `call`/`call_mut`/`call_once` functions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/command-line-register-lint-tool.rs b/src/test/ui/lint/command-line-register-lint-tool.rs
new file mode 100644 (file)
index 0000000..d6e95fd
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: -A known_tool::foo
+// check-pass
+
+#![feature(register_tool)]
+#![register_tool(known_tool)]
+
+fn main() {}
diff --git a/src/test/ui/lint/command-line-register-unknown-lint-tool.rs b/src/test/ui/lint/command-line-register-unknown-lint-tool.rs
new file mode 100644 (file)
index 0000000..59fc020
--- /dev/null
@@ -0,0 +1,4 @@
+// compile-flags: -A unknown_tool::foo
+// error-pattern: unknown lint tool: `unknown_tool`
+
+fn main() {}
diff --git a/src/test/ui/lint/command-line-register-unknown-lint-tool.stderr b/src/test/ui/lint/command-line-register-unknown-lint-tool.stderr
new file mode 100644 (file)
index 0000000..c9a2aff
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0602]: unknown lint tool: `unknown_tool`
+   |
+   = note: requested on the command line with `-A unknown_tool::foo`
+
+error[E0602]: unknown lint tool: `unknown_tool`
+   |
+   = note: requested on the command line with `-A unknown_tool::foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs
new file mode 100644 (file)
index 0000000..bcfe6e5
--- /dev/null
@@ -0,0 +1,15 @@
+// compile-flags: --cap-lints warn  --force-warns rust-2021-compatibility -Zunstable-options
+// check-pass
+#![allow(ellipsis_inclusive_range_patterns)]
+
+pub fn f() -> bool {
+    let x = 123;
+    match x {
+        0...100 => true,
+        //~^ WARN range patterns are deprecated
+        //~| WARN this is accepted in the current edition
+        _ => false,
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr
new file mode 100644 (file)
index 0000000..07e786c
--- /dev/null
@@ -0,0 +1,12 @@
+warning: `...` range patterns are deprecated
+  --> $DIR/force-warn-cap-lints-warn.rs:8:10
+   |
+LL |         0...100 => true,
+   |          ^^^ help: use `..=` for an inclusive range
+   |
+   = note: `--force-warns ellipsis-inclusive-range-patterns` implied by `--force-warns rust-2021-compatibility`
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs
new file mode 100644 (file)
index 0000000..e364897
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: --cap-lints allow  --force-warns bare_trait_objects -Zunstable-options
+// check-pass
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr
new file mode 100644 (file)
index 0000000..2153202
--- /dev/null
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warns-cap-lints-allow.rs:6:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: requested on the command line with `--force-warns bare-trait-objects`
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/issue-86600-lint-twice.rs b/src/test/ui/lint/issue-86600-lint-twice.rs
new file mode 100644 (file)
index 0000000..0e8a837
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for #86600, where an instance of the
+// `illegal_floating_point_literal_pattern` lint was issued twice.
+
+// check-pass
+
+fn main() {
+    let x = 42.0;
+
+    match x {
+        5.0 => {}
+        //~^ WARNING: floating-point types cannot be used in patterns
+        //~| WARNING: this was previously accepted by the compiler
+        _ => {}
+    }
+}
diff --git a/src/test/ui/lint/issue-86600-lint-twice.stderr b/src/test/ui/lint/issue-86600-lint-twice.stderr
new file mode 100644 (file)
index 0000000..8da3fb5
--- /dev/null
@@ -0,0 +1,12 @@
+warning: floating-point types cannot be used in patterns
+  --> $DIR/issue-86600-lint-twice.rs:10:9
+   |
+LL |         5.0 => {}
+   |         ^^^
+   |
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: 1 warning emitted
+
index 94fc1a7b46dbaf85e1234f8e109091572ad66541..4b082fcd35951147a71aa9e01b9bb94c9590fd8a 100644 (file)
@@ -11,16 +11,16 @@ LL | #![warn(deprecated)]
    |         ^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:29:9
+  --> $DIR/lint-stability-deprecated.rs:29:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:31:9
+  --> $DIR/lint-stability-deprecated.rs:31:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `lint_stability::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:33:9
@@ -29,16 +29,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:38:9
+  --> $DIR/lint-stability-deprecated.rs:38:16
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:40:9
+  --> $DIR/lint-stability-deprecated.rs:40:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `lint_stability::deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:42:9
@@ -47,16 +47,16 @@ LL |         deprecated_unstable();
    |         ^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:47:9
+  --> $DIR/lint-stability-deprecated.rs:47:16
    |
 LL | ...   Trait::trait_deprecated_unstable(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:49:9
+  --> $DIR/lint-stability-deprecated.rs:49:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:51:9
@@ -65,16 +65,16 @@ LL |         deprecated_unstable_text();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:56:9
+  --> $DIR/lint-stability-deprecated.rs:56:16
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:58:9
+  --> $DIR/lint-stability-deprecated.rs:58:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text
   --> $DIR/lint-stability-deprecated.rs:108:17
@@ -101,16 +101,16 @@ LL |         let _ = DeprecatedUnstableUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text
-  --> $DIR/lint-stability-deprecated.rs:123:17
+  --> $DIR/lint-stability-deprecated.rs:123:23
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text
-  --> $DIR/lint-stability-deprecated.rs:124:17
+  --> $DIR/lint-stability-deprecated.rs:124:23
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:128:17
@@ -143,52 +143,52 @@ LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:145:9
+  --> $DIR/lint-stability-deprecated.rs:145:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:147:9
+  --> $DIR/lint-stability-deprecated.rs:147:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:149:9
+  --> $DIR/lint-stability-deprecated.rs:149:16
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:151:9
+  --> $DIR/lint-stability-deprecated.rs:151:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:153:9
+  --> $DIR/lint-stability-deprecated.rs:153:16
    |
 LL | ...   Trait::trait_deprecated_unstable(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:155:9
+  --> $DIR/lint-stability-deprecated.rs:155:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:157:9
+  --> $DIR/lint-stability-deprecated.rs:157:16
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:159:9
+  --> $DIR/lint-stability-deprecated.rs:159:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text
   --> $DIR/lint-stability-deprecated.rs:187:10
@@ -203,10 +203,10 @@ LL |     trait LocalTrait2 : DeprecatedTrait { }
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:208:9
+  --> $DIR/lint-stability-deprecated.rs:208:23
    |
 LL |         unstable_mod::deprecated();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^
 
 warning: use of deprecated function `this_crate::deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:330:9
@@ -215,16 +215,16 @@ LL |         deprecated();
    |         ^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:335:9
+  --> $DIR/lint-stability-deprecated.rs:335:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:337:9
+  --> $DIR/lint-stability-deprecated.rs:337:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `this_crate::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:339:9
@@ -233,16 +233,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:344:9
+  --> $DIR/lint-stability-deprecated.rs:344:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:346:9
+  --> $DIR/lint-stability-deprecated.rs:346:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated struct `this_crate::DeprecatedStruct`: text
   --> $DIR/lint-stability-deprecated.rs:384:17
@@ -257,10 +257,10 @@ LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
-  --> $DIR/lint-stability-deprecated.rs:395:17
+  --> $DIR/lint-stability-deprecated.rs:395:23
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:399:17
@@ -269,28 +269,28 @@ LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:406:9
+  --> $DIR/lint-stability-deprecated.rs:406:16
    |
 LL |         Trait::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:408:9
+  --> $DIR/lint-stability-deprecated.rs:408:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:410:9
+  --> $DIR/lint-stability-deprecated.rs:410:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:412:9
+  --> $DIR/lint-stability-deprecated.rs:412:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text
   --> $DIR/lint-stability-deprecated.rs:439:9
index 56d4ffc4727b2e2e627f76e5d9b4bdaf4d633bea..3bbb60dd35927f38833215860d5f543762c37263 100644 (file)
@@ -1,15 +1,14 @@
 error: use of deprecated function `lint_stability::deprecated_text`: text
-  --> $DIR/lint-stability3.rs:13:5
+  --> $DIR/lint-stability3.rs:13:28
    |
 LL |     macro_test_arg_nested!(deprecated_text);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-stability3.rs:4:9
    |
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
-   = note: this error originates in the macro `macro_test_arg_nested` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/missing-doc-private-macro.rs b/src/test/ui/lint/missing-doc-private-macro.rs
new file mode 100644 (file)
index 0000000..8d1d5c5
--- /dev/null
@@ -0,0 +1,43 @@
+// Checks that undocumented private macros will not generate `missing_docs`
+// lints, but public ones will.
+//
+// This is a regression test for issue #57569
+#![deny(missing_docs)]
+#![feature(decl_macro)]
+//! Empty documentation.
+
+macro new_style_private_macro {
+    () => ()
+}
+
+pub(crate) macro new_style_crate_macro {
+    () => ()
+}
+
+macro_rules! old_style_private_macro {
+    () => ()
+}
+
+mod submodule {
+    pub macro new_style_macro_in_private_module {
+        () => ()
+    }
+
+    macro_rules! old_style_mod_private_macro {
+        () => ()
+    }
+
+    #[macro_export]
+    macro_rules! exported_to_top_level {
+        //~^ ERROR missing documentation for macro
+        () => ()
+    }
+}
+
+pub macro top_level_pub_macro {
+    //~^ ERROR missing documentation for macro
+    () => ()
+}
+
+/// Empty documentation.
+pub fn main() {}
diff --git a/src/test/ui/lint/missing-doc-private-macro.stderr b/src/test/ui/lint/missing-doc-private-macro.stderr
new file mode 100644 (file)
index 0000000..a5d39fa
--- /dev/null
@@ -0,0 +1,20 @@
+error: missing documentation for macro
+  --> $DIR/missing-doc-private-macro.rs:31:5
+   |
+LL |     macro_rules! exported_to_top_level {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/missing-doc-private-macro.rs:5:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing documentation for macro
+  --> $DIR/missing-doc-private-macro.rs:37:1
+   |
+LL | pub macro top_level_pub_macro {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
index 713b79bae32e625a3cbdbffdedda6795557fc537..e4de04ef3ccd15582effed4fc7064c58eead0fab 100644 (file)
@@ -1,6 +1,6 @@
 warning: Linking globals named 'foo': symbol multiply defined!
 
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.3a1fbbbh-cgu.0.rcgu.o": 
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o": 
 
 error: aborting due to previous error; 1 warning emitted
 
index 2846f2a1f835332074f6bed990fc8c83d4124f80..753675872b9cac6f39228a89f28785a09c18002a 100644 (file)
@@ -2,7 +2,7 @@
 // error-pattern:panicked at 'test-assert-owned'
 // ignore-emscripten no processes
 
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 
 fn main() {
     assert!(false, "test-assert-owned".to_string());
index fd2c590ae5fd6eac0af7664732daf8ddd034b728..780e158fe0b8f8bf46fd1ee6d961fc06f68d5f5b 100644 (file)
 // revisions: std core
 
 // ignore-wasm32-bare compiled with panic=abort by default
-
 #![cfg_attr(core, no_std)]
 
-#[cfg(std)] use std::fmt;
-#[cfg(core)] use core::fmt;
+#[cfg(core)]
+use core::fmt;
+#[cfg(std)]
+use std::fmt;
 
 // an easy mistake in the implementation of 'assert!'
 // would cause this to say "explicit panic"
@@ -57,7 +58,7 @@ fn writeln_1arg() {
 //
 // (Example: Issue #48042)
 #[test]
-#[allow(non_fmt_panic)]
+#[allow(non_fmt_panics)]
 fn to_format_or_not_to_format() {
     // ("{}" is the easiest string to test because if this gets
     // sent to format_args!, it'll simply fail to compile.
@@ -80,13 +81,17 @@ fn to_format_or_not_to_format() {
     // format!("{}",); // see check-fail
     // format_args!("{}",); // see check-fail
 
-    if falsum() { panic!("{}",); }
+    if falsum() {
+        panic!("{}",);
+    }
 
     // print!("{}",); // see check-fail
     // println!("{}",); // see check-fail
     // unimplemented!("{}",); // see check-fail
 
-    if falsum() { unreachable!("{}",); }
+    if falsum() {
+        unreachable!("{}",);
+    }
 
     // write!(&mut stdout, "{}",); // see check-fail
     // writeln!(&mut stdout, "{}",); // see check-fail
index f5a42670fdd1c62402b243bd17eb1342ad8e452e..b0d56e9bb1ef0a5bd97923bf1b572401c1df7e38 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 // aux-build:or-pattern.rs
 
-#![deny(or_patterns_back_compat)]
+#![deny(rust_2021_incompatible_or_patterns)]
 #![allow(unused_macros)]
 
 #[macro_use]
index d6620f45f62705d371b1c9b65009a534c18aab60..9e24b5106b8bf528fbf3b5fdfdc71745a19ac4d5 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 // aux-build:or-pattern.rs
 
-#![deny(or_patterns_back_compat)]
+#![deny(rust_2021_incompatible_or_patterns)]
 #![allow(unused_macros)]
 
 #[macro_use]
index a48c926315403fb37a97c7d1efd9df94fd5f0600..eb6204fa02e69221dc89aee8af589b70bbbc1d97 100644 (file)
@@ -7,8 +7,8 @@ LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
 note: the lint level is defined here
   --> $DIR/macro-or-patterns-back-compat.rs:4:9
    |
-LL | #![deny(or_patterns_back_compat)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_or_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
 
index 15323ce9a9755561f943f3d797cd97f5fbdc5e23..5a4e31947f2b2e889a1ceee9b40625fe3c4a0270 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `self.how_hungry` which is behind a `&` reference
+error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference
   --> $DIR/mutable-class-fields-2.rs:9:5
    |
 LL |   pub fn eat(&self) {
index 8d48b00f8d1f19088a89c8fb53ec583fe309afbf..a4ee7781753060f0bb8c6fbd7f5227d692f031c0 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference
   --> $DIR/issue-47388.rs:8:5
    |
 LL |     let fancy_ref = &(&mut fancy);
index 743415d58afadb3b01e53473bdf25210cf1742c7..c4cbee6754c0461432785589aae247b71392fbcc 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
     let ref my_ref @ _ = 0;
     *my_ref = 0;
-    //~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
+    //~^ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
 }
index c91083955b8205b30678ec9c4abc18d370113a8f..19f0223a357a53e1fee7727c77516654b4e3a158 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
   --> $DIR/issue-51244.rs:3:5
    |
 LL |     let ref my_ref @ _ = 0;
index c410f0b0bfb4da6fd4d8b73d1ec5298cf5666c8a..8f3dec454d5ff9640212bd710a7b37c9a06bcfdb 100644 (file)
@@ -2,7 +2,7 @@
 
 fn f(x: &i32) {
     let g = &x;
-    *x = 0;     //~ ERROR cannot assign to `*x` which is behind a `&` reference
+    *x = 0;     //~ ERROR cannot assign to `*x`, which is behind a `&` reference
                 //~| ERROR cannot assign to `*x` because it is borrowed
     g;
 }
index 4c416105035d7e7681d022d0432ce73503634105..e85e63e52ecc37bbec6731f5b2f1c34078cddf92 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
   --> $DIR/issue-57989.rs:5:5
    |
 LL | fn f(x: &i32) {
index 0f451c1e0a9a3827d8ede3e1edee6dd1e8502d0b..6aa2eb174e922166af0333ce180de8478dfedc85 100644 (file)
@@ -4,7 +4,7 @@ warning: panic message contains a brace
 LL |     panic!("here's a brace: {");
    |                             ^
    |
-   = note: `#[warn(non_fmt_panic)]` on by default
+   = note: `#[warn(non_fmt_panics)]` on by default
    = note: this message is not used as a format string, but will be in Rust 2021
 help: add a "{}" format string to use the message literally
    |
index bfcc12cd186bd5a8d59160baaf0694f45c6e7d66..9d80357873488352e8078db797eae2f0c656e43c 100644 (file)
@@ -1,6 +1,6 @@
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 
 // run-fail
 // error-pattern:wooooo
index 100ac10c76717937d0b91bf46369ae583d1a32e4..663bf6713d090e444e8f900d3687d1e3be383a5e 100644 (file)
@@ -2,7 +2,7 @@
 // error-pattern:panicked at 'Box<dyn Any>'
 // ignore-emscripten no processes
 
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 
 fn main() {
     panic!(Box::new(612_i64));
index a5ba30220e89a2296e6fc47770297751c21057e7..08acc6e8078f9b8df2b804ee4a30e019f34f186f 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-emscripten no processes
 
 #![feature(box_syntax)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 
 fn main() {
     panic!(box 413 as Box<dyn std::any::Any + Send>);
diff --git a/src/test/ui/parser/issue-86895.rs b/src/test/ui/parser/issue-86895.rs
new file mode 100644 (file)
index 0000000..4cd0984
--- /dev/null
@@ -0,0 +1,3 @@
+const pub () {}
+//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`
+pub fn main() {}
diff --git a/src/test/ui/parser/issue-86895.stderr b/src/test/ui/parser/issue-86895.stderr
new file mode 100644 (file)
index 0000000..575d857
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+  --> $DIR/issue-86895.rs:1:7
+   |
+LL | const pub () {}
+   |       ^^^ expected one of `async`, `extern`, `fn`, or `unsafe`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/recover-ref-dyn-mut.rs b/src/test/ui/parser/recover-ref-dyn-mut.rs
new file mode 100644 (file)
index 0000000..3016275
--- /dev/null
@@ -0,0 +1,9 @@
+// Test that the parser detects `&dyn mut`, offers a help message, and
+// recovers.
+
+fn main() {
+    let r: &dyn mut Trait;
+    //~^ ERROR: `mut` must precede `dyn`
+    //~| HELP: place `mut` before `dyn`
+    //~| ERROR: cannot find trait `Trait` in this scope [E0405]
+}
diff --git a/src/test/ui/parser/recover-ref-dyn-mut.stderr b/src/test/ui/parser/recover-ref-dyn-mut.stderr
new file mode 100644 (file)
index 0000000..c048c8e
--- /dev/null
@@ -0,0 +1,15 @@
+error: `mut` must precede `dyn`
+  --> $DIR/recover-ref-dyn-mut.rs:5:12
+   |
+LL |     let r: &dyn mut Trait;
+   |            ^^^^^^^^ help: place `mut` before `dyn`: `&mut dyn`
+
+error[E0405]: cannot find trait `Trait` in this scope
+  --> $DIR/recover-ref-dyn-mut.rs:5:21
+   |
+LL |     let r: &dyn mut Trait;
+   |                     ^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
index 9c320edc4dc0ec0f6a6ac5021d0ef5fb6485b685..a6144c9497d0483255c3fbaa23c314d36ab49292 100644 (file)
@@ -23,8 +23,8 @@ fn tuple() {
     _x1 = U; //~ ERROR cannot assign twice to immutable variable
     let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also
     let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also
-    *_x0 = U; //~ ERROR cannot assign to `*_x0` which is behind a `&` reference
-    *_x2 = U; //~ ERROR cannot assign to `*_x2` which is behind a `&` reference
+    *_x0 = U; //~ ERROR cannot assign to `*_x0`, which is behind a `&` reference
+    *_x2 = U; //~ ERROR cannot assign to `*_x2`, which is behind a `&` reference
     drop(tup.1); //~ ERROR use of moved value: `tup.1`
     let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1`
     let (.., ref mut _x3) = tup;
index d0726f05cc3be01d2a48f2a667d86d52afdeacc5..5beca04d285901aafc840a7b0aba00f63903e7f7 100644 (file)
@@ -101,7 +101,7 @@ LL |     let (ref mut _x0_hold, ..) = tup;
 LL |     *_x0 = U;
    |     -------- immutable borrow later used here
 
-error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
+error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference
   --> $DIR/borrowck-move-ref-pattern.rs:26:5
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
@@ -110,7 +110,7 @@ LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
 LL |     *_x0 = U;
    |     ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
+error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference
   --> $DIR/borrowck-move-ref-pattern.rs:27:5
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
index 368326e02166e573038f528482e8faf5615c4fd8..dc63d014451db8b1f5705b297de01fbc938ca36a 100644 (file)
@@ -45,10 +45,10 @@ fn main /* 0#0 */() { ; }
 Expansions:
 0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
 1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "produce_it", proc_macro: false }
+2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
 3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "meta_macro::print_def_site", proc_macro: true }
-5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "$crate::dummy", proc_macro: true }
+4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
+5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
 
 SyntaxContexts:
 #0: parent: #0, outer_mark: (ExpnId(0), Opaque)
index 2911707fdb03e60d7f95308ce5895ea8d86952d7..75e6a49b314dfe56f65ef616aaef13c6b4acb604 100644 (file)
@@ -69,10 +69,10 @@ fn main /* 0#0 */() { }
 Expansions:
 0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
 1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "outer", proc_macro: false }
+2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
 3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro { kind: Bang, name: "inner", proc_macro: false }
-5: parent: ExpnId(4), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "print_bang", proc_macro: true }
+4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
+5: parent: ExpnId(4), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
 
 SyntaxContexts:
 #0: parent: #0, outer_mark: (ExpnId(0), Opaque)
index 2cbe91afacdd18557031dd1873ac779e28816059..9152ee60a7ed46a51d127250f69a7e9f9ad1442f 100644 (file)
@@ -2,7 +2,7 @@ error[E0412]: cannot find type `MissingType` in this scope
   --> $DIR/auxiliary/span-from-proc-macro.rs:37:20
    |
 LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
-   | ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
+   | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]`
 ...
 LL |             field: MissingType
    |                    ^^^^^^^^^^^ not found in this scope
@@ -16,7 +16,7 @@ error[E0412]: cannot find type `OtherMissingType` in this scope
   --> $DIR/auxiliary/span-from-proc-macro.rs:46:21
    |
 LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream {
-   | ------------------------------------------------------------ in this expansion of procedural macro `#[derive(ErrorFromDerive)]`
+   | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]`
 ...
 LL |             Variant(OtherMissingType)
    |                     ^^^^^^^^^^^^^^^^ not found in this scope
@@ -30,7 +30,7 @@ error[E0425]: cannot find value `my_ident` in this scope
   --> $DIR/auxiliary/span-from-proc-macro.rs:29:9
    |
 LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream {
-   | ---------------------------------------------------------------- in this expansion of procedural macro `other_error_from_bang!`
+   | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!`
 LL |     custom_quote::custom_quote! {
 LL |         my_ident
    |         ^^^^^^^^ not found in this scope
@@ -49,7 +49,7 @@ LL |             let bang_error: bool = 25;
    |                             expected due to this
 ...
 LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream {
-   | ---------------------------------------------------------- in this expansion of procedural macro `error_from_bang!`
+   | ---------------------------------------------------------- in this expansion of `error_from_bang!`
    | 
   ::: $DIR/span-from-proc-macro.rs:15:5
    |
index 31ff9c1e3a72e0290f17e6162597d6b15b6bf1e2..59dae106c0001daad8f03b55468e04e5f3d58e3d 100644 (file)
@@ -2,5 +2,7 @@
 
 #![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer
                          //~| `limit` must be a non-negative integer
+                         //~| ERROR `limit` must be a non-negative integer
+                         //~| `limit` must be a non-negative integer
 
 fn main() {}
index bcd1d27e59b56be8926ceaa16a36d7dbb0b28422..cb5c0c35a5ebf624be1592514d3dbd35c80afa2d 100644 (file)
@@ -6,5 +6,13 @@ LL | #![recursion_limit = ""]
    |                      |
    |                      `limit` must be a non-negative integer
 
-error: aborting due to previous error
+error: `limit` must be a non-negative integer
+  --> $DIR/empty.rs:3:1
+   |
+LL | #![recursion_limit = ""]
+   | ^^^^^^^^^^^^^^^^^^^^^--^
+   |                      |
+   |                      `limit` must be a non-negative integer
+
+error: aborting due to 2 previous errors
 
index 759d69d0af20d08e33fa25f736b45d46c97da6ef..03df3e7a92713502cbad66fcce24333ef1ff1677 100644 (file)
@@ -2,5 +2,6 @@
 
 #![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer
                              //~| not a valid integer
-
+                             //~| ERROR `limit` must be a non-negative integer
+                             //~| not a valid integer
 fn main() {}
index e6fd6b72a0900e04013f6db6d2c5600ce1ca7e18..4dc93ad5f67b38a089c27b2f2063448e1a667636 100644 (file)
@@ -6,5 +6,13 @@ LL | #![recursion_limit = "-100"]
    |                      |
    |                      not a valid integer
 
-error: aborting due to previous error
+error: `limit` must be a non-negative integer
+  --> $DIR/invalid_digit.rs:3:1
+   |
+LL | #![recursion_limit = "-100"]
+   | ^^^^^^^^^^^^^^^^^^^^^------^
+   |                      |
+   |                      not a valid integer
+
+error: aborting due to 2 previous errors
 
index 8eee2792b23832cf6d5a6528a0bf67df474a6c8d..c733ba6b93ce55f943c9237a9426c5772271b49c 100644 (file)
@@ -3,5 +3,7 @@
 #![recursion_limit = "999999999999999999999999"]
 //~^ ERROR `limit` must be a non-negative integer
 //~| `limit` is too large
+//~| ERROR `limit` must be a non-negative integer
+//~| `limit` is too large
 
 fn main() {}
index f6ed76c1ebc0e096facf4431f9edfefd65331fcf..2f622d28b45a151f9ddeaa3ef2948d3e31e4d8dc 100644 (file)
@@ -6,5 +6,13 @@ LL | #![recursion_limit = "999999999999999999999999"]
    |                      |
    |                      `limit` is too large
 
-error: aborting due to previous error
+error: `limit` must be a non-negative integer
+  --> $DIR/overflow.rs:3:1
+   |
+LL | #![recursion_limit = "999999999999999999999999"]
+   | ^^^^^^^^^^^^^^^^^^^^^--------------------------^
+   |                      |
+   |                      `limit` is too large
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/repr/issue-83921-ice.rs b/src/test/ui/repr/issue-83921-ice.rs
new file mode 100644 (file)
index 0000000..70583eb
--- /dev/null
@@ -0,0 +1,34 @@
+// Regression test for various ICEs inspired by
+// https://github.com/rust-lang/rust/issues/83921#issuecomment-814640734
+
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
+#[repr(packed())]
+//~^ ERROR: incorrect `repr(packed)` attribute format
+struct S1;
+
+#[repr(align)]
+//~^ ERROR: invalid `repr(align)` attribute
+struct S2;
+
+#[repr(align(2, 4))]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S3;
+
+#[repr(align())]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S4;
+
+#[repr(i8())]
+//~^ ERROR: invalid representation hint
+enum E1 { A, B }
+
+#[repr(u32(42))]
+//~^ ERROR: invalid representation hint
+enum E2 { A, B }
+
+#[repr(i64 = 2)]
+//~^ ERROR: invalid representation hint
+enum E3 { A, B }
+
+fn main() {}
diff --git a/src/test/ui/repr/issue-83921-ice.stderr b/src/test/ui/repr/issue-83921-ice.stderr
new file mode 100644 (file)
index 0000000..32c4504
--- /dev/null
@@ -0,0 +1,46 @@
+error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+  --> $DIR/issue-83921-ice.rs:6:8
+   |
+LL | #[repr(packed())]
+   |        ^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
+  --> $DIR/issue-83921-ice.rs:10:8
+   |
+LL | #[repr(align)]
+   |        ^^^^^ help: supply an argument here: `align(...)`
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/issue-83921-ice.rs:14:8
+   |
+LL | #[repr(align(2, 4))]
+   |        ^^^^^^^^^^^
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/issue-83921-ice.rs:18:8
+   |
+LL | #[repr(align())]
+   |        ^^^^^^^
+
+error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list
+  --> $DIR/issue-83921-ice.rs:22:8
+   |
+LL | #[repr(i8())]
+   |        ^^^^
+
+error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list
+  --> $DIR/issue-83921-ice.rs:26:8
+   |
+LL | #[repr(u32(42))]
+   |        ^^^^^^^
+
+error[E0552]: invalid representation hint: `i64` does not take a value
+  --> $DIR/issue-83921-ice.rs:30:8
+   |
+LL | #[repr(i64 = 2)]
+   |        ^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0552, E0589, E0693.
+For more information about an error, try `rustc --explain E0552`.
diff --git a/src/test/ui/repr/issue-83921-pretty.normal.stderr b/src/test/ui/repr/issue-83921-pretty.normal.stderr
new file mode 100644 (file)
index 0000000..6b7e831
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0565]: meta item in `repr` must be an identifier
+  --> $DIR/issue-83921-pretty.rs:10:8
+   |
+LL | #[repr("C")]
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/repr/issue-83921-pretty.pretty.stdout b/src/test/ui/repr/issue-83921-pretty.pretty.stdout
new file mode 100644 (file)
index 0000000..dad3641
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+#[repr("C")]
+struct A {
+}
+
+fn main() { loop { } }
diff --git a/src/test/ui/repr/issue-83921-pretty.rs b/src/test/ui/repr/issue-83921-pretty.rs
new file mode 100644 (file)
index 0000000..d5d3647
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+
+#[repr("C")]
+//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565]
+struct A {}
+
+fn main() {}
index fa5630837b9ad66748c0d6066b2ac88aab8715d2..59a22c33778c5f14583620b97138ba8ff8409df2 100644 (file)
@@ -17,8 +17,6 @@ fn main() {
     match x {
         f32::INFINITY => { }
         //~^ WARNING floating-point types cannot be used in patterns
-        //~| WARNING will become a hard error in a future release
-        //~| WARNING floating-point types cannot be used in patterns
         //~| WARNING this was previously accepted by the compiler but is being phased out
         _ => { }
     }
index 9a5d57d411832e3b0386207d241685246db548f0..df4809dabf159beae8fc19dddb3c55e882017450 100644 (file)
@@ -14,14 +14,5 @@ LL |         f32::INFINITY => { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-warning: floating-point types cannot be used in patterns
-  --> $DIR/match-forbidden-without-eq.rs:18:9
-   |
-LL |         f32::INFINITY => { }
-   |         ^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
 
index af82d36f87eb080e7046c2ee29663726fb744408..4e57769d6e24c877885437173092118d558a9e52 100644 (file)
@@ -6,17 +6,17 @@ enum Wrapper {
 
 pub fn main() {
     let Wrap(x) = &Wrap(3);
-    *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+    *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
 
 
     if let Some(x) = &Some(3) {
-        *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+        *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
     } else {
         panic!();
     }
 
     while let Some(x) = &Some(3) {
-        *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+        *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
         break;
     }
 }
index d6a89006bc0fb9a489ef4934089e0cacd6c8b04e..21e3d3d273d7f3295435089754d57ef04e10aea2 100644 (file)
@@ -1,16 +1,16 @@
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
   --> $DIR/enum.rs:9:5
    |
 LL |     *x += 1;
    |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
   --> $DIR/enum.rs:13:9
    |
 LL |         *x += 1;
    |         ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
   --> $DIR/enum.rs:19:9
    |
 LL |         *x += 1;
index 212fd94ded3e7f38231f20424a1926807e1907d0..b8fde2208acd5a1bf4fd7d3ba4ed670b6e435aac 100644 (file)
@@ -4,7 +4,7 @@
 fn main() {
     match &&Some(5i32) {
         Some(n) => {
-            *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
+            *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
             let _ = n;
         }
         None => {},
@@ -12,7 +12,7 @@ fn main() {
 
     match &mut &Some(5i32) {
         Some(n) => {
-            *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
+            *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
             let _ = n;
         }
         None => {},
@@ -20,7 +20,7 @@ fn main() {
 
     match &&mut Some(5i32) {
         Some(n) => {
-            *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
+            *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
             let _ = n;
         }
         None => {},
index a6f2f3ec3096858df5aacd0b9078ff330b191166..c3f64f65a412ec40e5bdd79ce18fffa0b90ccc83 100644 (file)
@@ -1,16 +1,16 @@
-error[E0594]: cannot assign to `*n` which is behind a `&` reference
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
   --> $DIR/explicit-mut.rs:7:13
    |
 LL |             *n += 1;
    |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*n` which is behind a `&` reference
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
   --> $DIR/explicit-mut.rs:15:13
    |
 LL |             *n += 1;
    |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*n` which is behind a `&` reference
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
   --> $DIR/explicit-mut.rs:23:13
    |
 LL |             *n += 1;
index 3b2a2238fa82d4b8b48162c0ac579872cb608f23..06883a857900ef5e027eb00c1db6015d33d16b5b 100644 (file)
@@ -2,22 +2,60 @@
 
 trait Tracked {
     #[track_caller]
-    fn handle(&self) {
+    fn track_caller_trait_method(&self, line: u32, col: u32) {
         let location = std::panic::Location::caller();
         assert_eq!(location.file(), file!());
-        // we only call this via trait object, so the def site should *always* be returned
-        assert_eq!(location.line(), line!() - 4);
-        assert_eq!(location.column(), 5);
+        // The trait method definition is annotated with `#[track_caller]`,
+        // so caller location information will work through a method
+        // call on a trait object
+        assert_eq!(location.line(), line, "Bad line");
+        assert_eq!(location.column(), col, "Bad col");
     }
+
+    fn track_caller_not_on_trait_method(&self);
+
+    #[track_caller]
+    fn track_caller_through_self(self: Box<Self>, line: u32, col: u32);
 }
 
-impl Tracked for () {}
-impl Tracked for u8 {}
+impl Tracked for () {
+    // We have `#[track_caller]` on the implementation of the method,
+    // but not on the definition of the method in the trait. Therefore,
+    // caller location information will *not* work through a method call
+    // on a trait object. Instead, we will get the location of this method
+    #[track_caller]
+    fn track_caller_not_on_trait_method(&self) {
+        let location = std::panic::Location::caller();
+        assert_eq!(location.file(), file!());
+        assert_eq!(location.line(), line!() - 3);
+        assert_eq!(location.column(), 5);
+    }
+
+    // We don't have a `#[track_caller]` attribute, but
+    // `#[track_caller]` is present on the trait definition,
+    // so we'll still get location information
+    fn track_caller_through_self(self: Box<Self>, line: u32, col: u32) {
+        let location = std::panic::Location::caller();
+        assert_eq!(location.file(), file!());
+        // The trait method definition is annotated with `#[track_caller]`,
+        // so caller location information will work through a method
+        // call on a trait object
+        assert_eq!(location.line(), line, "Bad line");
+        assert_eq!(location.column(), col, "Bad col");
+    }
+}
 
 fn main() {
-    let tracked: &dyn Tracked = &5u8;
-    tracked.handle();
+    let tracked: &dyn Tracked = &();
+    // The column is the start of 'track_caller_trait_method'
+    tracked.track_caller_trait_method(line!(), 13);
 
     const TRACKED: &dyn Tracked = &();
-    TRACKED.handle();
+    // The column is the start of 'track_caller_trait_method'
+    TRACKED.track_caller_trait_method(line!(), 13);
+    TRACKED.track_caller_not_on_trait_method();
+
+    // The column is the start of `track_caller_through_self`
+    let boxed: Box<dyn Tracked> = Box::new(());
+    boxed.track_caller_through_self(line!(), 11);
 }
diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs
new file mode 100644 (file)
index 0000000..e5a5ac2
--- /dev/null
@@ -0,0 +1,13 @@
+// only-x86_64-pc-windows-msvc
+// compile-flags: --crate-type lib --emit link
+#![allow(incomplete_features)]
+#![feature(raw_dylib)]
+#[link(name = "foo", kind = "raw-dylib")]
+extern "stdcall" {
+    fn f(x: i32);
+    //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+}
+
+pub fn lib_main() {
+    unsafe { f(42); }
+}
diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr
new file mode 100644 (file)
index 0000000..fc90081
--- /dev/null
@@ -0,0 +1,8 @@
+error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+  --> $DIR/unsupported-abi.rs:7:5
+   |
+LL |     fn f(x: i32);
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 725d5aa234eee982217c97c418a9030163c47e75..c5ff0b4bcd0f8cb3bdb74fb3d3d15ca4d5316b8a 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 // edition:2018
 // check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 #![allow(dead_code)]
 #![allow(unused_imports)]
 
index 6ca9a919f3cd7fca56755c1bce712ed346d927d2..cd39eec47f2a4125416440a5053eee6b50d5841f 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 // edition:2018
 // check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 #![allow(dead_code)]
 #![allow(unused_imports)]
 
index 8889485c9172996103abc316a3513654841a2112..61975876819229bfbfc8fbe123f3b10a20eff4ad 100644 (file)
@@ -7,8 +7,8 @@ LL |         let _: u32 = 3u8.try_into().unwrap();
 note: the lint level is defined here
   --> $DIR/future-prelude-collision-imported.rs:4:9
    |
-LL | #![warn(future_prelude_collision)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
 
index c9d2529341f4f1a0eae784cf3714584dd22bc9d6..27891a8d11db7474a64db2b7defdedc478e0b590 100644 (file)
@@ -1,5 +1,5 @@
 // edition:2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 #![allow(dead_code)]
 #![allow(unused_imports)]
 
index a4a5b6667df8cdd96ab783648b9369dd42f6a6fd..247d5884b868af877e91fc91d1d46621263c3521 100644 (file)
@@ -1,16 +1,60 @@
 // edition:2018
 // check-pass
 #![allow(unused)]
-#![deny(future_prelude_collision)]
+#![deny(rust_2021_prelude_collisions)]
 
 struct S;
 
 impl S {
-    fn try_into(self) -> S { S }
+    fn try_into(self) -> S {
+        S
+    }
+}
+
+struct X;
+
+trait Hey {
+    fn from_iter(_: i32) -> Self;
+}
+
+impl Hey for X {
+    fn from_iter(_: i32) -> Self {
+        X
+    }
+}
+
+struct Y<T>(T);
+
+impl Hey for Y<i32> {
+    fn from_iter(_: i32) -> Self {
+        Y(0)
+    }
+}
+
+struct Z<T>(T);
+
+impl Hey for Z<i32> {
+    fn from_iter(_: i32) -> Self {
+        Z(0)
+    }
+}
+
+impl std::iter::FromIterator<u32> for Z<u32> {
+    fn from_iter<T: IntoIterator<Item = u32>>(_: T) -> Self {
+        todo!()
+    }
 }
 
-// See https://github.com/rust-lang/rust/issues/86633
 fn main() {
+    // See https://github.com/rust-lang/rust/issues/86633
     let s = S;
     let s2 = s.try_into();
+
+    // Check that we do not issue suggestions for types that do not implement `FromIter`.
+    //
+    // See https://github.com/rust-lang/rust/issues/86902
+    X::from_iter(1);
+    Y::from_iter(1);
+    Y::<i32>::from_iter(1);
+    Z::<i32>::from_iter(1);
 }
index 4bcbe6b094afdb40244b5b4befd694ec5dbe4f38..43b0ec1c3e6a709fab2eefc5670e7c80854b67a2 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 // edition:2018
 // check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 
 trait TryIntoU32 {
     fn try_into(self) -> Result<u32, ()>;
index bc23a8a92a6b5f00229ca19ab7a50e55aa696b90..4c7a47ffbe28ac0bca9213847beb2379c63c1175 100644 (file)
@@ -1,7 +1,7 @@
 // run-rustfix
 // edition:2018
 // check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 
 trait TryIntoU32 {
     fn try_into(self) -> Result<u32, ()>;
index e167468ab19719e13158fcc6c3e129a7a4c0527e..03b89da00d970c934ece61e64ba817bc7f7eb4c4 100644 (file)
@@ -7,8 +7,8 @@ LL |     let _: u32 = 3u8.try_into().unwrap();
 note: the lint level is defined here
   --> $DIR/future-prelude-collision.rs:4:9
    |
-LL | #![warn(future_prelude_collision)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
 
index d1a085f23a01c9ede8629dae15366309c8e74cc4..feba7d19b6615750da3f1a06fd48fee2f602c823 100644 (file)
@@ -1,7 +1,7 @@
 // check-pass
 // run-rustfix
 // edition 2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 
 trait MyTrait<A> {
     fn from_iter(x: Option<A>);
index 5069fba396ec6b4a638bb8d628eb43133a9e454f..335e7e520a495450d8e9cc2151a1c91afbcc2a0e 100644 (file)
@@ -1,7 +1,7 @@
 // check-pass
 // run-rustfix
 // edition 2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 
 trait MyTrait<A> {
     fn from_iter(x: Option<A>);
index 05591c3d4487d86d00947f49408bb70e246e5eee..d4999201c27f962bacb9586e0d7687fe91eb296b 100644 (file)
@@ -7,8 +7,8 @@ LL |     <Vec<i32>>::from_iter(None);
 note: the lint level is defined here
   --> $DIR/generic-type-collision.rs:4:9
    |
-LL | #![warn(future_prelude_collision)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
 
index cf6287a758f9134a86b17b1ca5f715369f1fe2d8..5789a90393bae56106f04d19020c575691bbffc8 100644 (file)
@@ -5,7 +5,7 @@
 // run-rustfix
 // edition:2018
 
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 
 trait TryIntoU32 {
     fn try_into(&self) -> Result<u32, ()>;
index 0349ad5b6415af05c9e106a91ac492d543646514..a3893c033e942cf1e7c9566ca41a9bcc66ee99f4 100644 (file)
@@ -5,7 +5,7 @@
 // run-rustfix
 // edition:2018
 
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
 
 trait TryIntoU32 {
     fn try_into(&self) -> Result<u32, ()>;
index 9e95419715e319843eda97f4b955ec74db73c95f..605f9ced9ebb72e559a81c5ae2d35bacdce59010 100644 (file)
@@ -7,8 +7,8 @@ LL |         get_dyn_trait().try_into().unwrap()
 note: the lint level is defined here
   --> $DIR/inherent-dyn-collision.rs:8:9
    |
-LL | #![warn(future_prelude_collision)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
 
index c638351d5fc09bf9a93e999402cc5da6d165a02f..507105207d695e18794c876f7c5390c0cbf890dc 100644 (file)
@@ -2,7 +2,7 @@
 //
 // check-pass
 
-#![deny(future_prelude_collision)]
+#![deny(rust_2021_prelude_collisions)]
 
 pub struct MySeq {}
 
index dbc2ec6d42ee2eeeab358f9e667dad270696ce6a..e026f01e93fb038027d0b773c7a4ff53f709e42e 100644 (file)
@@ -2,7 +2,7 @@
 // run-rustfix
 // compile-flags: -Z unstable-options --edition 2018
 
-#![warn(reserved_prefix)]
+#![warn(rust_2021_prefixes_incompatible_syntax)]
 
 macro_rules! m2 {
     ($a:tt $b:tt) => {};
@@ -14,16 +14,16 @@ macro_rules! m3 {
 
 fn main() {
     m2!(z "hey");
-    //~^ WARNING prefix `z` is unknown [reserved_prefix]
+    //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
     m2!(prefix "hey");
-    //~^ WARNING prefix `prefix` is unknown [reserved_prefix]
+    //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
     m3!(hey #123);
-    //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
     m3!(hey #hey);
-    //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
 }
 
@@ -33,6 +33,6 @@ macro_rules! quote {
 
 quote! {
     #name = #kind #value
-    //~^ WARNING prefix `kind` is unknown [reserved_prefix]
+    //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
 }
index 6f7e3eb7a43a6b7b44999126dbc2cf60c56dffc4..d24f29634806d9d70cee029979f0a6258a7b8869 100644 (file)
@@ -2,7 +2,7 @@
 // run-rustfix
 // compile-flags: -Z unstable-options --edition 2018
 
-#![warn(reserved_prefix)]
+#![warn(rust_2021_prefixes_incompatible_syntax)]
 
 macro_rules! m2 {
     ($a:tt $b:tt) => {};
@@ -14,16 +14,16 @@ macro_rules! m3 {
 
 fn main() {
     m2!(z"hey");
-    //~^ WARNING prefix `z` is unknown [reserved_prefix]
+    //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
     m2!(prefix"hey");
-    //~^ WARNING prefix `prefix` is unknown [reserved_prefix]
+    //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
     m3!(hey#123);
-    //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
     m3!(hey#hey);
-    //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+    //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
 }
 
@@ -33,6 +33,6 @@ macro_rules! quote {
 
 quote! {
     #name = #kind#value
-    //~^ WARNING prefix `kind` is unknown [reserved_prefix]
+    //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax]
     //~| WARNING hard error in Rust 2021
 }
index 28ac1966a1bce087619daaaa7c3faab4471e38a1..95105f932dcbd945f9777fba6c998e96b5952550 100644 (file)
@@ -7,8 +7,8 @@ LL |     m2!(z"hey");
 note: the lint level is defined here
   --> $DIR/reserved-prefixes-migration.rs:5:9
    |
-LL | #![warn(reserved_prefix)]
-   |         ^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prefixes_incompatible_syntax)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
 help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
index 723c4a7a1fbf0672233b6d440ce2b21d3418fe9c..b251e8a438ac1c79fda0763694e425e3c3e11f2a 100644 (file)
@@ -1,11 +1,11 @@
-error: lifetime parameter `'b` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |                      ^^-
-   |                      |
-   |                      this lifetime is only used here
-   |                      help: elide the single-use lifetime
+   |          ^^-
+   |          |
+   |          this lifetime is only used here
+   |          help: elide the single-use lifetime
    |
 note: the lint level is defined here
   --> $DIR/one-use-in-fn-argument-in-band.rs:4:9
@@ -13,14 +13,14 @@ note: the lint level is defined here
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: lifetime parameter `'a` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
+error: lifetime parameter `'b` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |          ^^-
-   |          |
-   |          this lifetime is only used here
-   |          help: elide the single-use lifetime
+   |                      ^^-
+   |                      |
+   |                      this lifetime is only used here
+   |                      help: elide the single-use lifetime
 
 error: aborting due to 2 previous errors
 
index fa59d7a031397530d9114219be96e3c8097302f9..d2eea15f3988619895f9d6c0bed32a0f2d24cc76 100644 (file)
@@ -1,4 +1,4 @@
-error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[b09c]::Id::This) }, (I,)), [])`
   --> $DIR/repeated_projection_type.rs:19:1
    |
 LL | / impl<I, V: Id<This = (I,)>> X for V {
index 99523f8eb645d5877260abc8b62f03ee0215f949..bc59844f77c8b80fee37bd70e692cdab785d7295 100644 (file)
@@ -34,7 +34,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct4`: test
   --> $DIR/generics-default-stability.rs:83:12
    |
 LL |     let _: Struct4<isize> = Struct4 { field: 1 };
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^
 
 warning: use of deprecated struct `unstable_generic_param::Struct4`: test
   --> $DIR/generics-default-stability.rs:88:12
@@ -46,7 +46,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct4`: test
   --> $DIR/generics-default-stability.rs:89:12
    |
 LL |     let _: Struct4<usize> = STRUCT4;
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^
 
 warning: use of deprecated struct `unstable_generic_param::Struct4`: test
   --> $DIR/generics-default-stability.rs:90:29
@@ -58,7 +58,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct4`: test
   --> $DIR/generics-default-stability.rs:90:12
    |
 LL |     let _: Struct4<isize> = Struct4 { field: 0 };
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^
 
 warning: use of deprecated struct `unstable_generic_param::Struct5`: test
   --> $DIR/generics-default-stability.rs:96:29
@@ -70,7 +70,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct5`: test
   --> $DIR/generics-default-stability.rs:96:12
    |
 LL |     let _: Struct5<isize> = Struct5 { field: 1 };
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^
 
 warning: use of deprecated struct `unstable_generic_param::Struct5`: test
   --> $DIR/generics-default-stability.rs:101:12
@@ -82,7 +82,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct5`: test
   --> $DIR/generics-default-stability.rs:102:12
    |
 LL |     let _: Struct5<usize> = STRUCT5;
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^
 
 warning: use of deprecated struct `unstable_generic_param::Struct5`: test
   --> $DIR/generics-default-stability.rs:104:29
@@ -94,7 +94,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct5`: test
   --> $DIR/generics-default-stability.rs:104:12
    |
 LL |     let _: Struct5<isize> = Struct5 { field: 0 };
-   |            ^^^^^^^^^^^^^^
+   |            ^^^^^^^
 
 warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
   --> $DIR/generics-default-stability.rs:159:28
@@ -106,7 +106,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
   --> $DIR/generics-default-stability.rs:159:12
    |
 LL |     let _: Alias4<isize> = Alias4::Some(1);
-   |            ^^^^^^^^^^^^^
+   |            ^^^^^^
 
 warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
   --> $DIR/generics-default-stability.rs:163:12
@@ -118,7 +118,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
   --> $DIR/generics-default-stability.rs:164:12
    |
 LL |     let _: Alias4<usize> = ALIAS4;
-   |            ^^^^^^^^^^^^^
+   |            ^^^^^^
 
 warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
   --> $DIR/generics-default-stability.rs:165:28
@@ -130,7 +130,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
   --> $DIR/generics-default-stability.rs:165:12
    |
 LL |     let _: Alias4<isize> = Alias4::Some(0);
-   |            ^^^^^^^^^^^^^
+   |            ^^^^^^
 
 warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
   --> $DIR/generics-default-stability.rs:170:28
@@ -142,7 +142,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
   --> $DIR/generics-default-stability.rs:170:12
    |
 LL |     let _: Alias5<isize> = Alias5::Some(1);
-   |            ^^^^^^^^^^^^^
+   |            ^^^^^^
 
 warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
   --> $DIR/generics-default-stability.rs:174:12
@@ -154,7 +154,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
   --> $DIR/generics-default-stability.rs:175:12
    |
 LL |     let _: Alias5<usize> = ALIAS5;
-   |            ^^^^^^^^^^^^^
+   |            ^^^^^^
 
 warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
   --> $DIR/generics-default-stability.rs:177:28
@@ -166,19 +166,19 @@ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
   --> $DIR/generics-default-stability.rs:177:12
    |
 LL |     let _: Alias5<isize> = Alias5::Some(0);
-   |            ^^^^^^^^^^^^^
+   |            ^^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test
-  --> $DIR/generics-default-stability.rs:231:27
+  --> $DIR/generics-default-stability.rs:231:34
    |
 LL |     let _: Enum4<isize> = Enum4::Some(1);
-   |                           ^^^^^^^^^^^
+   |                                  ^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum4`: test
   --> $DIR/generics-default-stability.rs:231:12
    |
 LL |     let _: Enum4<isize> = Enum4::Some(1);
-   |            ^^^^^^^^^^^^
+   |            ^^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum4`: test
   --> $DIR/generics-default-stability.rs:235:12
@@ -190,31 +190,31 @@ warning: use of deprecated enum `unstable_generic_param::Enum4`: test
   --> $DIR/generics-default-stability.rs:236:12
    |
 LL |     let _: Enum4<usize> = ENUM4;
-   |            ^^^^^^^^^^^^
+   |            ^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test
-  --> $DIR/generics-default-stability.rs:237:27
+  --> $DIR/generics-default-stability.rs:237:34
    |
 LL |     let _: Enum4<isize> = Enum4::Some(0);
-   |                           ^^^^^^^^^^^
+   |                                  ^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum4`: test
   --> $DIR/generics-default-stability.rs:237:12
    |
 LL |     let _: Enum4<isize> = Enum4::Some(0);
-   |            ^^^^^^^^^^^^
+   |            ^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test
-  --> $DIR/generics-default-stability.rs:242:27
+  --> $DIR/generics-default-stability.rs:242:34
    |
 LL |     let _: Enum5<isize> = Enum5::Some(1);
-   |                           ^^^^^^^^^^^
+   |                                  ^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum5`: test
   --> $DIR/generics-default-stability.rs:242:12
    |
 LL |     let _: Enum5<isize> = Enum5::Some(1);
-   |            ^^^^^^^^^^^^
+   |            ^^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum5`: test
   --> $DIR/generics-default-stability.rs:246:12
@@ -226,19 +226,19 @@ warning: use of deprecated enum `unstable_generic_param::Enum5`: test
   --> $DIR/generics-default-stability.rs:247:12
    |
 LL |     let _: Enum5<usize> = ENUM5;
-   |            ^^^^^^^^^^^^
+   |            ^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test
-  --> $DIR/generics-default-stability.rs:249:27
+  --> $DIR/generics-default-stability.rs:249:34
    |
 LL |     let _: Enum5<isize> = Enum5::Some(0);
-   |                           ^^^^^^^^^^^
+   |                                  ^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum5`: test
   --> $DIR/generics-default-stability.rs:249:12
    |
 LL |     let _: Enum5<isize> = Enum5::Some(0);
-   |            ^^^^^^^^^^^^
+   |            ^^^^^
 
 error[E0658]: use of unstable library feature 'unstable_default'
   --> $DIR/generics-default-stability.rs:35:20
index 32367d2d0cf213b1acc49cd88865911899572709..7f931f0cdc9e8d11133f978284628b1ee70fe83c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
   --> $DIR/issue-68049-1.rs:7:9
    |
 LL |         self.0 += 1;
index f10a83c68a81b062a6cb84c8ab28b168f29ec447..2f31193e4a4a2b1717bf3d1bd5acd45e9e21a74b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `*input` which is behind a `&` reference
+error[E0594]: cannot assign to `*input`, which is behind a `&` reference
   --> $DIR/issue-68049-2.rs:9:7
    |
 LL |   fn example(&self, input: &i32); // should suggest here
@@ -7,7 +7,7 @@ LL |   fn example(&self, input: &i32); // should suggest here
 LL |       *input = self.0;
    |       ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
   --> $DIR/issue-68049-2.rs:17:5
    |
 LL |   fn example(&self, input: &i32); // should suggest here
index 6ab08197441c39a2654826518983683c503b9108..3eb9e1031d7067101cf620aa4f64aa06ad08c6dd 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `t.v` which is behind a `&` reference
+error[E0594]: cannot assign to `t.v`, which is behind a `&` reference
   --> $DIR/suggest-mut-method-for-loop.rs:14:9
    |
 LL |     for mut t in buzz.values() {
index b4981279a238b1f955d98aafdcd2f1727f5470b3..9fd2658ec702db71609de9cba8ea44458c58bc86 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
   --> $DIR/suggest-ref-mut.rs:7:9
    |
 LL |     fn zap(&self) {
@@ -7,7 +7,7 @@ LL |     fn zap(&self) {
 LL |         self.0 = 32;
    |         ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
   --> $DIR/suggest-ref-mut.rs:16:5
    |
 LL |     let ref foo = 16;
@@ -16,7 +16,7 @@ LL |     let ref foo = 16;
 LL |     *foo = 32;
    |     ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
   --> $DIR/suggest-ref-mut.rs:21:9
    |
 LL |     if let Some(ref bar) = Some(16) {
@@ -25,7 +25,7 @@ LL |     if let Some(ref bar) = Some(16) {
 LL |         *bar = 32;
    |         ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
 
-error[E0594]: cannot assign to `*quo` which is behind a `&` reference
+error[E0594]: cannot assign to `*quo`, which is behind a `&` reference
   --> $DIR/suggest-ref-mut.rs:25:22
    |
 LL |         ref quo => { *quo = 32; },
diff --git a/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs
new file mode 100644 (file)
index 0000000..f882a15
--- /dev/null
@@ -0,0 +1,27 @@
+// Regression test for #87051, where a double semicolon was erroneously
+// suggested after a `?` operator.
+
+fn main() -> Result<(), ()> {
+    a(|| {
+        b()
+        //~^ ERROR: mismatched types [E0308]
+        //~| NOTE: expected `()`, found `i32`
+        //~| HELP: consider using a semicolon here
+    })?;
+
+    // Here, we do want to suggest a semicolon:
+    let x = Ok(42);
+    if true {
+    //~^ NOTE: expected this to be `()`
+        x?
+        //~^ ERROR: mismatched types [E0308]
+        //~| NOTE: expected `()`, found integer
+        //~| HELP: consider using a semicolon here
+    }
+    //~^ HELP: consider using a semicolon here
+
+    Ok(())
+}
+
+fn a<F>(f: F) -> Result<(), ()> where F: FnMut() { Ok(()) }
+fn b() -> i32 { 42 }
diff --git a/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
new file mode 100644 (file)
index 0000000..4f7e187
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9
+   |
+LL |         b()
+   |         ^^^- help: consider using a semicolon here: `;`
+   |         |
+   |         expected `()`, found `i32`
+
+error[E0308]: mismatched types
+  --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9
+   |
+LL | /     if true {
+LL | |
+LL | |         x?
+   | |         ^^ expected `()`, found integer
+LL | |
+LL | |
+LL | |
+LL | |     }
+   | |_____- expected this to be `()`
+   |
+help: consider using a semicolon here
+   |
+LL |         x?;
+   |           ^
+help: consider using a semicolon here
+   |
+LL |     };
+   |      ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 3dd2b19fbf987f9cc290979b09f0988ac9c06fd5..de4d35e261ca7aea1f5660538916a03991ea5104 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E)
+error: symbol-name(_ZN5basic4main17hd75b915511563828E)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic::main::h6c535bbea2051f85)
+error: demangling(basic::main::hd75b915511563828)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
index bd107c10207078d8b8b39559267a962648f066bd..d871a4ee829f0ee05c07aeca5826f5e0b3e93cf8 100644 (file)
@@ -9,8 +9,8 @@
 //[legacy]~^ ERROR symbol-name(_ZN5basic4main
 //[legacy]~| ERROR demangling(basic::main
 //[legacy]~| ERROR demangling-alt(basic::main)
- //[v0]~^^^^ ERROR symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
-    //[v0]~| ERROR demangling(basic[17891616a171812d]::main)
+ //[v0]~^^^^ ERROR symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
+    //[v0]~| ERROR demangling(basic[de7d5b6b69c71f37]::main)
     //[v0]~| ERROR demangling-alt(basic::main)
 #[rustc_def_path]
 //[legacy]~^ ERROR def-path(main)
index 519efc9d7b4b9725a9016ab8461b3465bc841f60..e30fa6f66d5143b09c42ba5e2ab13c06c2920d2e 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
+error: symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic[17891616a171812d]::main)
+error: demangling(basic[de7d5b6b69c71f37]::main)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
index bd7e1c0f336983d4aba2b65a50fb974be5889bf0..05c6b8352de63634f9a95f8507518befb69de33a 100644 (file)
@@ -5,32 +5,32 @@
 pub struct Unsigned<const F: u8>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
+//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Unsigned<11>>)
 impl Unsigned<11> {}
 
 pub struct Signed<const F: i16>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
+//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Signed<-152>>)
 impl Signed<-152> {}
 
 pub struct Bool<const F: bool>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
+//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Bool<true>>)
 impl Bool<true> {}
 
 pub struct Char<const F: char>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
+//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Char<'∂'>>)
 impl Char<'∂'> {}
 
index 13995403f7791ee4a1d2371a3f75f360e1fc608b..05c485d001f03dab9b9b6aa18c8cd25fe72528c0 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+error: symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
@@ -16,13 +16,13 @@ error: demangling-alt(<const_generics_demangling::Unsigned<11>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
+error: symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
@@ -34,13 +34,13 @@ error: demangling-alt(<const_generics_demangling::Signed<-152>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
+error: symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
@@ -52,13 +52,13 @@ error: demangling-alt(<const_generics_demangling::Bool<true>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
+error: symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
index b0b31a57d0692db4359d0019a4fed440466a7519..960049be7936f032248a61d60a608564ec3f08c7 100644 (file)
@@ -15,8 +15,8 @@ impl Foo {
         //[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar
         //[legacy]~| ERROR demangling(impl1::foo::Foo::bar
         //[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
-            //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
+            //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
             //[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::bar)
         #[rustc_def_path]
         //[legacy]~^ ERROR def-path(foo::Foo::bar)
@@ -33,8 +33,8 @@ impl Foo {
         //[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
         //[legacy]~| ERROR demangling(impl1::bar::<impl impl1::foo::Foo>::baz
         //[legacy]~| ERROR demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
-            //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
+            //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
             //[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::baz)
         #[rustc_def_path]
         //[legacy]~^ ERROR def-path(bar::<impl foo::Foo>::baz)
@@ -63,8 +63,8 @@ fn method(&self) {}
             //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
             //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method
             //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
-             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-                //[v0]~| ERROR demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
+             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+                //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
                 //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
             #[rustc_def_path]
             //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
index e5b0deee36e3c0bb72112610a2cda0348b32a924..a7c3a389909a4f75eb72f329f21258c07b64eb3a 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
+error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
   --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
+error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
   --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
@@ -22,13 +22,13 @@ error: def-path(foo::Foo::bar)
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
+error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
   --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
+error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
   --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
@@ -46,13 +46,13 @@ error: def-path(bar::<impl foo::Foo>::baz)
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+error: symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
+error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
index 8357678399235c3f303d5ed8b37f436dd227683e..52d0c66639835ec7b9925d03cbb0b52a1feff85b 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h18eaa05e22e59176E)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h18eaa05e22e59176)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
index 3238eb1e579f079c736cb18b631421890887d697..a313c1ef3832679ed500ee1c8d18bde70e93eeae 100644 (file)
@@ -22,8 +22,8 @@ impl Foo<::llvm::Foo> {
         //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
         //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo
         //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
-            //[v0]~| ERROR demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+            //[v0]~| ERROR demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
             //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
         pub(crate) fn foo() {
             for _ in 0..0 {
index 6a5885e1ea32b08149fdd6cf06598f5ba986eab8..5d99abff59ab5a0151eddecd9f6de6919b9e028f 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+error: symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
+error: demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
index 4d061cafef3b2d99a125b57220c50d18a269dcfc..0f721fc1f89c8e4f8f17bc7a91b4a7c3464e1ba2 100644 (file)
@@ -42,8 +42,8 @@ impl<I, T, E> Iterator2 for Foo<I, E>
     //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next
     //[legacy]~| ERROR demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next
     //[legacy]~| ERROR demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next)
-    //[v0]~^^^^  ERROR symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
-    //[v0]~|     ERROR demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
+    //[v0]~^^^^  ERROR symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+    //[v0]~|     ERROR demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
     //[v0]~|     ERROR demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next)
     fn next(&mut self) -> Option<Self::Item> {
         self.find(|_| true)
index 98844aafb65528ac8f7210198a7c52537282a2bd..093ba8c857685969558a729809c5c14f3cbd5d69 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+error: symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
   --> $DIR/issue-75326.rs:41:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
+error: demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
   --> $DIR/issue-75326.rs:41:5
    |
 LL |     #[rustc_symbol_name]
index 2b09318f06c74806386f6f668cc805dfd1a74c2f..5ada82dfb2df61e79551b564418ee05bc8cc0824 100644 (file)
@@ -4,7 +4,7 @@ error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3f8b57f879016e18]::Bar>::method)
   --> $DIR/trait-objects.rs:16:5
    |
 LL |     #[rustc_symbol_name]
@@ -22,7 +22,7 @@ error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3op
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Foo>::method)
   --> $DIR/trait-objects.rs:28:5
    |
 LL |     #[rustc_symbol_name]
@@ -40,7 +40,7 @@ error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3o
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Baz>::method)
   --> $DIR/trait-objects.rs:40:5
    |
 LL |     #[rustc_symbol_name]
index 1340ae43cd6afd5c6182b79e7cc65990f5602da6..6a44f27dbb2a48b474d18d9934ee007857d1b603 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 use std::mem::{size_of, size_of_val, align_of, align_of_val};
index 4efd4c4d3d3aa2b9882a9fe95100201c24554bea..b19eab9f52b5294e248d25740569fe22ce1ca8fe 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(path_statements)]
 #![allow(dead_code)]
 
index 73cc9793f2c4c911947408bc6627529ec55fc590..dcc552ac75c89a6294faf19981eb0f00c83dc257 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(unused_imports)]
 
 // aux-build:union.rs
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..e785a2e
--- /dev/null
@@ -0,0 +1,60 @@
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:56:13
+   |
+LL |     let a = &mut u.x.0;
+   |             ---------- mutable borrow occurs here (via `u.x.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:63:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = u.x.0;
+   |             ----- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:69:13
+   |
+LL |     let a = &mut (u.x.0).0;
+   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:76:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = (u.x.0).0;
+   |             --------- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:82:13
+   |
+LL |     let a = &mut *u.y;
+   |                   --- mutable borrow occurs here (via `u.y`)
+LL |     let b = &u.x;
+   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
index edf08e6ca678f13a4340aac6b5afd54052fc8bff..e56d87255dbaff1e590d53bd5f2698a65d006051 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(untagged_unions)]
 #![allow(unused)]
 
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.stderr
deleted file mode 100644 (file)
index 8ba155b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
-  --> $DIR/union-borrow-move-parent-sibling.rs:53:13
-   |
-LL |     let a = &mut u.x.0;
-   |             ---------- mutable borrow occurs here (via `u.x.0`)
-LL |     let b = &u.y;
-   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
-LL |     use_borrow(a);
-   |                - mutable borrow later used here
-   |
-   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
-
-error[E0382]: use of moved value: `u`
-  --> $DIR/union-borrow-move-parent-sibling.rs:60:13
-   |
-LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
-   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
-LL |     let a = u.x.0;
-   |             ----- value moved here
-LL |     let b = u.y;
-   |             ^^^ value used here after move
-
-error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
-  --> $DIR/union-borrow-move-parent-sibling.rs:66:13
-   |
-LL |     let a = &mut (u.x.0).0;
-   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
-LL |     let b = &u.y;
-   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
-LL |     use_borrow(a);
-   |                - mutable borrow later used here
-   |
-   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
-
-error[E0382]: use of moved value: `u`
-  --> $DIR/union-borrow-move-parent-sibling.rs:73:13
-   |
-LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
-   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
-LL |     let a = (u.x.0).0;
-   |             --------- value moved here
-LL |     let b = u.y;
-   |             ^^^ value used here after move
-
-error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
-  --> $DIR/union-borrow-move-parent-sibling.rs:79:13
-   |
-LL |     let a = &mut *u.y;
-   |                   --- mutable borrow occurs here (via `u.y`)
-LL |     let b = &u.x;
-   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
-LL |     use_borrow(a);
-   |                - mutable borrow later used here
-   |
-   = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0382, E0502.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..e785a2e
--- /dev/null
@@ -0,0 +1,60 @@
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:56:13
+   |
+LL |     let a = &mut u.x.0;
+   |             ---------- mutable borrow occurs here (via `u.x.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:63:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = u.x.0;
+   |             ----- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:69:13
+   |
+LL |     let a = &mut (u.x.0).0;
+   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:76:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = (u.x.0).0;
+   |             --------- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:82:13
+   |
+LL |     let a = &mut *u.y;
+   |                   --- mutable borrow occurs here (via `u.y`)
+LL |     let b = &u.x;
+   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
index d5b305595956386ff4dc4dc71ea79aa45a8b6400..32a546cf35f2cd2d33f9ad7cb2513260220dd9ee 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 union U {
     a: u64,
index 15a20899a78d1a24419303e24dde5591a9ecb19d..ca48785cd9f5ae2ab062d5790e6d0b06aa652baa 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 type Field1 = (i32, u32);
 type Field2 = f32;
index 90af8de447dfdaa2c9eea756580b7c51bb3a5a6a..0b6788b4226ab9d1f9b6fa3829b11c7eca336fe5 100644 (file)
@@ -1,4 +1,7 @@
 // build-pass (FIXME(62277): could be check-pass?)
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(const_fn_union)]
 
 union U {
diff --git a/src/test/ui/union/union-deref.mirunsafeck.stderr b/src/test/ui/union/union-deref.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..ff37e6f
--- /dev/null
@@ -0,0 +1,56 @@
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:17:14
+   |
+LL |     unsafe { u.f.0 = Vec::new() };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:19:19
+   |
+LL |     unsafe { &mut u.f.0 };
+   |                   ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:21:14
+   |
+LL |     unsafe { u.f.0.push(0) };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:25:14
+   |
+LL |     unsafe { u.f.0.0 = Vec::new() };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:27:19
+   |
+LL |     unsafe { &mut u.f.0.0 };
+   |                   ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:29:14
+   |
+LL |     unsafe { u.f.0.0.push(0) };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: aborting due to 6 previous errors
+
index 48f5b36bd17f3927a1734760f418d0eb3c24ba9a..4bf2ba2f1bfce0bccad8cef5f7780e3361f4c118 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 //! Test the part of RFC 2514 that is about not applying `DerefMut` coercions
 //! of union fields.
 #![feature(untagged_unions)]
diff --git a/src/test/ui/union/union-deref.stderr b/src/test/ui/union/union-deref.stderr
deleted file mode 100644 (file)
index 6af050b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:14:14
-   |
-LL |     unsafe { u.f.0 = Vec::new() };
-   |              ^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:16:19
-   |
-LL |     unsafe { &mut u.f.0 };
-   |                   ^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:18:14
-   |
-LL |     unsafe { u.f.0.push(0) };
-   |              ^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:22:14
-   |
-LL |     unsafe { u.f.0.0 = Vec::new() };
-   |              ^^^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:24:19
-   |
-LL |     unsafe { &mut u.f.0.0 };
-   |                   ^^^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:26:14
-   |
-LL |     unsafe { u.f.0.0.push(0) };
-   |              ^^^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/union/union-deref.thirunsafeck.stderr b/src/test/ui/union/union-deref.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..ff37e6f
--- /dev/null
@@ -0,0 +1,56 @@
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:17:14
+   |
+LL |     unsafe { u.f.0 = Vec::new() };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:19:19
+   |
+LL |     unsafe { &mut u.f.0 };
+   |                   ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:21:14
+   |
+LL |     unsafe { u.f.0.push(0) };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:25:14
+   |
+LL |     unsafe { u.f.0.0 = Vec::new() };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:27:19
+   |
+LL |     unsafe { &mut u.f.0.0 };
+   |                   ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:29:14
+   |
+LL |     unsafe { u.f.0.0.push(0) };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..41e828c
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:6:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `Copy` is not implemented for `U1`
+   | 
+  ::: $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+   |                                 ---- required by this bound in `AssertParamIsCopy`
+   |
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
+  --> $DIR/union-derive-clone.rs:38:15
+   |
+LL | union U5<T> {
+   | -----------
+   | |
+   | method `clone` not found for this
+   | doesn't satisfy `U5<CloneNoCopy>: Clone`
+...
+LL | struct CloneNoCopy;
+   | ------------------- doesn't satisfy `CloneNoCopy: Copy`
+...
+LL |     let w = u.clone();
+   |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `CloneNoCopy: Copy`
+           which is required by `U5<CloneNoCopy>: Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
index 7ab19edb47179d385f014791c66938914e0c1f10..7aa62146e5490b913f31cf795317b041d1c22346 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 use std::mem::ManuallyDrop;
 
 #[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
deleted file mode 100644 (file)
index 789bcc9..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0277]: the trait bound `U1: Copy` is not satisfied
-  --> $DIR/union-derive-clone.rs:3:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^ the trait `Copy` is not implemented for `U1`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ---- required by this bound in `AssertParamIsCopy`
-   |
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
-  --> $DIR/union-derive-clone.rs:35:15
-   |
-LL | union U5<T> {
-   | -----------
-   | |
-   | method `clone` not found for this
-   | doesn't satisfy `U5<CloneNoCopy>: Clone`
-...
-LL | struct CloneNoCopy;
-   | ------------------- doesn't satisfy `CloneNoCopy: Copy`
-...
-LL |     let w = u.clone();
-   |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
-   |
-   = note: the following trait bounds were not satisfied:
-           `CloneNoCopy: Copy`
-           which is required by `U5<CloneNoCopy>: Clone`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0599.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..41e828c
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:6:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `Copy` is not implemented for `U1`
+   | 
+  ::: $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+   |                                 ---- required by this bound in `AssertParamIsCopy`
+   |
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
+  --> $DIR/union-derive-clone.rs:38:15
+   |
+LL | union U5<T> {
+   | -----------
+   | |
+   | method `clone` not found for this
+   | doesn't satisfy `U5<CloneNoCopy>: Clone`
+...
+LL | struct CloneNoCopy;
+   | ------------------- doesn't satisfy `CloneNoCopy: Copy`
+...
+LL |     let w = u.clone();
+   |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `CloneNoCopy: Copy`
+           which is required by `U5<CloneNoCopy>: Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-eq.mirunsafeck.stderr b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9477d84
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:16:5
+   |
+LL |     a: PartialEqNotEq,
+   |     ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
+   | 
+  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
+   |                               -- required by this bound in `AssertParamIsEq`
+   |
+   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index e689f8c27d772ba38fe16ed86b68671e06b8c7e6..b7e7f343f8a28b35ac83db3c48f8a3850960b302 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #[derive(Eq)] // OK
 union U1 {
     a: u8,
diff --git a/src/test/ui/union/union-derive-eq.stderr b/src/test/ui/union/union-derive-eq.stderr
deleted file mode 100644 (file)
index 3198e97..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
-  --> $DIR/union-derive-eq.rs:13:5
-   |
-LL |     a: PartialEqNotEq,
-   |     ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
-   | 
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               -- required by this bound in `AssertParamIsEq`
-   |
-   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9477d84
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:16:5
+   |
+LL |     a: PartialEqNotEq,
+   |     ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
+   | 
+  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
+   |                               -- required by this bound in `AssertParamIsEq`
+   |
+   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index db18a81c1f6651a0c8ec95090cac5d412afff8a7..8276bc635fc748799a161d9b3de98681e2fe47c5 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/union/union-drop.thirunsafeck.stderr b/src/test/ui/union/union-drop.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9766ae4
--- /dev/null
@@ -0,0 +1,22 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/union-drop.rs:27:9
+   |
+LL |         unsafe { CHECK += 1; }
+   |         ^^^^^^ unnecessary `unsafe` block
+   |
+   = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union-drop.rs:33:9
+   |
+LL |         unsafe { CHECK += 1; }
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union-drop.rs:40:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/union/union-fields-1.mirunsafeck.stderr b/src/test/ui/union/union-fields-1.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9f1e294
--- /dev/null
@@ -0,0 +1,32 @@
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:9:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-fields-1.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:12:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:16:20
+   |
+LL | union NoDropLike { a: u8 }
+   |                    ^^^^^
+
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:21:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+
+error: aborting due to 4 previous errors
+
index edef41de159bae806cd36b26a0a9f07e90d3a18e..3d3e2355a26f2b10a9280d6c8178fb4057f5b1b5 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![deny(dead_code)]
 
 union U1 {
diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr
deleted file mode 100644 (file)
index 87621cc..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error: field is never read: `c`
-  --> $DIR/union-fields-1.rs:6:5
-   |
-LL |     c: u8,
-   |     ^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/union-fields-1.rs:1:9
-   |
-LL | #![deny(dead_code)]
-   |         ^^^^^^^^^
-
-error: field is never read: `a`
-  --> $DIR/union-fields-1.rs:9:5
-   |
-LL |     a: u8,
-   |     ^^^^^
-
-error: field is never read: `a`
-  --> $DIR/union-fields-1.rs:13:20
-   |
-LL | union NoDropLike { a: u8 }
-   |                    ^^^^^
-
-error: field is never read: `c`
-  --> $DIR/union-fields-1.rs:18:5
-   |
-LL |     c: u8,
-   |     ^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/union/union-fields-1.thirunsafeck.stderr b/src/test/ui/union/union-fields-1.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9f1e294
--- /dev/null
@@ -0,0 +1,32 @@
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:9:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-fields-1.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:12:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:16:20
+   |
+LL | union NoDropLike { a: u8 }
+   |                    ^^^^^
+
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:21:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/union/union-fields-2.mirunsafeck.stderr b/src/test/ui/union/union-fields-2.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..867bf75
--- /dev/null
@@ -0,0 +1,84 @@
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:10:13
+   |
+LL |     let u = U {};
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:12:13
+   |
+LL |     let u = U { a: 0, b: 1 };
+   |             ^
+
+error[E0560]: union `U` has no field named `c`
+  --> $DIR/union-fields-2.rs:13:29
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |                             ^ `U` does not have this field
+   |
+   = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:13:13
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:15:13
+   |
+LL |     let u = U { ..u };
+   |             ^
+
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/union-fields-2.rs:15:19
+   |
+LL |     let u = U { ..u };
+   |                   ^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:18:9
+   |
+LL |     let U {} = u;
+   |         ^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:20:9
+   |
+LL |     let U { a, b } = u;
+   |         ^^^^^^^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:21:9
+   |
+LL |     let U { a, b, c } = u;
+   |         ^^^^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+  --> $DIR/union-fields-2.rs:21:19
+   |
+LL |     let U { a, b, c } = u;
+   |                   ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:25:9
+   |
+LL |     let U { a, .. } = u;
+   |         ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
index 71b204fcdc5b88f1a414734da64a4beb085ff193..e738b18470337b586799488df597e9112567c720 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 union U {
     a: u8,
     b: u16,
diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.stderr
deleted file mode 100644 (file)
index 4865434..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:7:13
-   |
-LL |     let u = U {};
-   |             ^
-
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:9:13
-   |
-LL |     let u = U { a: 0, b: 1 };
-   |             ^
-
-error[E0560]: union `U` has no field named `c`
-  --> $DIR/union-fields-2.rs:10:29
-   |
-LL |     let u = U { a: 0, b: 1, c: 2 };
-   |                             ^ `U` does not have this field
-   |
-   = note: available fields are: `a`, `b`
-
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:10:13
-   |
-LL |     let u = U { a: 0, b: 1, c: 2 };
-   |             ^
-
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:12:13
-   |
-LL |     let u = U { ..u };
-   |             ^
-
-error[E0436]: functional record update syntax requires a struct
-  --> $DIR/union-fields-2.rs:12:19
-   |
-LL |     let u = U { ..u };
-   |                   ^
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:15:9
-   |
-LL |     let U {} = u;
-   |         ^^^^
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:17:9
-   |
-LL |     let U { a, b } = u;
-   |         ^^^^^^^^^^
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:18:9
-   |
-LL |     let U { a, b, c } = u;
-   |         ^^^^^^^^^^^^^
-
-error[E0026]: union `U` does not have a field named `c`
-  --> $DIR/union-fields-2.rs:18:19
-   |
-LL |     let U { a, b, c } = u;
-   |                   ^ union `U` does not have this field
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:20:9
-   |
-LL |     let U { .. } = u;
-   |         ^^^^^^^^
-
-error: `..` cannot be used in union patterns
-  --> $DIR/union-fields-2.rs:20:9
-   |
-LL |     let U { .. } = u;
-   |         ^^^^^^^^
-
-error: `..` cannot be used in union patterns
-  --> $DIR/union-fields-2.rs:22:9
-   |
-LL |     let U { a, .. } = u;
-   |         ^^^^^^^^^^^
-
-error: aborting due to 13 previous errors
-
-Some errors have detailed explanations: E0026, E0436, E0560.
-For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/union/union-fields-2.thirunsafeck.stderr b/src/test/ui/union/union-fields-2.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..867bf75
--- /dev/null
@@ -0,0 +1,84 @@
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:10:13
+   |
+LL |     let u = U {};
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:12:13
+   |
+LL |     let u = U { a: 0, b: 1 };
+   |             ^
+
+error[E0560]: union `U` has no field named `c`
+  --> $DIR/union-fields-2.rs:13:29
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |                             ^ `U` does not have this field
+   |
+   = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:13:13
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:15:13
+   |
+LL |     let u = U { ..u };
+   |             ^
+
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/union-fields-2.rs:15:19
+   |
+LL |     let u = U { ..u };
+   |                   ^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:18:9
+   |
+LL |     let U {} = u;
+   |         ^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:20:9
+   |
+LL |     let U { a, b } = u;
+   |         ^^^^^^^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:21:9
+   |
+LL |     let U { a, b, c } = u;
+   |         ^^^^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+  --> $DIR/union-fields-2.rs:21:19
+   |
+LL |     let U { a, b, c } = u;
+   |                   ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:25:9
+   |
+LL |     let U { a, .. } = u;
+   |         ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
index 69837f31cab27aa78e6ef57bf11ca08d6f1797d3..25f1f5050f99b46cf6835facd26d73ec775ec8a6 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 use std::mem::ManuallyDrop;
diff --git a/src/test/ui/union/union-generic.mirunsafeck.stderr b/src/test/ui/union/union-generic.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..fcd0bde
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:11:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:13:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index ff877892579b9008a9d87425b267fcf517659132..3d68ecb87d8d673d1c93dfb2409e915e808c7e0e 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 use std::rc::Rc;
 
 union U<T: Copy> {
diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.stderr
deleted file mode 100644 (file)
index c418b27..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:8:13
-   |
-LL | union U<T: Copy> {
-   | ---------------- required by `U`
-...
-LL |     let u = U { a: Rc::new(0u32) };
-   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
-
-error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:10:13
-   |
-LL | union U<T: Copy> {
-   | ---------------- required by `U`
-...
-LL |     let u = U::<Rc<u32>> { a: Default::default() };
-   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-generic.thirunsafeck.stderr b/src/test/ui/union/union-generic.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..fcd0bde
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:11:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:13:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 2e75cce7b108be3955582b0aeb98b4c51b0811ac..b0fd22da73adc146c203e8aa687a667b2753fe70 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 union U {
     a: u8,
diff --git a/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..22d4428
--- /dev/null
@@ -0,0 +1,14 @@
+error: field is never read: `b`
+  --> $DIR/union-lint-dead-code.rs:8:5
+   |
+LL |     b: bool,
+   |     ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-lint-dead-code.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
index ae5337c618a754d470c8af176689390c56be7c60..64c28d72e9eaa3ee59656d0e29bad07dba2a2299 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![deny(dead_code)]
 
 union Foo {
diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr
deleted file mode 100644 (file)
index 7de70ec..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: field is never read: `b`
-  --> $DIR/union-lint-dead-code.rs:5:5
-   |
-LL |     b: bool,
-   |     ^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/union-lint-dead-code.rs:1:9
-   |
-LL | #![deny(dead_code)]
-   |         ^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..22d4428
--- /dev/null
@@ -0,0 +1,14 @@
+error: field is never read: `b`
+  --> $DIR/union-lint-dead-code.rs:8:5
+   |
+LL |     b: bool,
+   |     ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-lint-dead-code.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
index e938cd5a614e9ff143618d063f5fa25758fc7b3d..7fd9d8221c612a0602bc875e1f153910af46743c 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(unused_variables)]
 
 macro_rules! duplicate {
index 977d12f1086028bb1e37fc7c4933955a4f27a36f..826bdf07cef5ec35937b8d4c9304bdb6cc3d8c25 100644 (file)
@@ -1,5 +1,8 @@
-#![allow(dead_code)]
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![allow(dead_code)]
 
 use std::mem::needs_drop;
 use std::mem::ManuallyDrop;
diff --git a/src/test/ui/union/union-move.mirunsafeck.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..f55fbea
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:29:18
+   |
+LL | fn test1(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f2_nocopy);
+   |                  ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:45:18
+   |
+LL | fn test3(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f3_copy);
+   |                  ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+  --> $DIR/union-move.rs:52:18
+   |
+LL |         move_out(x.f1_nocopy);
+   |                  ^^^^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.
index a0a2d0d659837a60bbe6e4b6a04ea34796938cfd..8f78c30d67a5537824396294b3ef9ac88f068720 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 //! Test the behavior of moving out of non-`Copy` union fields.
 //! Avoid types that `Drop`, we want to focus on moving.
 #![feature(untagged_unions)]
diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.stderr
deleted file mode 100644 (file)
index 5679192..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0382]: use of moved value: `x`
-  --> $DIR/union-move.rs:26:18
-   |
-LL | fn test1(x: U1) {
-   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
-...
-LL |         move_out(x.f1_nocopy);
-   |                  ----------- value moved here
-LL |         move_out(x.f2_nocopy);
-   |                  ^^^^^^^^^^^ value used here after move
-
-error[E0382]: use of moved value: `x`
-  --> $DIR/union-move.rs:42:18
-   |
-LL | fn test3(x: U1) {
-   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
-...
-LL |         move_out(x.f2_nocopy);
-   |                  ----------- value moved here
-LL |         move_out(x.f3_copy);
-   |                  ^^^^^^^^^ value used here after move
-
-error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
-  --> $DIR/union-move.rs:49:18
-   |
-LL |         move_out(x.f1_nocopy);
-   |                  ^^^^^^^^^^^
-   |                  |
-   |                  cannot move out of here
-   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0382, E0509.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..f55fbea
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:29:18
+   |
+LL | fn test1(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f2_nocopy);
+   |                  ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:45:18
+   |
+LL | fn test3(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f3_copy);
+   |                  ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+  --> $DIR/union-move.rs:52:18
+   |
+LL |         move_out(x.f1_nocopy);
+   |                  ^^^^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.
index bc58c5995cb80e2ed8317a7976362fe9a7fc2bae..6e6b105a73e9f461f2adeb5cfa64916f11aff7d8 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 #![allow(dead_code)]
 
index bd84b46bf3d234a9e6bbb3db18775974d837241b..d29e7a97180cf633d44f1d754a172c68682f0b8e 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 // Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.
index 399ed9ae458b8f664435e414a4b0f9da2debbbea..0eea14d9de0fc34beda14ecaa63f6b737406d28e 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 #[repr(C)]
 #[derive(Copy, Clone)]
index 9cde44c06bd476ccdf363079d3fe149a1582632e..9c6398bf5aa631039253d25a501cc344f9b6df10 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(non_snake_case)]
 
index ebb0672664716ebed36c384e20e85fb64c7e348c..d628a200a076e675fcf184fe53a53a5dd275db11 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(illegal_floating_point_literal_pattern)]
 
diff --git a/src/test/ui/union/union-suggest-field.mirunsafeck.stderr b/src/test/ui/union/union-suggest-field.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..26fc25b
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0560]: union `U` has no field named `principle`
+  --> $DIR/union-suggest-field.rs:13:17
+   |
+LL |     let u = U { principle: 0 };
+   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+  --> $DIR/union-suggest-field.rs:17:15
+   |
+LL |     let w = u.principial;
+   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+  --> $DIR/union-suggest-field.rs:21:15
+   |
+LL |     let y = u.calculate;
+   |               ^^^^^^^^^ method, not a field
+   |
+help: use parentheses to call the method
+   |
+LL |     let y = u.calculate();
+   |                        ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
index 71b93e873c22026ceca22d8e30c146afa2b3745c..601a22a060048ec5bd64a95c6aae2eba06a6c765 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 union U {
     principal: u8,
 }
diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr
deleted file mode 100644 (file)
index 461db17..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0560]: union `U` has no field named `principle`
-  --> $DIR/union-suggest-field.rs:10:17
-   |
-LL |     let u = U { principle: 0 };
-   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
-
-error[E0609]: no field `principial` on type `U`
-  --> $DIR/union-suggest-field.rs:14:15
-   |
-LL |     let w = u.principial;
-   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
-
-error[E0615]: attempted to take value of method `calculate` on type `U`
-  --> $DIR/union-suggest-field.rs:18:15
-   |
-LL |     let y = u.calculate;
-   |               ^^^^^^^^^ method, not a field
-   |
-help: use parentheses to call the method
-   |
-LL |     let y = u.calculate();
-   |                        ^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0560, E0609, E0615.
-For more information about an error, try `rustc --explain E0560`.
diff --git a/src/test/ui/union/union-suggest-field.thirunsafeck.stderr b/src/test/ui/union/union-suggest-field.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..26fc25b
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0560]: union `U` has no field named `principle`
+  --> $DIR/union-suggest-field.rs:13:17
+   |
+LL |     let u = U { principle: 0 };
+   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+  --> $DIR/union-suggest-field.rs:17:15
+   |
+LL |     let w = u.principial;
+   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+  --> $DIR/union-suggest-field.rs:21:15
+   |
+LL |     let y = u.calculate;
+   |               ^^^^^^^^^ method, not a field
+   |
+help: use parentheses to call the method
+   |
+LL |     let y = u.calculate();
+   |                        ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
index 8a7ac81724040cd4d2d2279a3a43abf24a10ed96..6134e91f31e49023b341abb7d32f99fda2b4eb43 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 use std::fmt;
 
index be8062f6276fd8a90a92e7c9a9410da927c76355..1a3b32d55f321cb161db870eb28fbf64afcfd6bb 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 union U {
     a: (u8, u8),
diff --git a/src/test/ui/union/union-unsafe.mir.stderr b/src/test/ui/union/union-unsafe.mir.stderr
new file mode 100644 (file)
index 0000000..84a7eb2
--- /dev/null
@@ -0,0 +1,91 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:34:5
+   |
+LL |     *(u.p) = 13;
+   |     ^^^^^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:39:5
+   |
+LL |     u.a = (RefCell::new(0), 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:40:5
+   |
+LL |     u.a.0 = RefCell::new(0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:47:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:53:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:61:13
+   |
+LL |     let a = u1.a;
+   |             ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:64:14
+   |
+LL |     let U1 { a } = u1;
+   |              ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:65:20
+   |
+LL |     if let U1 { a: 12 } = u1 {}
+   |                    ^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:70:6
+   |
+LL |     *u2.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:74:6
+   |
+LL |     *u3.a = 1;
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:78:6
+   |
+LL |     *u3.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
index 6adf0ac59b93ce518c60660290803fdcab1aa93e..e8414903d548fbd80e8e6efdbbaa3ff54694e041 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
 #![feature(untagged_unions)]
 use std::mem::ManuallyDrop;
 use std::cell::RefCell;
@@ -32,8 +35,9 @@ fn deref_union_field(mut u: URef) {
 }
 
 fn assign_noncopy_union_field(mut u: URefCell) {
-    u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping
-    u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping
+    // FIXME(thir-unsafeck)
+    u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping
+    u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping
     u.a.1 = 1; // OK
 }
 
diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.stderr
deleted file mode 100644 (file)
index a25c091..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:31:5
-   |
-LL |     *(u.p) = 13;
-   |     ^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:35:5
-   |
-LL |     u.a = (RefCell::new(0), 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
-   |
-   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
-
-error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:36:5
-   |
-LL |     u.a.0 = RefCell::new(0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
-   |
-   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:43:6
-   |
-LL |     *u3.a = T::default();
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:49:6
-   |
-LL |     *u3.a = T::default();
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:57:13
-   |
-LL |     let a = u1.a;
-   |             ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:60:14
-   |
-LL |     let U1 { a } = u1;
-   |              ^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:61:20
-   |
-LL |     if let U1 { a: 12 } = u1 {}
-   |                    ^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:66:6
-   |
-LL |     *u2.a = String::from("new");
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:70:6
-   |
-LL |     *u3.a = 1;
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:74:6
-   |
-LL |     *u3.a = String::from("new");
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error: aborting due to 11 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr
new file mode 100644 (file)
index 0000000..51f1987
--- /dev/null
@@ -0,0 +1,75 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:34:6
+   |
+LL |     *(u.p) = 13;
+   |      ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:47:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:53:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:61:13
+   |
+LL |     let a = u1.a;
+   |             ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:64:14
+   |
+LL |     let U1 { a } = u1;
+   |              ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:65:20
+   |
+LL |     if let U1 { a: 12 } = u1 {}
+   |                    ^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:70:6
+   |
+LL |     *u2.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:74:6
+   |
+LL |     *u3.a = 1;
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:78:6
+   |
+LL |     *u3.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/union/union-unsized.mirunsafeck.stderr b/src/test/ui/union/union-unsized.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..86a13c1
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:7:8
+   |
+LL |     a: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     a: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     a: Box<str>,
+   |        ^^^^   ^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:15:8
+   |
+LL |     b: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     b: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     b: Box<str>,
+   |        ^^^^   ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 16f2a73d42570a70f21de7107addbb6390a7d83d..e9792f527dc71ef672c44e51a1a9b1a6a8fe0bcb 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(untagged_unions)]
 
 union U {
diff --git a/src/test/ui/union/union-unsized.stderr b/src/test/ui/union/union-unsized.stderr
deleted file mode 100644 (file)
index 454580d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/union-unsized.rs:4:8
-   |
-LL |     a: str,
-   |        ^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `str`
-   = note: no field of a union may have a dynamically sized type
-   = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
-   |
-LL |     a: &str,
-   |        ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     a: Box<str>,
-   |        ^^^^   ^
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/union-unsized.rs:12:8
-   |
-LL |     b: str,
-   |        ^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `str`
-   = note: no field of a union may have a dynamically sized type
-   = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
-   |
-LL |     b: &str,
-   |        ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     b: Box<str>,
-   |        ^^^^   ^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-unsized.thirunsafeck.stderr b/src/test/ui/union/union-unsized.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..86a13c1
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:7:8
+   |
+LL |     a: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     a: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     a: Box<str>,
+   |        ^^^^   ^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:15:8
+   |
+LL |     b: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     b: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     b: Box<str>,
+   |        ^^^^   ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..2062fb7
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0740`.
index e3c63a6d5b5a2e7ad447a3ff7bb7a8d3e794e4fa..96c293418b62951fc548d7ef00872fe8bb348e52 100644 (file)
@@ -1,4 +1,6 @@
-#![feature(untagged_unions)]
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 union U {
diff --git a/src/test/ui/union/union-with-drop-fields.stderr b/src/test/ui/union/union-with-drop-fields.stderr
deleted file mode 100644 (file)
index 0e77279..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/union-with-drop-fields.rs:9:5
-   |
-LL |     a: String,
-   |     ^^^^^^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/union-with-drop-fields.rs:9:5
-   |
-LL |     a: String,
-   |     ^^^^^^^^^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/union-with-drop-fields.rs:17:5
-   |
-LL |     a: S,
-   |     ^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/union-with-drop-fields.rs:17:5
-   |
-LL |     a: S,
-   |     ^^^^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/union-with-drop-fields.rs:22:5
-   |
-LL |     a: T,
-   |     ^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/union-with-drop-fields.rs:22:5
-   |
-LL |     a: T,
-   |     ^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0740`.
diff --git a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..2062fb7
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0740`.
diff --git a/src/test/ui/unsafe/access_union_field.mir.stderr b/src/test/ui/unsafe/access_union_field.mir.stderr
new file mode 100644 (file)
index 0000000..98bc407
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:13:13
+   |
+LL |     let a = foo.bar;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:14:13
+   |
+LL |     let b = foo.baz;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/access_union_field.rs b/src/test/ui/unsafe/access_union_field.rs
new file mode 100644 (file)
index 0000000..5c4e695
--- /dev/null
@@ -0,0 +1,15 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(unused_variables)]
+
+union Foo {
+    bar: i8,
+    baz: u8,
+}
+
+fn main() {
+    let foo = Foo { bar: 5 };
+    let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block
+    let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block
+}
diff --git a/src/test/ui/unsafe/access_union_field.thir.stderr b/src/test/ui/unsafe/access_union_field.thir.stderr
new file mode 100644 (file)
index 0000000..98bc407
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:13:13
+   |
+LL |     let a = foo.bar;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:14:13
+   |
+LL |     let b = foo.baz;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union.mir.stderr b/src/test/ui/unsafe/union.mir.stderr
new file mode 100644 (file)
index 0000000..f7bd411
--- /dev/null
@@ -0,0 +1,16 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/union.rs:61:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+   = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union.rs:66:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs
new file mode 100644 (file)
index 0000000..0130fa6
--- /dev/null
@@ -0,0 +1,80 @@
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(untagged_unions)]
+
+union Foo {
+    bar: i8,
+    zst: (),
+    pizza: Pizza,
+}
+
+struct Pizza {
+    topping: Option<PizzaTopping>
+}
+
+#[allow(dead_code)]
+enum PizzaTopping {
+    Cheese,
+    Pineapple,
+}
+
+struct FooHolder {
+    inner_foo: Foo
+}
+
+fn do_nothing(_x: &mut Foo) {}
+
+pub fn main() {
+    let mut foo = Foo { bar: 5 };
+    do_nothing(&mut foo);
+    foo.bar = 6;
+    unsafe { foo.bar += 1; }
+    assert_eq!(unsafe { foo.bar }, 7);
+    unsafe {
+        let Foo { bar: inner } = foo;
+        assert_eq!(inner, 7);
+    }
+    let foo = if let true = true { foo } else { foo };
+
+    unsafe {
+        match foo {
+            Foo { bar: _a } => {},
+        }
+    }
+    unsafe {
+        match foo {
+            Foo {
+                pizza: Pizza {
+                    topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None
+                }
+            } => {},
+        }
+    }
+    // binding to wildcard is okay
+    match foo {
+        Foo { bar: _ } => {},
+    }
+    let Foo { bar: _ } = foo;
+    // MIR unsafeck incorrectly thinks that it is safe to do these
+    unsafe { //[mir]~ WARNING
+        match foo {
+            Foo { zst: () } => {},
+        }
+    }
+    unsafe { //[mir]~ WARNING
+        match foo {
+            Foo { pizza: Pizza { .. } } => {},
+        }
+    }
+    let foo = Foo { bar: 5 };
+    let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo };
+
+    let (_foo2, _random) = (foo, 42);
+
+    let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } };
+    foo_holder.inner_foo.bar = 4;
+    assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4);
+    drop(foo_holder);
+}
diff --git a/src/test/ui/unsafe/union_access_through_block.rs b/src/test/ui/unsafe/union_access_through_block.rs
new file mode 100644 (file)
index 0000000..e4c0976
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+pub struct Foo { a: bool }
+
+pub union Bar {
+    a: Foo,
+    b: u32,
+}
+pub fn baz(mut bar: Bar) {
+    unsafe {
+        { bar.a }.a = true;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/union_destructure.mir.stderr b/src/test/ui/unsafe/union_destructure.mir.stderr
new file mode 100644 (file)
index 0000000..818f5ce
--- /dev/null
@@ -0,0 +1,16 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/union_destructure.rs:35:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+   = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union_destructure.rs:41:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/unsafe/union_destructure.rs b/src/test/ui/unsafe/union_destructure.rs
new file mode 100644 (file)
index 0000000..6c88344
--- /dev/null
@@ -0,0 +1,51 @@
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+#[allow(dead_code)]
+struct Pie {
+    slices: u8,
+    size: u8,
+}
+
+union Foo {
+    #[allow(dead_code)]
+    bar: i8,
+    baz: Pie
+}
+
+fn main() {
+    let u = Foo { bar: 5 };
+    let (Some(Foo { bar: _ }) | None) = Some(u);
+    let u = Foo { bar: 6 };
+    let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u);
+    unsafe {
+        let u = Foo { bar: 7 };
+        let (Foo { bar } | Foo { bar }) = u;
+        assert_eq!(bar, 7)
+    }
+    let u = Foo { bar: 8 };
+    match Some(u) {
+        Some(Foo { bar: _ }) => 3,
+        None => 4,
+    };
+
+    let u = Foo { bar: 9 };
+    unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+        match u {
+            Foo { baz: Pie { .. } } => {},
+        };
+    }
+    let u = Foo { bar: 10 };
+    unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+        match u {
+            Foo { baz: Pie { slices: _, size: _ } } => {},
+        };
+    }
+
+    let u = Foo { bar: 11 };
+    match u {
+        Foo { baz: _ } => {},
+    };
+}
diff --git a/src/test/ui/unsafe/union_wild_or_wild.rs b/src/test/ui/unsafe/union_wild_or_wild.rs
new file mode 100644 (file)
index 0000000..52a0a7a
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+union X { a: i8 }
+
+fn main() {
+    let x = X { a: 5 };
+    match x {
+        X { a: _ | _ } => {},
+    }
+}
index 7d4dc8c9343f1c5af01b1dba7e98c68ed5597d84..cfa8eb3cad04b13d7103f3fe9d201d9512b08ff2 100644 (file)
@@ -1,13 +1,30 @@
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-// ignore-riscv64 stdcall isn't supported
+// gate-test-c_unwind
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
 
 // Test that the "stdcall-unwind" ABI is feature-gated, and cannot be used when
 // the `c_unwind` feature gate is not used.
 
-extern "stdcall-unwind" fn f() {}
-//~^ ERROR stdcall-unwind ABI is experimental and subject to change [E0658]
+extern "stdcall-unwind" fn fu() {} //~ ERROR stdcall-unwind ABI is experimental
 
-fn main() {
-    f();
+trait T {
+    extern "stdcall-unwind" fn mu(); //~ ERROR stdcall-unwind ABI is experimental
+    extern "stdcall-unwind" fn dmu() {} //~ ERROR stdcall-unwind ABI is experimental
 }
+
+struct S;
+impl T for S {
+    extern "stdcall-unwind" fn mu() {} //~ ERROR stdcall-unwind ABI is experimental
+}
+
+impl S {
+    extern "stdcall-unwind" fn imu() {} //~ ERROR stdcall-unwind ABI is experimental
+}
+
+type TAU = extern "stdcall-unwind" fn(); //~ ERROR stdcall-unwind ABI is experimental
+
+extern "stdcall-unwind" {} //~ ERROR stdcall-unwind ABI is experimental
index e3d569f464f8791abcf46fd2d2e33edbb461d93c..c2cce0e1193cd81eb8449bbd878057a7dd097772 100644 (file)
@@ -1,12 +1,66 @@
 error[E0658]: stdcall-unwind ABI is experimental and subject to change
-  --> $DIR/feature-gate-stdcall-unwind.rs:8:8
+  --> $DIR/feature-gate-stdcall-unwind.rs:12:8
    |
-LL | extern "stdcall-unwind" fn f() {}
+LL | extern "stdcall-unwind" fn fu() {}
    |        ^^^^^^^^^^^^^^^^
    |
    = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
    = help: add `#![feature(c_unwind)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-stdcall-unwind.rs:15:12
+   |
+LL |     extern "stdcall-unwind" fn mu();
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-stdcall-unwind.rs:16:12
+   |
+LL |     extern "stdcall-unwind" fn dmu() {}
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-stdcall-unwind.rs:21:12
+   |
+LL |     extern "stdcall-unwind" fn mu() {}
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-stdcall-unwind.rs:25:12
+   |
+LL |     extern "stdcall-unwind" fn imu() {}
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-stdcall-unwind.rs:28:19
+   |
+LL | type TAU = extern "stdcall-unwind" fn();
+   |                   ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-stdcall-unwind.rs:30:8
+   |
+LL | extern "stdcall-unwind" {}
+   |        ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 2f4cefccc19672314f1e6e207daadd1fb5572824..0a323e50fcf26015dfe4b7e881d40b83928d2896 100644 (file)
@@ -1,13 +1,39 @@
-// ignore-arm thiscall isn't supported
-// ignore-aarch64 thiscall isn't supported
-// ignore-riscv64 thiscall isn't supported
+// gate-test-abi_thiscall
+// gate-test-c_unwind
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
 
 // Test that the "thiscall-unwind" ABI is feature-gated, and cannot be used when
 // the `c_unwind` feature gate is not used.
 
-extern "thiscall-unwind" fn f() {}
-//~^ ERROR thiscall-unwind ABI is experimental and subject to change [E0658]
+extern "thiscall-unwind" fn fu() {} //~ ERROR thiscall-unwind ABI is experimental
+extern "thiscall" fn f() {} //~ ERROR thiscall is experimental
 
-fn main() {
-    f();
+trait T {
+    extern "thiscall" fn m(); //~ ERROR thiscall is experimental
+    extern "thiscall-unwind" fn mu(); //~ ERROR thiscall-unwind ABI is experimental
+
+    extern "thiscall" fn dm() {} //~ ERROR thiscall is experimental
+    extern "thiscall-unwind" fn dmu() {} //~ ERROR thiscall-unwind ABI is experimental
+}
+
+struct S;
+impl T for S {
+    extern "thiscall" fn m() {} //~ ERROR thiscall is experimental
+    extern "thiscall-unwind" fn mu() {} //~ ERROR thiscall-unwind ABI is experimental
 }
+
+impl S {
+    extern "thiscall" fn im() {} //~ ERROR thiscall is experimental
+    extern "thiscall-unwind" fn imu() {} //~ ERROR thiscall-unwind ABI is experimental
+}
+
+type TA = extern "thiscall" fn(); //~ ERROR thiscall is experimental
+type TAU = extern "thiscall-unwind" fn(); //~ ERROR thiscall-unwind ABI is experimental
+
+extern "thiscall" {} //~ ERROR thiscall is experimental
+extern "thiscall-unwind" {} //~ ERROR thiscall-unwind ABI is experimental
index b103bb8d565850ff422bbb958762082459587b11..9ca00a55cd85ba824c02054f0ffbb8bf198b52e1 100644 (file)
 error[E0658]: thiscall-unwind ABI is experimental and subject to change
-  --> $DIR/feature-gate-thiscall-unwind.rs:8:8
+  --> $DIR/feature-gate-thiscall-unwind.rs:13:8
    |
-LL | extern "thiscall-unwind" fn f() {}
+LL | extern "thiscall-unwind" fn fu() {}
    |        ^^^^^^^^^^^^^^^^^
    |
    = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
    = help: add `#![feature(c_unwind)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:14:8
+   |
+LL | extern "thiscall" fn f() {}
+   |        ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:17:12
+   |
+LL |     extern "thiscall" fn m();
+   |            ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:18:12
+   |
+LL |     extern "thiscall-unwind" fn mu();
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:20:12
+   |
+LL |     extern "thiscall" fn dm() {}
+   |            ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:21:12
+   |
+LL |     extern "thiscall-unwind" fn dmu() {}
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:26:12
+   |
+LL |     extern "thiscall" fn m() {}
+   |            ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:27:12
+   |
+LL |     extern "thiscall-unwind" fn mu() {}
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:31:12
+   |
+LL |     extern "thiscall" fn im() {}
+   |            ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:32:12
+   |
+LL |     extern "thiscall-unwind" fn imu() {}
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:35:18
+   |
+LL | type TA = extern "thiscall" fn();
+   |                  ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:36:19
+   |
+LL | type TAU = extern "thiscall-unwind" fn();
+   |                   ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:38:8
+   |
+LL | extern "thiscall" {}
+   |        ^^^^^^^^^^
+   |
+   = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+  --> $DIR/feature-gate-thiscall-unwind.rs:39:8
+   |
+LL | extern "thiscall-unwind" {}
+   |        ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+   = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index f3a8070323879ec8e9d1fb765ac47df1a74c3cb2..421614057c577771c457fc6e129f071ed68e2de3 100644 (file)
@@ -592,7 +592,7 @@ Released 2021-02-11
 
 * Previously deprecated [`str_to_string`] and [`string_to_string`] have been un-deprecated
   as `restriction` lints [#6333](https://github.com/rust-lang/rust-clippy/pull/6333)
-* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panic`
+* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panics`
   [#6351](https://github.com/rust-lang/rust-clippy/pull/6351)
 * Move [`map_err_ignore`] to `restriction`
   [#6416](https://github.com/rust-lang/rust-clippy/pull/6416)
index 4e164d33a0512b5ef15a909c82f52247520876df..d6e3e92fc5eb6b76caf1c6575cfd889f7f4d2d07 100644 (file)
@@ -26,6 +26,7 @@
 use rustc_span::{sym, FileName, Pos};
 use std::io;
 use std::ops::Range;
+use std::thread;
 use url::Url;
 
 declare_clippy_lint! {
@@ -584,10 +585,10 @@ fn get_current_span(spans: &[(usize, Span)], idx: usize) -> (usize, Span) {
 }
 
 fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
-    fn has_needless_main(code: &str, edition: Edition) -> bool {
+    fn has_needless_main(code: String, edition: Edition) -> bool {
         rustc_driver::catch_fatal_errors(|| {
-            rustc_span::with_session_globals(edition, || {
-                let filename = FileName::anon_source_code(code);
+            rustc_span::create_session_globals_then(edition, || {
+                let filename = FileName::anon_source_code(&code);
 
                 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
                 let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
@@ -649,7 +650,10 @@ fn has_needless_main(code: &str, edition: Edition) -> bool {
         .unwrap_or_default()
     }
 
-    if has_needless_main(text, edition) {
+    // Because of the global session, we need to create a new session in a different thread with
+    // the edition we need.
+    let text = text.to_owned();
+    if thread::spawn(move || has_needless_main(text, edition)).join().expect("thread::spawn failed") {
         span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
     }
 }
index e0325738466bec902564ee0c4138862bfd4365d5..c29b3e7c74c2c113fd85fbd0893d52ab4aad2f30 100644 (file)
@@ -2171,7 +2171,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
     ls.register_renamed("clippy::unused_label", "unused_labels");
     ls.register_renamed("clippy::drop_bounds", "drop_bounds");
     ls.register_renamed("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr");
-    ls.register_renamed("clippy::panic_params", "non_fmt_panic");
+    ls.register_renamed("clippy::panic_params", "non_fmt_panics");
     ls.register_renamed("clippy::unknown_clippy_lints", "unknown_lints");
 }
 
index 804c04fe1b838894926bdfe1d1b54713b70667b4..7cfce2e61cca59e153cf08caf4c40fb08880cd99 100644 (file)
@@ -662,14 +662,7 @@ fn in_attributes_expansion(expr: &Expr<'_>) -> bool {
     use rustc_span::hygiene::MacroKind;
     if expr.span.from_expansion() {
         let data = expr.span.ctxt().outer_expn_data();
-        matches!(
-            data.kind,
-            ExpnKind::Macro {
-                kind: MacroKind::Attr,
-                name: _,
-                proc_macro: _
-            }
-        )
+        matches!(data.kind, ExpnKind::Macro(MacroKind::Attr, _))
     } else {
         false
     }
index 0454214651683afbfae4ede5b4afdcbeedf0f0aa..85257f3113cb774adc43f326707c0182b1eac616 100644 (file)
@@ -8,12 +8,7 @@
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if expr.span.from_expansion() {
         if let Some(callee) = expr.span.source_callee() {
-            if let ExpnKind::Macro {
-                kind: MacroKind::Bang,
-                name: symbol,
-                proc_macro: _,
-            } = callee.kind
-            {
+            if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
                 if let ExprKind::Binary(ref cmp, left, _) = expr.kind {
                     let op = cmp.node;
                     if op.is_comparison() && cx.typeck_results().expr_ty(left).is_unit() {
index 217a1f4dded545ecc20c75c84c080f8e0c78c732..2f10472180f5e4f56b00177a927df3aab30dec31 100644 (file)
@@ -953,12 +953,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
             let data = span.ctxt().outer_expn_data();
             let new_span = data.call_site;
 
-            if let ExpnKind::Macro {
-                kind: MacroKind::Bang,
-                name: mac_name,
-                proc_macro: _,
-            } = data.kind
-            {
+            if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
                 if mac_name.as_str() == name {
                     return Some(new_span);
                 }
@@ -986,12 +981,7 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
         let data = span.ctxt().outer_expn_data();
         let new_span = data.call_site;
 
-        if let ExpnKind::Macro {
-            kind: MacroKind::Bang,
-            name: mac_name,
-            proc_macro: _,
-        } = data.kind
-        {
+        if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
             if mac_name.as_str() == name {
                 return Some(new_span);
             }
index 2808fc35e2a1b2d01215e8837b3679fa59fa3177..8857e77d8983d34d0e9505c8a00097731275c5d5 100644 (file)
@@ -15,6 +15,7 @@
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::infer::InferCtxtExt;
 
 use crate::{match_def_path, must_use_attr};
 
@@ -112,6 +113,7 @@ pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<
 }
 
 /// Checks whether a type implements a trait.
+/// The function returns false in case the type contains an inference variable.
 /// See also `get_trait_def_id`.
 pub fn implements_trait<'tcx>(
     cx: &LateContext<'tcx>,
@@ -119,18 +121,18 @@ pub fn implements_trait<'tcx>(
     trait_id: DefId,
     ty_params: &[GenericArg<'tcx>],
 ) -> bool {
-    // Do not check on infer_types to avoid panic in evaluate_obligation.
-    if ty.has_infer_types() {
-        return false;
-    }
+    // Clippy shouldn't have infer types
+    assert!(!ty.needs_infer());
+
     let ty = cx.tcx.erase_regions(ty);
     if ty.has_escaping_bound_vars() {
         return false;
     }
     let ty_params = cx.tcx.mk_substs(ty_params.iter());
-    cx.tcx
-        .type_implements_trait((trait_id, ty, ty_params, cx.param_env))
+    cx.tcx.infer_ctxt().enter(|infcx|
+        infcx.type_implements_trait(trait_id, ty, ty_params, cx.param_env)
         .must_apply_modulo_regions()
+    )
 }
 
 /// Checks whether this type implements `Drop`.
index 6617ca183a8cb2cbd37c0fa60c3b4fe1a1eb23cc..2180f848d62cd256f7538d100d6cf5c634398ec2 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
 
 macro_rules! assert_const {
     ($len:expr) => {
index 0af6b500115dc1ae828261e7f38baa9cf6281ebf..c0002e5354310ab9bcc32c2f0753e534c02ff9eb 100644 (file)
@@ -60,11 +60,11 @@ error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cs
 LL | #[warn(clippy::temporary_cstring_as_ptr)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
-error: lint `clippy::panic_params` has been renamed to `non_fmt_panic`
+error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
   --> $DIR/deprecated.rs:11:8
    |
 LL | #[warn(clippy::panic_params)]
-   |        ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panic`
+   |        ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
   --> $DIR/deprecated.rs:12:8
index 49731b2d7dc04f858b8393b96d70c076a4fd57b9..181ce0f2c3de5808f483e95249f9bd70c29ab577 100644 (file)
@@ -1133,8 +1133,8 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
 
         let rust_type_regexes = vec![
             "^(alloc::([a-z_]+::)+)String$",
-            "^&str$",
-            "^&\\[.+\\]$",
+            "^&(mut )?str$",
+            "^&(mut )?\\[.+\\]$",
             "^(std::ffi::([a-z_]+::)+)OsString$",
             "^(alloc::([a-z_]+::)+)Vec<.+>$",
             "^(alloc::([a-z_]+::)+)VecDeque<.+>$",
index e3700136aca8aa186bc0e239228a0d95acaab39f..01a3fc812b2087cbad4ef95e08524e1d0cf38060 100644 (file)
@@ -284,7 +284,8 @@ fn parse_args() -> (OutputFormat, PathBuf) {
 fn main() {
     rustc_driver::init_env_logger("RUST_LOG");
     let (format, dst) = parse_args();
-    let result = rustc_span::with_default_session_globals(move || main_with_result(format, &dst));
+    let result =
+        rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst));
     if let Err(e) = result {
         panic!("{}", e.to_string());
     }
index ea54a351e03b5339f52e8e130d7cb415a9da7831..e5c7f1257123801d48a39812cfb003967342ee6d 100644 (file)
@@ -467,7 +467,9 @@ fn lint_name(line: &str) -> Result<String, &'static str> {
                 return Err("lint name should end with comma");
             }
             let name = &name[..name.len() - 1];
-            if !name.chars().all(|ch| ch.is_uppercase() || ch == '_') || name.is_empty() {
+            if !name.chars().all(|ch| ch.is_uppercase() || ch.is_ascii_digit() || ch == '_')
+                || name.is_empty()
+            {
                 return Err("lint name did not have expected format");
             }
             Ok(name.to_lowercase().to_string())
index 15e81a94b1aff99f7c38151d6976757ee0ed0097..b06130762ed75f52da7c22979c61c597ced667c6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 15e81a94b1aff99f7c38151d6976757ee0ed0097
+Subproject commit b06130762ed75f52da7c22979c61c597ced667c6
index 1fa82adfdca502a13f4dd952f9a50574870f5b7b..e5c1c8cf2fcfae3e15c8bcf5256e84cad3bd3436 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 1fa82adfdca502a13f4dd952f9a50574870f5b7b
+Subproject commit e5c1c8cf2fcfae3e15c8bcf5256e84cad3bd3436
index b69ecdc5cb8ae2985065bf54c5872d0528f1ac69..e0403574eebc1d73a361c70e144fe67920c4a40a 100644 (file)
@@ -34,7 +34,7 @@ pub(crate) fn format_input_inner(
             return Err(ErrorKind::VersionMismatch);
         }
 
-        rustc_span::with_session_globals(self.config.edition().into(), || {
+        rustc_span::create_session_if_not_set_then(self.config.edition().into(), |_| {
             if self.config.disable_all_formatting() {
                 // When the input is from stdin, echo back the input.
                 if let Input::Text(ref buf) = input {
index ea587210b4f4e786fa485fd24863b274bcb642dd..799d685ce5ca1844e698cd49f4d0726a93da3dd1 100644 (file)
     "libloading",
     "log",
     "mach",
+    "memchr",
     "object",
     "regalloc",
     "region",
index 63fbee34bd6e405eb7981e0db0993d8579b8909f..53c75a463390d75b8be1e66b9a9dd2f9b31e91df 100644 (file)
@@ -11,7 +11,7 @@
 // A few of those error codes can't be tested but all the others can and *should* be tested!
 const EXEMPTED_FROM_TEST: &[&str] = &[
     "E0227", "E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0464", "E0465", "E0476",
-    "E0482", "E0514", "E0519", "E0523", "E0554", "E0570", "E0640", "E0717", "E0729",
+    "E0482", "E0514", "E0519", "E0523", "E0554", "E0640", "E0717", "E0729",
 ];
 
 // Some error codes don't have any tests apparently...